[英]How to interact with Smart Contract deployed on Blockchain from Swift app
這是我第一次使用智能合約,我的目標是創建一個移動應用程序,該應用程序可以通過調用方法與它進行交互以保存或檢索數據。 出於這個原因,我使用 Remix 創建了一個非常簡單的合約,並且我還在 Rinkeby 測試網上進行了部署。
contract Storage {
uint256 number;
function store(uint256 num) public {
number = num;
}
function retrieve() public view returns (uint256){
return number;
}
}
然后我構建了一個 SwiftUI 應用程序,它有一個按鈕。 當我按下這個按鈕時,我想調用store方法並保存一些int數。 例如數字 9。因此我創建了一個名為write的函數,如下所示:
let myInt = 9
func write() {
let web3 = Web3.InfuraRinkebyWeb3(accessToken: "https://rinkeby.infura.io/v3/a146daf63d93490995823f0910f50118")
let walletAddress = EthereumAddress("0xc65943Fae5a554e7DCF916F8828a73E5f7b1bDCd")! // Your wallet address
let contractMethod = "store" // Contract method you want to write
let contractABI = contractABIString // Contract ABI
let contractAddress = EthereumAddress("0x2826C42354FE5B816c7E21AD9e3B395Ced512C0C")!
let abiVersion = 2 // Contract ABI version
let parameters = [myInt] as [AnyObject]
let extraData: Data = Data() // Extra data for contract method
let contract = web3.contract(contractABI, at: contractAddress, abiVersion: abiVersion)!
var options = TransactionOptions.defaultOptions
options.from = walletAddress
options.gasPrice = .automatic
options.gasLimit = .automatic
do {
contract.write(
contractMethod,
parameters: parameters,
extraData: extraData,
transactionOptions: options)
} catch {
print("error:", error)
}
不幸的是,當我運行這段代碼時,什么都沒有發生。 我沒有收到任何錯誤,但是當我刷新合同時,我看到數字 9 沒有通過。
我正在使用 web3swift 庫, https://github.com/skywinder/web3swift/tree/master#send-erc-20-token 。 根據文檔,它應該沒問題,但它不工作,因此我非常感謝一些助手讓它工作或一些我可以看看的示例項目,因為我也找不到任何東西。
我發現了其他一些使用 JS 的項目,我看到那里的人使用他們的私鑰,也許我也需要它,但是由於它沒有在文檔中顯示,我不知道如何使用它。
智能合約交互需要幾個初始化步驟:
假設你已經有了一個 Metamask 錢包。 另外,您需要有一個單獨的文件,其中包含要與之交互的 smartContract 的 ABI。 它是一個數組,將它放在 Swift.String 中更容易。(我不會向你展示這一步)
struct Wallet {
let address: String
let data: Data
let name: String
let isHD: Bool
}
class SmartContractInteraction {
var wallet: Wallet!
var keystoreManager: KeystoreManager!
var web3: web3!
init() {
wallet = initializeWallet()
keystoreManager = getKeyStoreManager()
web3 = initializeweb3()
}
private func initializeWallet() -> Wallet? {
let password = "PasswordMetamask"
let key = "AccountPrivateKey"
let formattedKey = key.trimmingCharacters(in: .whitespacesAndNewlines)
let dataKey = Data.fromHex(formattedKey)!
let name = "Account 1"
do {
let keystore = try EthereumKeystoreV3(privateKey: dataKey, password: password)!
let keyData = try JSONEncoder().encode(keystore.keystoreParams)
let address = keystore.addresses!.first!.address
return Wallet(address: address, data: keyData, name: name, isHD: false)
} catch {
print("wallet init failed: \(error)")
return nil
}
}
private func getKeyStoreManager() -> KeystoreManager {
let data = wallet.data
let keystoreManager: KeystoreManager
if wallet.isHD {
let keystore = BIP32Keystore(data)!
keystoreManager = KeystoreManager([keystore])
} else {
let keystore = EthereumKeystoreV3(data)!
keystoreManager = KeystoreManager([keystore])
}
return keystoreManager
}
private func initializeweb3() -> web3 {
let endpoint = "https://ropsten.infura.io/v3/....."
let web3 = web3swift.web3(provider: Web3HttpProvider(URL(string: endpoint)!)!)
web3.addKeystoreManager(keystoreManager)
return web3
}
func callSmartContract() {
let value: String = "1"
let walletAddress = EthereumAddress(wallet.address)!
let contractAddress = EthereumAddress("SmartContractAddress")!
let contractMethod = "store"
let contractABI = MyContractABI
let abiVersion = 2
let parameters = [9] as [AnyObject]
let extraData: Data = Data()
let contract = web3.contract(contractABI, at: contractAddress, abiVersion: abiVersion)!
let amount = Web3.Utils.parseToBigUInt(value, units: .wei)
var options = TransactionOptions.defaultOptions
options.value = amount
options.from = walletAddress
options.gasPrice = .automatic
options.gasLimit = .automatic
let tx = contract.write(
contractMethod,
parameters: parameters,
extraData: extraData,
transactionOptions: options)!
do {
let password = "MetamaskPassword"
let result = try tx.send(password: password)
print(result)
} catch {
print("Token Balance failed: \(error)")
}
}
}
像這樣應該可以工作,我認為在 smartContract 調用方法中傳遞 value/option.value 是不必要的,但由於我沒有你的 ABI,我寧願不從它對我的工作方式中刪除任何內容。 另外,我不確定您傳遞的號碼的類型。 如果沒有這樣的作品,請隨意編輯:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.