前言:什么是智能合约?

智能合约,是一段写在区块链上的代码,一旦某个事件触发合约中的条款,代码即自动执行。也就是说,满足条件就执行,不需要人为操控。

web3Swift

web3json数据Swift是一个纯粹json数据而快速以太坊Web3库 github.com/skywi源码精灵永久兑换码nder/w…

在使用之前,请先Cocoapproachapods集成web3swift

 pod 'web3swift' #web3智能合约

Web3SwiftUtils

  • 相信很多接触刚智能合约开发和合约API调用的iOSer会遇到很多问题或踩坑,本工具类主要实现了Etherum、B源码时代inance、Polygon链等智能合约常用业务调用及主要方jsonobject法封装;

主要方法调用

调用智能合约

  /// 操作智能合约
  /// - Parameters:
  ///  - method: 方法名称
  ///  - params: 参数
  ///  - config: options配置
  ///  - closure: tx结果信息
  private func callContractService(_ abiType: CSContractAbiType = .erc20, methodName: String, callType: CSContractCallType, params: [AnyObject] = [AnyObject](), config: CSContractConfig, closure: @escaping (CSContractTransResult)->Void) {
    if let object = config.modelToJSONObject() {
      print("Contract call config:(object)n")
      print("Contract call params:(params)n")
      print("Contract call rpc:(self.network.ipUrl)n")
    }
    let transResult = CSContractTransResult()
    // key
    guard let privateKey = config.privateKey else { return }
    let formattedKey = privateKey.trimmingCharacters(in: .whitespacesAndNewlines)
    let dataKey = Data.fromHex(formattedKey)!
    let keystore = try! EthereumKeystoreV3(privateKey: dataKey, password: password)
    let keystoreManager = KeystoreManager([keystore! as EthereumKeystoreV3])
    /// web3
    let endpoint = URL(string: contractURL)!
    guard let web333 = try? Web3.new(endpoint) else {
      return
    }
    web333.addKeystoreManager(keystoreManager)
    web3Manager = web333
    // 合约方法名称
    let contractMethod = methodName
    // ABI资源
    var contractABI = Web3.Utils.erc20ABI
    switch abiType {
    case .erc20:
      contractABI = Web3.Utils.erc20ABI
    default:
      let abiName = fetchAbiType(type: abiType)
      contractABI = String.fileContractABI(resName: abiName)
    }
    // 合约地址
    let ethContractAddress = EthereumAddress(config.contractAddress!)
    let abiVersion = 2 // Contract ABI version
    guard let contract = web333.contract(contractABI, at: ethContractAddress, abiVersion: abiVersion) else {
      return
    }
    var options = TransactionOptions.defaultOptions
    // 我的地址
    if let from = config.from, let walletAddress = EthereumAddress(from) {
      options.from = walletAddress
    }
    // 接收地址
    if let to = config.to, let toAddress = EthereumAddress(to) {
      options.to = toAddress
    }
    var decimals = BigUInt(18)
    // get the decimals manually
    if let callResult = try? contract.read("decimals", transactionOptions: options)?.call() {
      guard let dec = callResult["0"], let decTyped = dec as? BigUInt else {
        return
      }
      decimals = decTyped
    }
    let intDecimals = Int(decimals)
    if let amount = config.amount {
             options.value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals)
    }
    if let gasLimit = config.gasLimit {
      options.gasLimit = .manual(BigUInt("(gasLimit)")!)
    }else {
      options.gasLimit = .automatic
    }
    if let gasPrice = config.gasPrice {
      if let gwei = Web3.Utils.parseToBigUInt(gasPrice, units: .Gwei) {
        options.gasPrice = .manual(gwei)
      }else {
        options.gasPrice = .automatic
      }
    }
    else {
      options.gasPrice = .automatic
    }
    let extraData: Data = Data() // Extra data for contract method
    if (callType == .write) {
      guard let tx = contract.write(contractMethod,
                     parameters: params,
                     extraData: extraData,
                     transactionOptions: options) else {
        // callback
        closure(transResult)
        return
      }
      print("Transaction methodName:(methodName)n")
      print("Transaction description:(tx.transaction.description)n")
      if let result = try? tx.call() {
        transResult.callData = result
        print("Transaction callData:(result)")
        if let etherAddress = result["0"] as? EthereumAddress {
          print("Transaction _link:(etherAddress.address)")
          transResult.linkAddress = etherAddress.address
        }
      }
      txSendCallResult(tx, config: config) { result in
        transResult.transHash = result?.hash ?? ""
        transResult.transDesc = result?.transaction.description ?? ""
      }
    }else {
      guard let tx = contract.read(contractMethod,
                    parameters: params,
                    extraData: extraData,
                    transactionOptions: options) else {
        // callback
        closure(transResult)
        return
      }
      print("Transaction methodName:(methodName)n")
      print("Transaction description:(tx.transaction.description)n")
      if let result = try? tx.call() {
        transResult.callData = result
        if let tokenWei = result["0"] as? BigUInt {
          transResult.callStatus = tokenWei > 0
          transResult.approvedAmount = "(tokenWei)"
        }else if let status = result["0"] as? Bool {
          if (config.symbol == "BNB" || config.symbol == "ETH" || config.symbol == "MATIC") {
            transResult.callStatus = true
          }else {
            transResult.callStatus = status
          }
        }
        print("Transaction callData:(result)")
      }
    }
    // callback
    closure(transResult)
  }

