
Web3.Swiftは、取引に署名し、Ethereumネットワークでスマートコントラクトと対話するための迅速なライブラリです。
これにより、GethまたはErigon Ethereumノード(ChainNodesなど)に接続して、プロトコルの実装を作成する必要なく、トランザクションを送信し、スマートコントラクトから値を読み取ることができます。
Web3.Swiftは、SwiftパッケージマネージャーとともにiOS、MacOS、TVOS、WatchOS、Linuxをサポートしています。
以下の使用法を確認するか、リポジトリテストをご覧ください。
Swiftで書かれたWeb3ライブラリがすでにいくつかあります。私たちは彼らの長所と短所を知っており、私たちのユースケースでは、彼らはうまくいきませんでした。
Web3.swift 、モジュール性、移植性、速度、効率を念頭に置いて構築されました。
OK、流行語をありがとう。しかし、これは実際にはどういう意味ですか?
Web3.swiftモジュラーになるように構築されました。 Basic Web3 SPM製品をインストール/使用すると、HTTP RPCサーバーとの署名や対話などの最も基本的な機能にアクセスできます。
IPC RPCなどのサポートを追加する場合は、 Web3に依存してこの正確な機能を実装するライブラリを簡単に作成できます。それについては後で詳しく説明します。
Web3呼び出しにPromiseKit拡張機能を使用する場合は、提供されているPromiseKit SPM製品を使用するか、独自の製品を作成できます。
EthereumスマートコントラクトのためにJSON Abisを便利に解析したい場合は、提供されたABI解析SPM製品を使用できます。
最後に、まだ提供されていないWeb3.swiftに機能を追加する場合は、バージョンバンプでマージされてリリースされるまで待つ必要はありません。 APIは変更に対して非常にオープンになるため、自分のアプリ内で単純な拡張/更新機能を使用できます。
たとえば、 Web3.swiftによってまだ提供されていないWeb3メソッドを追加する場合(Infuraサポートされたメソッドのみをサポートします)、約3行のコードのみを追加する必要があります(メソッドの入力と出力パラメーターに応じて)。 IPC RPCサポートを追加するには、プロトコルと応答リクエストのみが実装されます。
ご覧のとおり、 Web3.swiftですべてが可能です。
このプロジェクトに取り組み始めた主な理由の1つは、さまざまなプラットフォームでSwiftパッケージマネージャーと一緒に使用したかったためです。
そのため、 Web3.swift 、iOS、MacOS、TVOS、WatchOS、LinuxのSwiftパッケージマネージャーを通じて利用できます。
注:SPMの場合、iOS、MACOS、および公式にサポートされているLinuxディストリビューション(現在はUbuntu 16.04および20.04)のみをテストしていますが、Swiftコンパイラ、ファンデーション、GLIBCをコンパイルできるすべてのリトルエンディアンシステムと互換性があるはずです。
私たちは、実装の詳細を心配するのではなく、素晴らしいダップを構築することに集中できるように、開発ワークフローを増やすAPIを提供しようとしながら、このライブラリをできるだけ速く作成しようとします。
すべてのAPIはスレッドセーフであり、非常に同時アプリケーションで使用されるように設計されています。
Web3は、Swift Package Manager V5(Swift 5以降)と互換性があります。 Package.swiftの依存関係に追加するだけです。
dependencies: [
. package ( url : " https://github.com/Boilertalk/Web3.swift.git " , from : " 0.6.0 " )
]次に、ターゲットの依存関係に追加します。
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 " ] )
]注:
Web3PromiseKitとWeb3ContractABIはオプションであり、それらを使用する場合は、それらをターゲット依存関係に配置する必要があります(そして後でインポートする)。
インストール後、 .swiftファイルにWeb3をインポートできます。
import Web3
// Optional
import Web3PromiseKit
import Web3ContractABI内部決定のため、バージョン0.5.0から始まるSPM以外のパッケージマネージャーのサポートを停止しました。
この決定について少し詳しく説明するために:Xcode 11とSwift 5.1を使用すると、Swift Package Managerでポイントに到達し、他のパッケージマネージャーにゆっくりと無関係になり始めました。 Swift Package Managerを使用して、Xcodeプロジェクトにすべての依存関係を既にロードできます。
より多くの更新により、さらに一般的になりました。 CocoapodsとCarthageメンテナーは、プロジェクトへの関心を失い、維持を停止しました。多くの未解決の問題があります。特にココアポッドを持つ図書館開発者にとって多くの問題です。
本当の利益のためにそんなに手間がかかります。ユーザーは、XcodeプロジェクトにSPMをサポートする依存関係を既に配置できます。では、なぜわざわざなのですか?
答えは簡単です。 Xcode <11を使用している人もいれば、一部のライブラリ開発者は自分のポッド/カルセージでWeb3に依存しています。
決定は大変で、しばらく時間がかかりました。しかし、最後のバージョンが非常に安定しており、すでに多くの制作アプリで使用されていることを確認した後、この動きから始めることにしました。
Xcode 10はすでに2年以上前です。ほとんどのプロジェクトはすでにアップグレードされており、web3.swiftよりもはるかに大きな問題を抱えていなかったプロジェクトは、cocoapodsのアップデートを作成していません...
Web3.swiftに応じて図書館の所有者は、ココアポッドやカルタゴのサポートもドロップすることをお勧めします。
SPMは未来です。多くのライブラリがまだSPMに切り替えられなかったために使用するすべてのココアポッドとカルタゴユーザーについては、web3.swiftを.xcworkspaceまたは.xcodeprojに追加することができ、他のすべての依存関係をcocoapods/carthage内に保持できます。しかし、それでも。できるだけ多くの依存関係をSPMに切り替えることをお勧めします。遅かれ早かれ。これを行う方法の次のセクションを参照してください。
Xcode 11以降(iOS、MacO、またはその他のAppleプラットフォームの場合)を使用すると、SPMパッケージを非常に簡単に追加できます。
Xcodeで、プロジェクトを選択します。ドロップダウンから、単一のターゲットではなくプロジェクトを選択します。タブでSwift Packagesを選択します。
次に、 +アイコンをクリックして、このリポジトリ(https://github.com/boilertalk/web3.swift)にURLを入力できます。
これで、すべての製品を選択して、依存関係が追加されるまで[次へ]をクリックできます。
それでおしまい。変更をプッシュすると、CIでさえ問題が発生しません。時代遅れのスペックリポジトリを備えた手間はなく、時々/依存関係がある場合にのみ発生する奇妙なリンカーエラーに問題はありません。
さらにガイダンスが必要な場合は、Telegram Groupに参加してください。 https://t.me/web3_swift
Web3.swiftを使用すると、サーバー上のEthereumノードを使用してEthereumと通信できます。
署名されたトランザクションを送信したり、契約データを読み取ったり、契約関数を呼び出したりすることができます。
利用可能なすべての方法の基本クラスはWeb3です。たとえば、HTTPプロバイダーでインスタンス化できます。
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " )すべてのweb3_メソッドは、 Web3 structから直接入手できます。 net_メソッドは、 web3 structのnet構造体で利用できます。 eth_メソッドは、 web3構造体のeth構造体で利用できます。
以下の例をご覧ください
注:動作する例については、最初にWeb3とPromiseKitをインポートする必要があります
現在のクライアントバージョンを返します。
パラメーター
なし
返品
String - 現在のクライアントバージョン
firstly {
web3 . clientVersion ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} 現在のネットワークIDを返します。
パラメーター
なし
返品
String - 現在のネットワークID
firstly {
web3 . net . version ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} 現在クライアントに接続されているピア数を返します。
パラメーター
なし
返品
EthereumQuantity -Connected Peersの数のBigint。
firstly {
web3 . net . peerCount ( )
} . done { ethereumQuantity in
print ( ethereumQuantity . quantity )
} . catch { error in
print ( " Error " )
} 署名されたトランザクションの新しいメッセージコールトランザクションまたは契約作成を作成します。
パラメーター
EthereumTransaction :署名されたトランザクション返品
EthereumData 、32バイト - トランザクションハッシュ、またはトランザクションがまだ利用できない場合はゼロハッシュ
いくつかのETHを送信するには、最初に送信者の現在のトランザクションカウント(NONCE)を取得し、トランザクションを作成し、署名してから送信する必要があります。
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 )
} その他の例については、テストケース、Web3 structまたは公式のEthereum JSON RPCドキュメントを読んでください。
スマートコントラクトとの相互作用のためのオプションのモジュールを提供しています。それを使用するには、Podfile(SPM用)のターゲット依存関係にWeb3ContractABIを追加する必要があります。最初にインストール手順を確認してください。
Swiftで契約ABIインターフェイスを作成するための2つの異なるオプションを提供しています。関数とイベントを手動で定義します(または、ERC20やERC721などの提供されたインターフェイスのいずれかを使用します)。または、Web3.jsのようにJSON ABIの表現からそれらを解析します。
静的契約は、 StaticContractを実装するクラスです。彼らは、元のスマートコントラクトから使用したい一連の機能とイベントを提供します。提供された静的契約を出発点としてチェックしてください(ERC20またはERC721)。
静的ERC20インターフェイスはGenericERC20Contractと呼ばれ、ERC721契約はGenericERC721Contractと呼ばれます。どちらもサブクラス化して、カスタム契約の関数を追加することができます。
これらのStaticContractタイプを使用すると、次の例のように契約を作成および使用できます(例ではPromiseKitを再度使用しています)。
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 )
}独自のインターフェイスを作成することにより、任意のスマートコントラクトと対話できます!
スマートコントラクトのJSON ABIのみにアクセスできる場合、または静的テンプレートを作成したくない場合は、ダイナミックコントラクトAPIを使用して、実行時間中にJSON文字列を使用可能な契約に解析できます。以下の例を参照してください。
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 )
}このAPIを使用すると、Ethereumネットワークのスマートコントラクトと対話できます!
契約作成(コンストラクターの呼び出し)などのその他の例については、テストをご覧ください。
JSONからABIを解析するときにこのエラーが発生している場合、契約にフォールバック機能があるためかもしれません。それを解決するには、フォールバック関数に関する情報があるABIの断片を削除します。削除する必要がある部分は次のようになるかもしれません:
{
"payable": false,
"stateMutability": "nonpayable",
"type": "fallback"
},
バージョン1.0.0に到達するまで、APIはマイナーバージョンジャンプ間の変化の影響を受けます。これは、非推奨を維持しようとするのではなく、重い開発中に最高の実装を提供することに集中できるようにするためです。
そうは言っても、壊れた変化を最小限に抑えようとします。確かに多くのことはありません。
boilertalkの素晴らしい人たち⚗️
...そしてコミュニティのさらに素晴らしいメンバー?
完全なリストについては、貢献者リストをご覧ください。
Web3はMITライセンスの下で利用できます。詳細については、ライセンスファイルを参照してください。