
Web3.swift é uma biblioteca Swift para assinar transações e interagir com contratos inteligentes na rede Ethereum.
Ele permite que você se conecte a um nó Geth ou Erigon Ethereum (como o ChainNodes) para enviar transações e ler valores de contratos inteligentes sem a necessidade de escrever suas próprias implementações dos protocolos.
O Web3.swift suporta iOS, MacOS, TVOS, WatchOS e Linux com o Swift Package Manager.
Verifique o uso abaixo ou examine os testes de repositórios.
Já existem alguma biblioteca Web3 por aí escrita em Swift. Conhecemos seus pontos fortes e fracos e, para o nosso caso de uso, eles simplesmente não funcionaram.
Web3.swift foi construído com modularidade, portabilidade, velocidade e eficiência em mente.
Ok, obrigado pelas palavras -chave. Mas o que isso realmente significa?
Web3.swift foi construído para ser modular. Se você instalar/usar o produto básico Web3 SPM, terá acesso às funções mais básicas, como assinatura de transações e interação com um servidor RPC HTTP.
Se você deseja adicionar suporte ao IPC RPC ou outra coisa, pode criar uma biblioteca que depende do Web3 e implementa essa funcionalidade exata. Mais sobre isso mais tarde.
Se você deseja usar extensões Promisekit para as chamadas do Web3, use o produto Promisekit SPM fornecido ou criar o seu.
Se você deseja analisar convenientemente o JSON ABIS para contratos inteligentes da Ethereum, pode usar o produto ABI ABI ABISING SPM.
Por fim, se você deseja adicionar funcionalidade ao Web3.swift , que ainda não foi fornecido, não precisará esperar até que ela seja mesclada e liberada em uma versão da versão. Você pode estender/atualizar a funcionalidade de extensão/atualização simples, pois nossas APIs são feitas para serem muito abertas para alterações.
Por exemplo, se você deseja adicionar um método Web3 que ainda não foi fornecido pelo Web3.swift (suportaremos apenas métodos suportados pela Infura), você deve adicionar apenas algumas linhas de código (dependendo dos parâmetros de entrada e saída do método). A adição de suporte do IPC RPC seria apenas implementar um protocolo e atender solicitações.
Como você pode ver, tudo é possível com Web3.swift .
Uma das principais razões pelas quais começamos a trabalhar neste projeto é porque queríamos usá -lo com o Swift Package Manager em diferentes plataformas.
Por esse motivo, Web3.swift está disponível no Swift Package Manager no iOS, macOS, TVOS, WatchOS e Linux.
NOTA: Para o SPM, estamos testando apenas iOS, macOS e distribuições de Linux oficialmente apoiadas (atualmente o Ubuntu 16.04 e 20.04), mas devem ser compatíveis com todos os pequenos sistemas Endianos que são capazes de compilar o compilador Swift, a fundação e o GLIBC.
Tentamos tornar essa biblioteca o mais rápido possível enquanto tentamos fornecer uma API que aumenta seu fluxo de trabalho de desenvolvimento, de modo que você possa se concentrar na criação de ótimos DAPPs, em vez de nos preocupar com os detalhes da implementação.
Todas as nossas APIs são seguras de threads e projetadas para serem usadas em aplicativos altamente simultâneos.
O Web3 é compatível com o Swift Package Manager V5 (Swift 5 e acima). Basta adicioná -lo às dependências no seu Package.swift .
dependencies: [
. package ( url : " https://github.com/Boilertalk/Web3.swift.git " , from : " 0.6.0 " )
]E depois adicione -o às suas dependências de destino:
targets: [
. target (
name : " MyProject " ,
dependencies : [
. product ( name : " Web3 " , package : " Web3.swift " ) ,
. product ( name : " Web3PromiseKit " , package : " Web3.swift " ) ,
. product ( name : " Web3ContractABI " , package : " Web3.swift " ) ,
]
) ,
. testTarget (
name : " MyProjectTests " ,
dependencies : [ " MyProject " ] )
]NOTA:
Web3PromiseKiteWeb3ContractABIsão opcionais e você só precisa colocá -los em suas dependências de destino (e importá -las posteriores) se quiser usá -las.
Após a instalação, você pode importar Web3 nos seus arquivos .swift .
import Web3
// Optional
import Web3PromiseKit
import Web3ContractABIDevido a uma decisão interna, paramos de apoiar quaisquer gerentes de pacotes que não sejam o SPM, começando na versão 0.5.0.
Para elaborar um pouco esta decisão: com o Xcode 11 e o Swift 5.1, chegamos a um ponto com o Swift Package Manager, onde começou a tornar lentamente os gerentes de pacotes irrelevantes. Você já pode carregar todas as suas dependências no projeto Xcode com o Swift Package Manager.
Com mais atualizações, tornou -se ainda mais prevalente. Cocoapods e mantenedores de cartago perderam o interesse em seu projeto e pararam de mantê -lo. Existem muitos problemas não resolvidos, muitos problemas, especialmente para desenvolvedores de bibliotecas com cocoapods.
Tanto aborrecimento sem ganho real. Os usuários já podem colocar dependências que suportam o SPM em seu projeto Xcode. Então, por que se preocupar?
A resposta é simples. Alguns ainda usam o Xcode <11 e alguns desenvolvedores de bibliotecas dependem do Web3 em suas próprias vagens/cartas.
A decisão foi difícil e levou algum tempo. Mas depois de ver que a última versão era muito estável e usada em muitos aplicativos de produção, decidimos começar com esse movimento agora.
O Xcode 10 já tem mais de 2 anos. A maioria dos projetos já atualizados, aqueles que não tiveram um problema muito maior do que o Web3.Swift não fazendo atualizações para Cocoapods ...
Os proprietários de bibliotecas, dependendo do Web3.Swift, são incentivados a abandonar o suporte de Cocoapods e Cartago também.
SPM é o futuro. Para todos os usuários de Cocoapods e Cartago que o usam porque muitas bibliotecas ainda não mudaram para o SPM: você ainda pode adicionar o Web3.Swift como um produto SPM no seu .xcworkspace ou .xcodeproj e manter todas as suas outras dependências dentro do Cocoapods/Cartago. Mas ainda assim. Incentivamos você a mudar com o maior número possível de dependências para o SPM. Melhor mais cedo ou mais tarde. Veja a próxima seção sobre como fazer isso.
Usando o Xcode 11 ou posterior (para iOS, macOS ou outras plataformas da Apple), você pode adicionar pacotes SPM muito fáceis.
No Xcode, selecione seu projeto, no suspensão Selecione o projeto, não um único alvo, nas guias Selecione Swift Packages .
Em seguida, você pode clicar no ícone + e colocar o URL neste repositório (https://github.com/boilertalk/web3.swift).
Agora você pode selecionar todos os produtos e clicar em Avançar até que a dependência fosse adicionada.
É isso. Se você pressionar suas alterações, mesmo o seu IC não causará problemas. Não há aborrecimentos com repositórios de especificações desatualizados, sem problemas com alguns erros estranhos do vinculador que ocorrem apenas às vezes/com algumas dependências.
Se você precisar de mais orientações, junte -se ao nosso grupo Telegram e nós o ajudaremos. https://t.me/web3_swift
Com Web3.swift você pode usar um nó Ethereum em um servidor para se comunicar com o Ethereum.
Você pode enviar transações assinadas, ler dados do contrato, chamar funções de contrato e muito mais.
A classe base para todos os métodos disponíveis é Web3 . Você pode, por exemplo, instanciá -lo com um provedor HTTP:
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " ) Todos os métodos web3_ estão disponíveis diretamente na estrutura Web3 . Os métodos net_ estão disponíveis na estrutura net na estrutura web3 . Os métodos eth_ estão disponíveis sob a estrutura eth na estrutura web3 .
Por favor, veja os exemplos abaixo
Nota: Para que os exemplos funcionem, você precisa importar o Web3 e Promisekit primeiro
Retorna a versão atual do cliente.
Parâmetros
nenhum
Retorna
String - a versão atual do cliente
firstly {
web3 . clientVersion ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} Retorna o ID de rede atual.
Parâmetros
nenhum
Retorna
String - o ID de rede atual
firstly {
web3 . net . version ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} Retorna o número de pares atualmente conectados ao cliente.
Parâmetros
nenhum
Retorna
EthereumQuantity - Bigint do número de pares conectados.
firstly {
web3 . net . peerCount ( )
} . done { ethereumQuantity in
print ( ethereumQuantity . quantity )
} . catch { error in
print ( " Error " )
} Cria uma nova transação de chamada de mensagem ou uma criação de contrato para transações assinadas.
Parâmetros
EthereumTransaction : a transação assinadaRetorna
EthereumData , 32 bytes - o hash da transação ou o hash zero se a transação ainda não estiver disponível
Para enviar algum ETH, você primeiro precisa obter a contagem atual de transações do remetente (nonce), criar a transação, assine -a e enviá -la.
let privateKey = try ! EthereumPrivateKey ( hexPrivateKey : " 0xa26da69ed1df3ba4bb2a231d506b711eace012f1bd2571dfbfff9650b03375af " )
firstly {
web3 . eth . getTransactionCount ( address : privateKey . address , block : . latest )
} . then { nonce in
let tx = try EthereumTransaction (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
gas : 21000 ,
to : EthereumAddress ( hex : " 0xC0866A1a0ed41e1aa75c932cA3c55fad847fd90D " , eip55 : true ) ,
value : EthereumQuantity ( quantity : 1 . eth )
)
return try tx . sign ( with : privateKey , chainId : 1 ) . promise
} . then { tx in
web3 . eth . sendRawTransaction ( transaction : tx )
} . done { hash in
print ( hash )
} . catch { error in
print ( error )
} firstly {
web3 . eth . getBlockTransactionCountByNumber ( block : . block ( 5397389 ) )
} . done { count in
print ( count ) // 88
} . catch { error in
print ( error )
} Para mais exemplos, lidos nos casos de teste, a Struct Web3 ou a documentação oficial do Ethereum JSON RPC.
Estamos fornecendo um módulo opcional para interação com contratos inteligentes. Para usá -lo, você deve adicionar Web3ContractABI às suas dependências de destino no seu PODFILE (para SPM). Verifique as instruções de instalação primeiro.
Estamos fornecendo duas opções diferentes para criar interfaces de contrato de ABI no Swift. Você define suas funções e eventos manualmente (ou usa uma de nossas interfaces fornecidas como ERC20 ou ERC721). Ou você os analisa da representação JSON ABI, como no web3.js.
Contratos estáticos são classes que implementam StaticContract . Eles fornecem um conjunto de funções e eventos que desejam usar do contrato inteligente original. Confira nossos contratos estáticos fornecidos como ponto de partida (ERC20 ou ERC721).
Nossa interface estática ERC20 é chamada de GenericERC20Contract , o contrato ERC721 é chamado de GenericERC721Contract . Ambos podem ser subclassificados para adicionar mais funções para contratos personalizados.
Com esses tipos de StaticContract você pode criar e usar seu contrato, como no exemplo a seguir (estamos usando o PromiseKit novamente em nossos exemplos).
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " )
let contractAddress = try EthereumAddress ( hex : " 0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 " , eip55 : true )
let contract = web3 . eth . Contract ( type : GenericERC20Contract . self , address : contractAddress )
// Get balance of some address
firstly {
try contract . balanceOf ( address : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) ) . call ( )
} . done { outputs in
print ( outputs [ " _balance " ] as? BigUInt )
} . catch { error in
print ( error )
}
// Send some tokens to another address (locally signing the transaction)
let myPrivateKey = try EthereumPrivateKey ( hexPrivateKey : " ... " )
firstly {
web3 . eth . getTransactionCount ( address : myPrivateKey . address , block : . latest )
} . then { nonce in
try contract . transfer ( to : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) , value : 100000 ) . createTransaction (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 100000 ,
from : myPrivateKey . address ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
) ! . sign ( with : myPrivateKey ) . promise
} . then { tx in
web3 . eth . sendRawTransaction ( transaction : tx )
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}
// Send some tokens to another address (signing will be done by the node)
let myAddress = try EthereumAddress ( hex : " 0x1f04ef7263804fafb839f0d04e2b5a6a1a57dc60 " , eip55 : true )
firstly {
web3 . eth . getTransactionCount ( address : myAddress , block : . latest )
} . then { nonce in
try contract . transfer ( to : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) , value : 100000 ) . send (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 150000 ,
from : myAddress ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
)
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}Ao criar suas próprias interfaces, você pode interagir com qualquer contrato inteligente!
Se você tiver acesso ao JSON ABI de um contrato inteligente ou não deseja criar um modelo estático, poderá usar nossa API de contrato dinâmico para analisar a sequência JSON em um contrato utilizável durante o tempo de execução . Veja o exemplo abaixo.
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " )
let contractAddress = try EthereumAddress ( hex : " 0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 " , eip55 : true )
let contractJsonABI = " <your contract ABI as a JSON string> " . data ( using : . utf8 ) !
// You can optionally pass an abiKey param if the actual abi is nested and not the top level element of the json
let contract = try web3 . eth . Contract ( json : contractJsonABI , abiKey : nil , address : contractAddress )
print ( contract . methods . count )
// Get balance of some address
firstly {
try contract [ " balanceOf " ] ! ( EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) ) . call ( )
} . done { outputs in
print ( outputs [ " _balance " ] as? BigUInt )
} . catch { error in
print ( error )
}
// Send some tokens to another address (locally signing the transaction)
let myPrivateKey = try EthereumPrivateKey ( hexPrivateKey : " ... " )
guard let transaction = contract [ " transfer " ] ? ( EthereumAddress . testAddress , BigUInt ( 100000 ) ) . createTransaction (
nonce : 0 ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 150000 ,
from : myPrivateKey . address ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
) ) else {
return
}
let signedTx = try transaction . sign ( with : myPrivateKey )
firstly {
web3 . eth . sendRawTransaction ( transaction : signedTx )
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}Usando esta API, você pode interagir com qualquer contrato inteligente na rede Ethereum!
Para mais exemplos, incluindo criação de contratos (chamada de construtor), consulte nossos testes.
Se você estiver recebendo esse erro ao analisar seu ABI de um JSON, pode ser porque seu contrato tem uma função de fallback. Para resolvê -lo, remova o fragmento do seu ABI que possui as informações sobre a função de fallback. A parte que você deve remover pode ficar assim:
{
"payable": false,
"stateMutability": "nonpayable",
"type": "fallback"
},
Até chegarmos à versão 1.0.0, nossa API está sujeita a mudanças de interrupção entre saltos de versão menor. Isso é para garantir que possamos nos concentrar em fornecer a melhor implementação enquanto estamos em desenvolvimento pesado, em vez de tentar manter algo que é preterido.
Dito isto, tentaremos minimizar as mudanças de quebra. Certamente não haverá muitos.
Os caras incríveis no BoilerTalk ⚗️
... e membros ainda mais incríveis da comunidade?
Confira a lista dos colaboradores para obter uma lista completa.
O Web3 está disponível sob a licença do MIT. Consulte o arquivo de licença para obter mais informações.