flutter web3主链,合约操作

引用的依赖

import 'package:web3dart/web3dart.dart';
import 'dart:math';
import 'package:http/http.dart';
import 'package:intl/intl.dart';
import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
const String contarctChainaddress =
    '0x1daEAaa139f801dA23153a381B78ec68D1551071'; //跨链合约地址
const String rpcUrl = 'https://mainnet.infura.io/v3/'; //默认rpc节点,这个需要自己更改,当前为以太坊主网
const int gcdecimals = 18;

首先初始化web3,创建client

 static Wbe3Api wbe3api;
 static Web3Client client;
 static DeployedContract contract;
 static String _contractAddress;
 static int decimals;
//使用单例模式,
Future getInstances() async {
    try {
      if (wbe3api == null) {
        wbe3api = Wbe3Api();
      }
      if (client == null) {
        client = new Web3Client(rpcUrl, Client());
      }
      return wbe3api;
    } catch (error) {
      return null;
    }
  }

主链币种操作:

1.获取主链的余额,这里面要用到主链的精度,也就是小数位

 //获取主链余额
  Future getBalance(String address) async {
    try {
      EtherAmount amount =
          await client.getBalance(EthereumAddress.fromHex(address));
      BigInt available = amount.getInWei;
      String blance = (available / BigInt.from(pow(10, gcdecimals))).toString();
      print("=====" + blance);
      await client.dispose();
      return formatFour(blance);
    } catch (err) {
      print(' 余额错误: ${err.toString()}');
      return formatFour('0.00');
    }
  }
//格式化小数点
String formatFour(String values) {
    double value = double.tryParse(values) / pow(10, gcdecimals);
    String newvalue = value.toStringAsFixed(8);
    return newvalue.substring(0, newvalue.indexOf('.') + 7);
  }

2.主链的交易
首先获取矿工费

 //获取主链矿工费,如果矿工费给的不够高,那就无法交易
  Future getdefaultEthfee() async {
    EtherAmount gasprice = await client.getGasPrice();
    print("==" + _tofee(BigInt.from(21000), gasprice));
    return _tofee(BigInt.from(21000), gasprice);
  }
  /**
   * 获取手续费
   * gaslimit :最小gas,合约需要算出来,主链币则默认为21000
   * gasprice:gas价格
   */
  String _tofee(BigInt gaslimit, EtherAmount gasprice) {
    var fee = gaslimit * gasprice.getInWei;
    var result = fee / BigInt.from(pow(10, gcdecimals));
    return result.toString();
  }

之后发起交易

  //判断以太坊地址是否正确
  Future getIsGCAddress(String maddress) async {
    try {
      EthereumAddress address = EthereumAddress.fromHex(maddress);
      return true;
    } catch (e) {
      return false;
    }
  }

  /**
   * 发起普通交易
   * fromaddress 发送地址
   * toaddress  接收地址
   * privatekey 私钥
   * fee  手续费
   * value  数量
   */
  Future signETHTransaction(String fromaddress, String toaddress,
      String privatekey, String fee, String value) async {
    try {
      final credentials = EthPrivateKey.fromHex(privatekey);
      EthereumAddress from = EthereumAddress.fromHex(fromaddress);
      final receiver = EthereumAddress.fromHex(toaddress);
      EtherAmount gasprice = await client.getGasPrice();
      final networkId = await client.getNetworkId();
      BigInt amount = tokenInt(value, gcdecimals);
      BigInt gaslimit = BigInt.from(double.parse(fee) * pow(10, 9));
      print("gaslimit ====" + gaslimit.toString());
      print("GCstart ====");
      var transaction = Transaction(
        to: receiver,
        gasPrice: gasprice,
        maxGas: gaslimit.toInt(),
        value: EtherAmount.fromUnitAndValue(EtherUnit.wei, amount),
      );
      var txHash = await client.sendTransaction(
        credentials,
        transaction,
        chainId: networkId,
      );
      print('transferhash====' + txHash);
      await client.dispose();
      return txHash;
    } catch (error) {
      return error;
    }
  }

 /**
   * 通过精度格式化 传入的数量
   * value 数量
   * decimals 精度(保留小数位)
   */
  BigInt tokenInt(String value, int decimals) {
    if (value == null) {
      return BigInt.zero;
    }
    double v = 0;
    try {
      if (value.contains(',') || value.contains('.')) {
        v = NumberFormat(",##0.${"0" * decimals}").parse(value);
      } else {
        v = double.parse(value);
      }
    } catch (err) {
      print('Fmt.tokenInt() error: ${err.toString()}');
    }
    return BigInt.from(v * pow(10, decimals));
  }