获取合约Transaction结果

private func txSendCallResult(_ tx: WriteTransaction, options: TransactionOptions? = nil, config: CSContractConfig, completion: @escaping (TransactionSendingResult?)->Void) {
    // Get transaction result
    do {
      let result = try tx.send(password: password, transactionOptions: options)
      completion(result)
      print("Transaction hash:(result.hash)n")
      print("Transaction desc:(result.transaction.description)n")
    } catch {
      completion(nil)
      let transactionErr = "(error)"
      showMessage(message: transactionErr, config: config)
    }
     }

代币授权

    func tokenApprove() {
        let config = CSContractConfig()
        config.abiType = .erc20;
        config.privateKey = "your privateKey"
        config.from = "your walletAddress";
        config.approveAmount = "1000000000000";
        config.contractAddress = "contract address"
        config.symbol = "token symbol"
        CSContractManager.shared.callContract(method: "approve", params: [], config: config) { result in
            if (result.transHash.length > 0 && result.callData.count > 0) {
                print("Token approve success")
            }else {
                print("Token approve fail")
            }
        }
    }

代币发送

    func sendToken() {
        let config = CSContractConfig()
        config.abiType = .erc20;
        config.privateKey = "your privateKey"
        config.from = "your walletAddress";
        config.contractAddress = "contract address"
        config.symbol = "token symbol"
        config.gasLimit = kBaseGasLimit;
        let targetAddress = "target address"
        CSContractManager.shared.sendToken(config: config, amount: "10", toAdds: targetAddress) { result  in
            if (result.transHash.length > 0) {
                print("Token send success")
            }else {
                print("Token send fail")
            }
        }
    }

查询代币信息

    func queryToken() {
        let tokenAddress = ""
        guard let token = CSContractManager.shared.querySocialToken(address: tokenAddress) else {
            return
        }
        print("Token Name:(token.name)n")
        print("Token Symbol:(token.symbol)n")
        print("Token decimals:(token.decimals)n")
    }

查询当前钱包账户余额

    func queryAccountBalance () {
        let myWalletAddress = "your walletAddress";
        let balance = CSContractManager.shared.getAccountBalance(address: myWalletAddress)
        print("Your account balance:(balance)")
    }

具体功能使用,可以下载源码了解;

githugiticomfort是什么轮胎b.com/deve源码时代loperje… 如果对您有一些帮助请麻烦给个Sgithub中文官网网页ta源码时代r,谢谢。