
Web3.Swift es una biblioteca rápida para firmar transacciones e interactuar con contratos inteligentes en la red Ethereum.
Le permite conectarse a un nodo Geth o Erigon Ethereum (como los Nodes de Cadra) para enviar transacciones y leer valores de contratos inteligentes sin la necesidad de escribir sus propias implementaciones de los protocolos.
Web3.Swift es compatible con iOS, MacOS, Tvos, Watchos y Linux con Swift Package Manager.
Verifique el uso a continuación o mire a través de las pruebas de repositorios.
Ya hay alguna biblioteca Web3 escrita en Swift. Conocemos sus fortalezas y debilidades y para nuestro caso de uso simplemente no funcionaron.
Web3.swift se construyó con modularidad, portabilidad, velocidad y eficiencia en mente.
Ok, gracias por las palabras de moda. Pero, ¿qué significa esto realmente?
Web3.swift fue creado para ser modular. Si instala/usa el producto BASIC Web3 SPM, tiene acceso a las funciones más básicas como la firma de transacciones e interactúa con un servidor HTTP RPC.
Si desea agregar soporte para IPC RPC o algo más, puede simplificar una biblioteca que depende de Web3 e implementa esta funcionalidad exacta. Más sobre eso más tarde.
Si desea utilizar las extensiones de prometía para las llamadas de Web3, puede usar el producto PROMEME SPM PROMEDS PROMEDIO o crear el suyo propio.
Si desea analizar convenientemente JSON Abis para Ethereum Smart Contracts, puede usar el producto SPM de análisis ABI proporcionado.
Finalmente, si desea agregar funcionalidad a Web3.swift que aún no se proporciona, no tiene que esperar hasta que se fusione y se lance en un golpe de versión. Puede simple extender/actualizar la funcionalidad dentro de su propia aplicación, ya que nuestras API están hechas para estar muy abiertas para los cambios.
Por ejemplo, si desea agregar un método Web3 que aún no lo proporciona Web3.swift (solo admitiremos los métodos compatibles con Infura), solo tiene que agregar unas 3 líneas de código (dependiendo de los parámetros de entrada y salida del método). Agregar soporte RPC IPC solo implementaría un protocolo y solicitudes de respuesta.
Como puede ver, todo es posible con Web3.swift .
Una de las principales razones por las que comenzamos a trabajar en este proyecto es porque queríamos usarlo con Swift Package Manager en diferentes plataformas.
Debido a eso, Web3.swift está disponible a través de Swift Package Manager en iOS, MacOS, Tvos, Watchos y Linux.
Nota: Para SPM solo estamos probando iOS, MacOS y distribuciones de Linux compatibles oficialmente (actualmente Ubuntu 16.04 y 20.04), pero debe ser compatible con todos los pequeños sistemas endian que pueden compilar el compilador Swift, Foundation y GLIBC.
Tratamos de hacer que esta biblioteca lo sea lo más rápido posible al tratar de proporcionar una API que aumente su flujo de trabajo de desarrollo de manera que pueda concentrarse en construir excelentes dapps en lugar de preocuparse por los detalles de implementación.
Todas nuestras API son seguras y diseñadas para usarse en aplicaciones altamente concurrentes.
Web3 es compatible con Swift Package Manager V5 (Swift 5 y superior). Simplemente agréguelo a las dependencias en su Package.swift .
dependencies: [
. package ( url : " https://github.com/Boilertalk/Web3.swift.git " , from : " 0.6.0 " )
]Y luego agréguelo a sus dependencias objetivo:
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:
Web3PromiseKityWeb3ContractABIson opcionales y solo tiene que ponerlas en sus dependencias objetivo (y luego importarlas) si desea usarlas.
Después de la instalación, puede importar Web3 en sus archivos .swift .
import Web3
// Optional
import Web3PromiseKit
import Web3ContractABIDebido a una decisión interna, dejamos de apoyar a los administradores de paquetes que no sean SPM a partir de la versión 0.5.0.
Para elaborar un poco sobre esta decisión: con Xcode 11 y Swift 5.1, llegamos a un punto con Swift Package Manager, donde lentamente comenzó a hacer que otros administradores de paquetes sean irrelevantes. Ya puede cargar todas sus dependencias en el proyecto XCode con Swift Package Manager.
Con más actualizaciones se volvió aún más frecuente. Cocoapods y Carthage Mantenerse perdieron interés en su proyecto y dejaron de mantenerlo. Hay muchos problemas no resueltos, muchos problemas, especialmente para los desarrolladores de la biblioteca con cocoapods.
Tanta molestia sin ganancia real. Los usuarios ya pueden poner dependencias que admiten SPM en su proyecto XCode. Entonces, ¿por qué molestarse?
La respuesta es simple. Algunos todavía usan Xcode <11 y algunos desarrolladores de la biblioteca dependen de Web3 en sus propias vainas/cartas.
La decisión fue difícil y tomó algún tiempo. Pero después de ver que la última versión era muy estable y se usó en muchas aplicaciones de producción, decidimos comenzar con este movimiento ahora.
Xcode 10 ya tiene más de 2 años. La mayoría de los proyectos ya actualizados, los que no tenían un problema mucho mayor que Web3.swift no realizó actualizaciones para Cocoapods ...
Se alienta a los propietarios de bibliotecas que dependen de Web3.swift a que también suelte el soporte de Cocoapods y Cartago.
SPM es el futuro. Para todos los usuarios de Cocoapods y Carthage que lo usan porque muchas bibliotecas aún no cambiaron a SPM: aún puede agregar Web3.swift como un producto SPM en su .xcworkspace o .xcodeproj y mantener todas sus otras dependencias dentro de los cocoapods/Carthage. Pero aún así. Le recomendamos que cambie con tantas dependencias como sea posible a SPM. Mejor más temprano que tarde. Vea la siguiente sección sobre cómo hacer esto.
Usando Xcode 11 o posterior (para iOS, macOS u otras plataformas Apple) puede agregar paquetes SPM muy fáciles.
En XCode, seleccione su proyecto, en el menú desplegable Seleccione el proyecto, no un solo objetivo, en las pestañas seleccione Swift Packages .
Luego puede hacer clic en el icono + y poner en la URL a este repositorio (https://github.com/boilertalk/web3.swift).
Ahora puede seleccionar todos los productos y simplemente haga clic en Siguiente hasta que se agregó la dependencia.
Eso es todo. Si presiona sus cambios, incluso su CI no tendrá ningún problema. No hay molestias con repositorios de especificaciones obsoletas, sin problemas con algunos errores de enlazador extraños que solo ocurren a veces/con algunas dependencias.
Si necesita más orientación, únase a nuestro grupo Telegram y lo ayudaremos. https://t.me/web3_swift
Con Web3.swift puede usar un nodo Ethereum en un servidor para comunicarse con Ethereum.
Puede enviar transacciones firmadas, leer datos del contrato, llamar a las funciones del contrato de llamada y mucho más.
La clase base para todos los métodos disponibles es Web3 . Puede, por ejemplo, instanciarlo con un proveedor HTTP:
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " ) Todos los métodos web3_ están disponibles directamente desde la estructura Web3 . Los métodos net_ están disponibles bajo la estructura net en la estructura web3 . Los métodos eth_ están disponibles bajo la estructura eth en la estructura web3 .
Consulte los ejemplos a continuación
Nota: para que los ejemplos funcionen, debe importar Web3 y prometer primero
Devuelve la versión actual del cliente.
Parámetros
ninguno
Devolución
String : la versión actual del cliente
firstly {
web3 . clientVersion ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} Devuelve la ID de red actual.
Parámetros
ninguno
Devolución
String : la ID de red actual
firstly {
web3 . net . version ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} Devuelve el número de pares actualmente conectados al cliente.
Parámetros
ninguno
Devolución
EthereumQuantity - Bigint del número de pares conectados.
firstly {
web3 . net . peerCount ( )
} . done { ethereumQuantity in
print ( ethereumQuantity . quantity )
} . catch { error in
print ( " Error " )
} Crea una nueva transacción de llamadas de mensaje o una creación de contrato para transacciones firmadas.
Parámetros
EthereumTransaction : la transacción firmadaDevolución
EthereumData , 32 bytes: el hash de la transacción o el hash cero si la transacción aún no está disponible
Para enviar algo de ETH, primero debe obtener el recuento de transacciones actual del remitente (nonce), crear la transacción, firmarlo y luego enviarlo.
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 obtener más ejemplos, lea nuestros casos de prueba, la estructura Web3 o la documentación oficial de Ethereum JSON RPC.
Proporcionamos un módulo opcional para la interacción con contratos inteligentes. Para usarlo, debe agregar Web3ContractABI a sus dependencias objetivo en su podfile (para SPM). Asegúrese de revisar las instrucciones de instalación primero.
Estamos proporcionando dos opciones diferentes para crear interfaces ABI contractuales en Swift. O define sus funciones y eventos manualmente (o use una de nuestras interfaces proporcionadas como ERC20 o ERC721). O los analiza de la representación JSON ABI al igual que en Web3.js.
Los contratos estáticos son clases que implementan StaticContract . Proporcionan un conjunto de funciones y eventos que desean usar del contrato inteligente original. Consulte nuestros contratos estáticos proporcionados como punto de partida (ERC20 o ERC721).
Nuestra interfaz ERC20 estática se llama GenericERC20Contract , el contrato ERC721 se llama GenericERC721Contract . Ambos se pueden subclase para agregar más funciones para contratos personalizados.
Con esos tipos de StaticContract , puede crear y usar su contrato como en el siguiente ejemplo (estamos utilizando prometedor nuevamente en nuestros ejemplos).
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 )
}Al crear sus propias interfaces, ¡puede interactuar con cualquier contrato inteligente!
Si solo tiene acceso al JSON ABI de un contrato inteligente o no desea crear una plantilla estática, puede usar nuestra API de contrato dinámico para analizar la cadena JSON en un contrato utilizable durante el tiempo de ejecución . Vea el ejemplo a continuación.
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, puede interactuar con cualquier contrato inteligente en la red Ethereum!
Para obtener más ejemplos, incluida la creación de contratos (llamadas del constructor), consulte nuestras pruebas.
Si recibe este error al analizar su ABI de un JSON, puede deberse a que su contrato tiene una función de respaldo. Para resolverlo, elimine el fragmento de su ABI que tiene la información sobre la función de retroceso. La parte que debe eliminar puede verse así:
{
"payable": false,
"stateMutability": "nonpayable",
"type": "fallback"
},
Hasta que llegamos a la versión 1.0.0, nuestra API está sujeta a cambios de ruptura entre los saltos de versión menor. Esto es para asegurarnos de que podamos centrarnos en proporcionar la mejor implementación mientras estamos en un gran desarrollo en lugar de tratar de mantener algo en desuso.
Dicho esto, intentaremos minimizar los cambios de ruptura. Ciertamente no habrá muchos.
Los increíbles chicos de Boilertalk ⚗️
... ¿Y aún más miembros increíbles de la comunidad?
Consulte la lista de contribuyentes para obtener una lista completa.
Web3 está disponible bajo la licencia MIT. Consulte el archivo de licencia para obtener más información.