合约查询和操作:
1.判断合约地址

 /**
   * 判断是否合约地址 
   * contractaddress 合约地址
   */
  Future getIsContractAddress(String contractaddress) async {
    if (contractaddress.length != 42) {
      return false;
    } else {
      EthereumAddress address = EthereumAddress.fromHex(contractaddress);
      var respons = await client.getCode(address);
      print("respons ====" + respons.toString());
      return respons.length > 0 ? true : false;
    }
  }

2.读取合约abi

 /**
   * 设置全局合约,读取abi
   */
  setContaract(String contractaddress) async {
    _contractAddress = contractaddress;
    contract = await fromAssets(
        'images/contract.json', _contractAddress);
    if (contract != null) {
      var result = await getContractInfo('decimals');
      decimals = int.parse(result.toString());
      print("==精度获取==" + decimals.toString());
    }
  }

  /**
   * 将合约格式化
   */
   Future fromAssets(
      String path, String contractAddress) async {
    final contractJson =
        jsonDecode(await rootBundle.loadString(path));
    return DeployedContract(ContractAbi.fromJson(jsonEncode(contractJson['abi']),contractJson['contractName'] as String),
        EthereumAddress.fromHex(contractAddress));
  }

abi为json,需要在yaml文件中读取

 assets:
    - images/home/
    - images/assets/
    - images/contract.json

abi为格式

