iOS 部署智慧合約

語歌發表於2018-07-12

廢話

因為專案業務原因,需要在新的專案中部署以太坊的智慧合約,關於這方面安卓方面貌似走在了前面。 web3j 的存在實在是喜人,而 iOS版本也是有的,功能貌似沒有那麼強大,對付平常的區塊鏈互動是足夠的了。但是iOS這個他沒有仔細的說明,我研究了一下其實部署起來挺簡單. 年紀大了搞過的東西很容易忘記,於是在這裡記錄一下.一來自己以後也可以回顧,二來為有需要的人略盡綿薄之力

語歌部落格

使用 web3swift 部署以太坊智慧合約

1.配置服務

a. IP地址

配置以太坊的伺服器地址:
我這裡是本地IP地址

struct Api {

    static let host = "http://192.168.6.66:6666"
    
    static func map(path: String) -> String {
        
        return host + path
    }
    
    static var chainUrl: String {
        return map(path: "")
    }
}
複製程式碼

b. abiString

部署合約會需要

public let abiString = "[{"constant":true,"inputs":[],"name":"getFlagData","outputs":[{"name":"data","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"string"}],"name":"setFlagData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]"
複製程式碼

c. byteCode

這個是一串很長的東西,合約生產的。沒有的記得找寫合約的要.

我這裡的例子:

public let BINARY = "606060409081526003805460a060020a61ffff021916905560006004558051908101604052600981527f4c696e67546f6b656e0000000000000000000000000000000000000000000000602082015260059080516100619291602001906100cf565b5060408051908101604052600481527f4c494e4700000000000000000000000000000000000000000000000000000000602082015260069080516100a99291602001906100cf565b50601260075560038054600160a060020a03191633600160a060020a031617905561016a565b82805460018160011615610100020316600290049若干省略號
複製程式碼

d. 整合 pod

pod `web3swift`, `~> 0.8.0`
複製程式碼

2.部署前奏

a. 建立賬戶,web3swift 的示例中有,同學可以仔細研究研究,我這裡就簡單過。

上程式碼:

class YYGKey {
    
    var key_password = "BANKEXFOUNDATION"
    
    var storeManager: KeystoreManager? {
        return keyStoreManager()
    }
    
    var keyAddress: EthereumKeystoreV3? {
        return addressManage()
    }
    
    convenience init(password: String) {
        self.init()
        self.key_password = password
    }

    
    func addressManage() -> EthereumKeystoreV3? {
        guard let userDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { return nil }
        let storeManager = KeystoreManager.managerForPath(userDir + "/keystore")
        if let manage = storeManager, let address = manage.addresses {
            return address.isEmpty ? creatAddress(dir: userDir) : getAddress(manage: manage)
        }
        return nil
    }
    
    func creatAddress(dir: String) -> EthereumKeystoreV3? {
        let ks = try! EthereumKeystoreV3(password: "BANKEXFOUNDATION")
        if let ks_ = ks {
            let keydata = try! JSONEncoder().encode(ks_.keystoreParams)
            FileManager.default.createFile(atPath: dir + "/keystore"+"/key.json", contents: keydata, attributes: nil)
        }
        return ks
    }
    
    func getAddress(manage: KeystoreManager) -> EthereumKeystoreV3? {
        if let address = manage.addresses, let first = address.first {
            return manage.walletForAddress(first) as? EthereumKeystoreV3
        }
        return nil
    }
    
    func keyStoreManager() -> KeystoreManager? {
        guard let userDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { return nil }
        return KeystoreManager.managerForPath(userDir + "/keystore")
    }
}
複製程式碼

b. 連線到部署的伺服器

class YYG {
    
    var chain: web3? {
        guard let url = URL(string: Api.chainUrl), let web = Web3.new(url) else { return nil }
        return web
    }
    
    static let yyg = YYG()
    
    private init() { }
}
複製程式碼

3.開始部署

需要的資料

  • EthereumKeystoreV3
  • EthereumAddress
  • web3
  • byteCode
  • web3contract
  • Web3Options
  • TransactionIntermediate
  • KeystoreManager

上程式碼:

struct YYGOperate {
    
    typealias result = Result<[String : String], Web3Error>
    typealias res = [String : String]
    
    func contractsResult(message: @escaping (Bool,res?) -> Void) {
        if let resul = smartContracts() {
            switch resul {
            case .success(let res):
                DispatchQueue.main.async {
                    message(true, res)
                }
            case .failure(let error):
                message(false, nil)
                print(error)
            }
        } else {
            message(false, nil)
        }
    }
    
    private func smartContracts() -> result? {
        guard let manage = YYGKey().addressManage(),let addresss = manage.addresses,let address = addresss.first, let chain = YYG.yyg.chain else { return nil }
        chain.provider.network = nil
        chain.addKeystoreManager(YYGKey().keyStoreManager())
        
        guard let contract = chain.contract(abiString, at: nil, abiVersion: 2), let byteCode = Data.fromHex(BINARY) else { return nil }
        var options = Web3Options.defaultOptions()
        options.from = address
        options.gasLimit = BigUInt(3000000)
        let inter = contract.deploy(bytecode: byteCode, options: options)
        guard let intermediate = inter else { return nil }
        return intermediate.send(password: "BANKEXFOUNDATION", options: options)
    }
}
複製程式碼

3.執行

YYGOperate().contractsResult { state, res in
    if state { printLogDebug(res) }
}
複製程式碼

結果:

Transaction
Nonce: 10
Gas price: 5000000000
Gas limit: 1111340
To: 0x
Value: 0
Data: 0x606060409081526003805460a060020a61ffff02191690556090810183818151815260200191508051906020019080838360005b8381101561017657808201518382015260200161015e565b50、5260200160405180910390a35050505050565b6000828201610acc82fd76404b5c55184a2e555312d3353bcb43e75666dd36d0af562b0c220029a165627a7a72305820f3efa245dad6ee48cc6d771a54067fb6e3b17b0caba5ecd4eed13aca2b1c00960029
v: 28
r: 79879464740714101996923170089344479265591202785750775462035438111705924396692
s: 39143622105442894879914151031821436277241889279036648521816051027427579390397
Intrinsic chainID: nil
Infered chainID: nil
sender: Optional("0x9E40Fb081777c232aBafc256165772572c057F95")
hash: Optional("0xcc16c3a245e4fd27b85e53b8cb6d0ac64028b60e61ca3de938e896e95202bde3")

複製程式碼

授人以魚不如授人以漁

學習資料

相關文章