以太坊智能合約有各種各樣的用例,但到目前爲止,從你的iOS應用程序中調用它們非常困難。不過如果使用以太坊iOS開發套件和EtherKit,這種情況會改善很多,你可以立即開始使用。在本教程結束時,你將能夠調用其ABI(應用程序二進制接口)中定義的任何公共合約函數。
對於這個項目,我們將使用Xcode 10.0和ContractCodegen 0.1。我們還建議使用iOS MVVM項目模板,但爲了使本教程簡單,我們將使用正常的iOS項目結構。
首先,我們將創建一個新的iOS項目,並將其稱爲EthereumContracts
。在這裏下載我們的示例合約abi.json
文件。下載成功後,將文件拖到Xcode項目中。你的Xcode項目現在應該如下所示:
安裝ContractCodegen
在本教程的下一部分中,我們將從我們的以太坊iOS開發工具包下載ContractCodegen。爲此,我將使用Cocoapods,它將自動下載必要的依賴項,但還有其他方法可用,在以太坊iOS開發套件Github中有描述。
在項目根目錄中創建Podfile並插入以下代碼:
platform :ios, '10.3' project 'EthereumContracts' inhibit_all_warnings! use_frameworks! target 'EthereumContracts' do pod 'ContractCodegen', '~> x.y.z' end
打開終端並粘貼此命令:
pod install
當此命令完成時,關閉我們的EthereumContracts
項目並在Finder中打開EthereumContracts.xcworkspace
。
很好!現在讓我們生成Swift代碼以與我們的智能合約進行交互。
生成Swift代碼
首先,確保你在項目根目錄中。如果你已經在了,我們可以非常簡單地生成我們的Swift代碼,只需使用以下命令:
Pods/ContractCodegen/ContractCodegen/bin/contractgen HelloContract EthereumContracts/abi.json -x EthereumContracts.xcodeproj -o EthereumContracts/GeneraredContracts
當命令詢問你使用哪個選項時,非常簡單,只使用一個,即第一個選項。
瞧,如果你收到“Code generation: ok”的消息,你已經爲以太坊智能合約創建了第一個Swift代碼。
你現在應該看到一組Generated Contracts
和其中的兩個文件:SharedContract.swift
和HelloContract.swift
。第一個幫助我們調用合約文件中定義的各個方法(在我們的例子中是HelloContract
),並且對於所有生成的合約都是相同的。
有趣的那部分實際上是使用我們生成的代碼來調用我們自己的合約。
創建密鑰
導航到我們的ViewController
並在文件頂部寫:
import EtherKit
現在我們需要聲明我們將使用哪個geth網絡與智能合約進行通信。爲了做到這一點,讓我們在ViewController
中定義一個屬性:
let query = EtherQuery(URL(string: "https://rinkeby.infura.io/v3/9f1a1e0782ab40c8b39fe189615714d0")!, connectionMode: .http)
你可以使用任何所需的URL,你在字符串中看到的只是我們爲你提供的URL。
然後我們將繼續在viewDidLoad()
函數中創建我們的密鑰:
let walletStorage = KeychainStorageStrategy(identifier: "cz.ackee.etherkit.example") HDKey.Private.create( with: MnemonicStorageStrategy(walletStorage), mnemonic: sentence, network: .main, path: [ KeyPathNode(at: 44, hardened: true), KeyPathNode(at: 60, hardened: true), KeyPathNode(at: 0, hardened: true), KeyPathNode(at: 0), ] )
這很簡單,對吧。
首先,我們創建助記句,這句話用於創建私鑰和公鑰以及地址。要創建你自己的,這是很顯然的,你可以使用從此處下載的MyCrypto錢包示例。然後,HDKey.Private.create
創建我們的主節點,從該節點派生所有其他公鑰和私鑰以及地址。
如你所見,編譯器現在向我們顯示此警告:
當我們查看HDKey.Private.create
的函數時,我們可以看到它有一個完成參數Result<HDKey.Private, EtherKitError>) -> Void
。這是因爲創建我們的帳戶是異步操作,因此我們需要在此功能完成後開始調用我們的智能合約。
爲了使我們的代碼簡單易讀,我們將創建一個新函數,我們將從中調用我們的合約:
private func testContract() { }
現在我們從前面提到的完成中調用這個函數,如下所示:
HDKey.Private.create( with: MnemonicStorageStrategy(walletStorage), mnemonic: sentence, network: .main, path: [ KeyPathNode(at: 44, hardened: true), KeyPathNode(at: 60, hardened: true), KeyPathNode(at: 0, hardened: true), KeyPathNode(at: 0), ] ) { [weak self] _ in self?.testContract() }
請耐心等待,我們越來越接近最終結果。
調用我們的合約
前往我們之前創建的testContract()
函數。首先,我們需要使用關鍵路徑找到存儲在存儲中的一個創建的密鑰(下面的代碼只是通過樹到達特定位置):
let walletStorage = KeychainStorageStrategy(identifier: "cz.ackee.etherkit.example") let key = HDKey.Private(walletStorage, network: .rinkeby, path: [ KeyPathNode(at: 44, hardened: true), KeyPathNode(at: 60, hardened: true), KeyPathNode(at: 0, hardened: true), KeyPathNode(at: 1), ])
到代碼的最後部分,我們差不多了!
let testContractAddress = try! Address(describing: "0xb8f016F3529b198b4a06574f3E9BDc04948ad852") query.helloContract(at: testContractAddress).testString(greetString: "Greetings!").send(using: key, amount: Wei(10)).startWithResult { result in switch result { case .success(let hash): print(hash) print("Test greetings succeeded!") case .failure(let error): print(error) print("Test greetings failed.") } }
好的,讓我們看看這是做什麼的。
testContractAddress
指向我們創建的智能合約地址。要使用你自己的字符串替換它,請使用所需的十六進制代碼。
其餘的代碼就是調用本身。我認爲這是非常自我描述的,但我們將運行它,只是爲了清楚。
我們找到所有的HelloContract
函數,並聲明我們要使用query.helloContract(at:testContractAddress)
的合約地址。然後我們選擇其中一個函數,在這個例子中我選擇了函數testString
,它將String
作爲輸入(這個值將由我們的智能合約使用)。之後,我們通過send
發送此數據。密鑰值是我們之前在存儲中找到的密鑰值,amount
聲明瞭我們想要發送多少以太坊(正如你所看到的,我們爲UInt256
使用了typealias
以獲得更好的可讀性)。然後send
返回SignalProducer
。如果你不知道那是什麼意思,請在ReactiveSwift文檔中閱讀更多相關信息。
如果調用成功,則返回Hash
類型。這只是我們發送的交易的哈希值。
讓我們看看它是否有效!
嘗試運行應用程序,如果你在輸出中看到一個哈希和一個字符串“Test greetings succeeded!”,你剛剛使用Swift調用了你的第一個智能合約函數!
還有一件事應該說。智能功能有兩種類型:應付款和非應付款。這種差異由生成的智能合約代碼處理,因此你在代碼中將在這兩種類型之間看到的唯一區別是,當調用非應付函數時,將省略參數金額(因爲不應發送以太坊)。很簡單,是吧?
如果想查看整個項目,可以在此處下載。
=====================================================================