{
  "contractName": "TargaryenCoin",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
   
    {
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
  
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "exchange",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "withdraw",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
 {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
   
  ]
}

3.获取合约基本参数

 /**
   * 读取合约基本信息decimals和symbol
   */
  Future adppContaractDecimals(String contractaddress) async {
    int dappDecimals = 18;
    // contract = await fromAssets(
    //     'images/contract.json', contractaddress);
    try {
      var dec = await getContractInfo('decimals');
      var type = await getContractInfo('symbol');
      dappDecimals = int.parse(dec.toString());
      print("adpp精度获取==" + dappDecimals.toString());
      return {'decimals': dappDecimals, 'coin': type};
    } catch (error) {
      return {'decimals': dappDecimals, 'coin': "ETH"};
    }
  }

/**
   * 获取合约基本信息
   * functionname 方法名
   * decimals:合约精度,小数位
   * name 名字
   * symbol  和名字一致
   */
  Future getContractInfo(String functionname) async {
    try {
      final response = await client.call(
        contract: contract,
        function: contract.function(functionname),
        params: [],
      );
      print(response.first.toString());
      return response.first.toString();
    } catch (error) {
      print(error);
      return error.toString();
    }
  }

4.获取合约余额,切记只能执行abi里面的方法

//获取合约余额
  Future getTokenBalance(String madress) async {
    EthereumAddress adress = EthereumAddress.fromHex(madress);
    final response = await client.call(
      contract: contract,
      function: contract.function('balanceOf'),
      params: [adress],
    );
    print(response.toString());
    String blance =
        (response.first / BigInt.from(pow(10, decimals))).toString();
    print('====' + blance);
    return formatFour(blance);
  }

5.合约交易
(1)矿工费,合约的任何交易都要手续费

 //转出手续费
  Future getTransferFee(
      String fromaddress, String toaddress, String value) async {
    BigInt amount = tokenInt(value, decimals);
    EthereumAddress receiver = EthereumAddress.fromHex(toaddress);
    return await getCommonFee(fromaddress, "transfer", [receiver, amount]);
  }

  //兑换手续费
  Future getexchangeFee(
      String fromaddress, String toaddress, String value) async {
    BigInt amount = tokenInt(value, decimals);
    await getCommonFee(fromaddress, "exchange", [amount]);
  }

/*
   * 获取合约手续费通用方法
   * fromaddress 发送地址
   * functionname 方法名
   * parameters  合约参数
   */
  Future getCommonFee(
      String from, String functionname, List parameters) async {
    EthereumAddress fromaddress = EthereumAddress.fromHex(from);
    final gasprice = await client.getGasPrice();
    print('gasprice' + gasprice.toString());
    var transaction = Transaction.callContract(
        contract: contract,
        function: contract.function(functionname),
        parameters: parameters,
        gasPrice: gasprice,
        from: fromaddress);
    print('检测gaslimit');
    var gaslimit = BigInt.from(21000);
    try {
      gaslimit = await client.estimateGas(
          sender: fromaddress,
          to: EthereumAddress.fromHex(_contractAddress),
          data: transaction.data,
          value: EtherAmount.zero());
      print('gaslimit ====' + gaslimit.toString());
      return _tofee(gaslimit, gasprice);
    } catch (error) {
      print(error.toString());
      return 'error' + error.toString();
    }
  }

(2)发起合约交易,转账和兑换

/**
   * 发起合约转账
   * fromaddress 发送地址
   * toaddress  接收地址
   * privatekey 私钥
   * value  数量
   */
  Future tokenTransfer(String fromaddress, String toaddress,
      String privatekey, String fee, String value) async {
    BigInt amount = tokenInt(value, decimals);
    EthereumAddress receiver = EthereumAddress.fromHex(toaddress);
    return await signContractTransaction(
        fromaddress, privatekey, fee, "transfer", [receiver, amount]);
  }

  /**
   * 发起兑换交易
   * fromaddress 发送地址
   * privatekey 私钥
   * value  数量
   */
  Future tokenExchange(
      String fromaddress, String privatekey, String fee, String value) async {
    BigInt amount = tokenInt(value, decimals);
    await signContractTransaction(
        fromaddress, privatekey, fee, "exchange", [amount]);
  }

/*
   * 发起合约交易
   * fromaddress 发送地址
   * privatekey 私钥
   * functionname 合約调用用方法
   * parameters  合約参數
   */
  Future signContractTransaction(String from, String privatekey,
      String fee, String functionname, List parameters) async {
    try {
      EthereumAddress fromaddress = EthereumAddress.fromHex(from);
      final credentials = EthPrivateKey.fromHex(privatekey);
      final networkId = await client.getNetworkId();
      final gasprice = await client.getGasPrice();
      BigInt gaslimit = BigInt.from(double.parse(fee) * pow(10, 9));
      print("gaslimit ====" + gaslimit.toString());
      var transaction = Transaction.callContract(
          contract: contract,
          function: contract.function(functionname),
          parameters: parameters,
          from: fromaddress,
          gasPrice: gasprice,
          maxGas: gaslimit.toInt());
      print("开始交易");
      var txHash = await client.sendTransaction(
        credentials,
        transaction,
        chainId: networkId,
      );
      print('hash====' + txHash);
      await client.dispose();
      return txHash;
    } catch (error) {
      print(error);
      return error;
    }
  }

  /**
   * 获取交易状态
   * txHash 交易hash
   */
  Future getTranferstate(String txHash) async {
    try {
      var transactionReceipt = await client.getTransactionReceipt(txHash);
      if (transactionReceipt != null) {
        print("交易状态: " + transactionReceipt.status.toString());
        await client.dispose();
        return transactionReceipt.status;
      }
      return false;
    } catch (error) {
      print("状态error: " + error.toString());
      return false;
    }
  }

你可能感兴趣的:(flutter web3主链,合约操作)