123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- // ignore_for_file: depend_on_referenced_packages
- import 'dart:typed_data';
- import 'package:flutter_wallet/tools/YSNetWork.dart';
- import 'package:flutter_wallet/tools/YSTools.dart';
- 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 int ysdecimals = 18;
- class Wbe3Api {
- late Wbe3Api? wbe3api;
- late Web3Client? client = Web3Client(YSData().rpc, Client());
- late DeployedContract contract;
- late String _contractAddress;
- late int decimals = 18;
- //使用单例模式,
- Future<Wbe3Api?> getInstances() async {
- try {
- wbe3api = Wbe3Api();
- client = Web3Client(YSData().rpc, Client());
- return wbe3api;
- } catch (error) {
- LogUtil.d(error);
- return null;
- }
- }
- //获取主链余额
- static Future<String> getBalance(String address) async {
- try {
- final client = Web3Client(YSData().rpc, Client());
- EtherAmount? amount =
- await client.getBalance(EthereumAddress.fromHex(address));
- BigInt? available = amount.getInWei;
- String blance = (available/ BigInt.from(pow(10, ysdecimals))).toString();
- LogUtil.d("$address=====$blance");
- await client.dispose();
- return blance;
- } catch (err) {
- LogUtil.d(' 余额错误: ${err.toString()}');
- return '0.0';
- }
- }
- //获取主链矿工费,如果矿工费给的不够高,那就无法交易
- Future<String> getdefaultEthfee() async {
- EtherAmount? gasprice = await client?.getGasPrice();
- LogUtil.d("==${_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, ysdecimals));
- return result.toString();
- }
- //判断以太坊地址是否正确
- Future<bool> getIsGCAddress(String maddress) async {
- try {//
- EthereumAddress address = EthereumAddress.fromHex(maddress);
- LogUtil.d(address);
- return true;
- } catch (e) {
- return false;
- }
- }
- /// 发起普通交易
- /// fromaddress 发送地址
- /// toaddress 接收地址
- /// privatekey 私钥
- /// fee 手续费
- /// value 数量
- Future<Object?> signETHTransaction(String fromaddress, String toaddress,
- String privatekey, String value,String gas,{Uint8List? data,String? fee}) async {
- // LogUtil.d('发送地址:$fromaddress\n接收地址:$toaddress\n金额:$value\n服务费:$gas');
- try {
- // LogUtil.d(YSData().rpc);
- final credentials = EthPrivateKey.fromHex(privatekey);
- // EthereumAddress from = EthereumAddress.fromHex(fromaddress);
- final receiver = EthereumAddress.fromHex(toaddress);
- // EtherAmount? gasprice = await client?.getGasPrice();
- EtherAmount? gasprice = await client?.getGasPrice();
- if(fee!=null){
- gasprice = EtherAmount.fromInt(EtherUnit.wei,int.parse(fee));
- }
- BigInt gaslimit = BigInt.from(double.parse(gas) * pow(10, 0));
- final networkId = await client?.getNetworkId();
- BigInt amount = tokenInt(value, decimals);
- EtherAmount amountValue = EtherAmount.fromBigInt(EtherUnit.wei, amount);
- if(value=='0'){
- amountValue = EtherAmount.fromInt(EtherUnit.wei,0);
- }
- // BigInt gaslimit = BigInt.from(double.parse(fee)* pow(10, decimals));
- // LogUtil.d(
- // '发送地址:$fromaddress\n'
- // '接收地址:$toaddress\n'
- // '金额:${EtherAmount.fromBigInt(EtherUnit.wei, amount)}\n'
- // 'gasPrice:$gasprice\n'
- // 'maxGas:${gaslimit.toInt()}'
- // );
- var transaction = data!=null?Transaction(
- to: receiver,
- gasPrice: gasprice,
- maxGas: gaslimit.toInt(),
- value: amountValue,
- data: data
- ):Transaction(
- to: receiver,
- gasPrice: gasprice,
- maxGas: gaslimit.toInt(),
- value: amountValue,
- );
- var txHash = await client?.sendTransaction(
- credentials,
- transaction,
- chainId: networkId,
- );
- LogUtil.d('transferhash====${txHash??''}');
- await client?.dispose();
- return txHash;
- } catch (error) {
- LogUtil.d(error);
- ysFlutterToast('$error');
- return '';
- }
- }
- /// 通过精度格式化 传入的数量
- /// 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) as double?;
- } else {
- v = double.parse(value);
- }
- } catch (err) {
- LogUtil.d('Fmt.tokenInt() error: ${err.toString()}');
- }
- return BigInt.from(v! * pow(10, decimals));
- }
- /// 判断是否合约地址
- /// contractaddress 合约地址
- Future<bool> getIsContractAddress(String contractaddress) async {
- if (contractaddress.length != 42) {
- return false;
- } else {
- EthereumAddress address = EthereumAddress.fromHex(contractaddress);
- var respons = await client?.getCode(address);
- LogUtil.d("respons ====$respons");
- return respons!.isNotEmpty ? true : false;
- }
- }
- /// 设置全局合约,读取abi
- Future<bool> setContaract(String contractaddress,{int decimal = 0}) async {
- _contractAddress = contractaddress;
- contract = await fromAssets('images/contract.json', _contractAddress);
- // decimals = decimal;
- // LogUtil.d(_contractAddress);
- // decimals = decimal;
- // return true;
- // LogUtil.d('setContaract=========$_contractAddress');
- var result = await getContractInfo('decimals');
- if('$result'.contains('RangeError')){
- decimals = decimal;
- return true;
- }else{
- var result = await getContractInfo('decimals');
- decimals = int.parse(result.toString());
- return true;
- }
- return false;
- }
- /// 将合约格式化
- Future<DeployedContract> fromAssets(String path, String contractAddress) async {
- final contractJson = jsonDecode(await rootBundle.loadString(path));
- DeployedContract value = DeployedContract(ContractAbi.fromJson(jsonEncode(contractJson['abi']),contractJson['contractName'] as String),EthereumAddress.fromHex(contractAddress));
- return value;
- }
- /// 读取合约基本信息decimals和symbol
- adppContaractDecimals(String contractaddress) async {
- // int dappDecimals = 18;
- _contractAddress = contractaddress;
- contract = await fromAssets('images/contract.json', _contractAddress);
- decimals = 0;
- // try {
- // contract = await fromAssets('images/contract.json', contractaddress);
- // var dec = await getContractInfo('decimals');
- // var type = await getContractInfo('symbol');
- // decimals = int.parse(dec.toString());
- // LogUtil.d("adpp精度获取==$decimals");
- // return {'decimals': decimals, 'coin': type};
- // } catch (error) {
- // return {'decimals': decimals, 'coin': "ETH"};
- // }
- }
- /// 获取合约基本信息
- /// functionname 方法名
- /// decimals:合约精度,小数位
- /// name 名字
- /// symbol 和名字一致
- Future<String?> getContractInfo(String functionname) async {
- try {
- final response = await client?.call(
- contract: contract,
- function: contract.function(functionname),
- params: [],
- );
- // LogUtil.d('getContractInfo${response?.first.toString()}');
- return response?.first.toString();
- } catch (error) {
- // LogUtil.d('getContractInfo2$error');
- return error.toString();
- }
- }
- //获取合约余额
- Future<String> getTokenBalance(String madress,String contractAddress) async {
- // LogUtil.d(YSData().rpc);
- bool isCheck = await setContaract(contractAddress);
- if(isCheck){
- EthereumAddress adress = EthereumAddress.fromHex(madress);
- final response = await client?.call(
- contract: contract,
- function: contract.function('balanceOf'),
- params: [adress],
- );
- // LogUtil.d('response=====${contract.address}');
- // LogUtil.d(response.toString());
- double blanceD = response?.first / BigInt.from(pow(10, decimals));
- // String blance = blanceD.toStringAsFixed(10);
- LogUtil.d('$madress====$blanceD');
- return '$blanceD';
- }
- return '0.0';
- }
- //转出手续费
- Future<String> 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<String> getexchangeFee(String fromaddress, String toaddress, String value) async {
- BigInt amount = tokenInt(value, decimals);
- return await getCommonFee(fromaddress, "exchange", [amount]);
- }
- /*
- * 获取合约手续费通用方法
- * fromaddress 发送地址
- * functionname 方法名
- * parameters 合约参数
- */
- Future<String> getCommonFee(
- String from, String functionname, List<dynamic> parameters) async {
- EthereumAddress fromaddress = EthereumAddress.fromHex(from);
- final gasprice = await client?.getGasPrice();
- LogUtil.d('gasprice$gasprice');
- var transaction = Transaction.callContract(
- contract: contract,
- function: contract.function(functionname),
- parameters: parameters,
- gasPrice: gasprice,
- from: fromaddress);
- BigInt? gaslimit = BigInt.from(21000);
- LogUtil.d('检测gaslimit${transaction.data} $gaslimit');
- try {
- LogUtil.d("gaslimit ====${transaction.from}====${transaction.to}====${transaction.data}====${EtherAmount.zero()}");
- gaslimit = await client?.estimateGas(
- sender: transaction.from,
- to: transaction.to,
- data: transaction.data,
- value: EtherAmount.zero()
- );
- // gaslimit = await client?.estimateGas(
- // sender: fromaddress,
- // to: EthereumAddress.fromHex(_contractAddress),
- // data: transaction.data,
- // value: EtherAmount.zero());
- LogUtil.d('gaslimit ====$gaslimit');
- return _tofee(gaslimit!, gasprice!);
- } catch (error) {
- LogUtil.d(error.toString());
- return 'error$error';
- }
- }
- /// 发起合约转账
- /// fromaddress 发送地址
- /// toaddress 接收地址
- /// privatekey 私钥
- /// value 数量
- Future<Object> tokenTransfer(String fromaddress, String toaddress,
- String privatekey, String fee, String value,String gas) async {
- LogUtil.d('发送地址:$fromaddress\n接收地址:$toaddress\n金额:$value\n服务费:$fee');
- BigInt amount = tokenInt(value, decimals);
- EthereumAddress receiver = EthereumAddress.fromHex(toaddress);
- return await signContractTransaction2(fromaddress, privatekey, fee, "transfer", [receiver, amount],gas);
- }
- Future<Object> tokenTransfer2(String fromaddress, String toaddress,
- String privatekey, String fee, String value,String gas) async {
- LogUtil.d('发送地址:$fromaddress\n接收地址:$toaddress\n金额:$value\n服务费:$fee');
- BigInt amount = tokenInt(value, decimals);
- EthereumAddress receiver = EthereumAddress.fromHex(toaddress);
- return await signContractTransaction3(fromaddress, privatekey, fee, "transfer", [receiver, amount],gas);
- }
- /// 发起兑换交易
- /// fromaddress 发送地址
- /// privatekey 私钥
- /// value 数量
- Future<Object> tokenExchange(String fromaddress, String privatekey, String fee, String value, String gas,String toaddress,String rpc,String towalletaddress,String fromtokenaddress) async {
- BigInt amount = tokenInt(value, decimals);
- // LogUtil.d(contract.address.hexEip55);
- // String changeStr = await getexchangeFee(fromaddress, contract.address.hexEip55, value);
- // LogUtil.d(changeStr);
- // return '';
- // return await signContractTransaction3(fromaddress, privatekey, fee, "exchange", [amount],gas);
- LogUtil.d('tokenExchange============$fromaddress===============$toaddress');
- bool isContract = await getIsContractAddress(fromtokenaddress);
- bool isWBNB = toaddress=='0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c'&&isContract==false;
- // final myAddress = EthereumAddress.fromHex(fromaddress);
- final toWalletAddress = EthereumAddress.fromHex(towalletaddress);
- // 要交换的代币合约地址,例如:CAKE
- final tokenIn = EthereumAddress.fromHex(isContract?fromtokenaddress:'0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c');
- // 要接收的代币合约地址,例如:USDT
- final tokenOut = EthereumAddress.fromHex(toaddress);
- client = Web3Client(rpc, Client());
- contract = await fromAssets('asset/exchange.json', isWBNB?'0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c':YSData().pancakeAddress);
- //swapExactETHForTokens swapExactTokensForTokens
- String funName = 'swapExactETHForTokens';
- if(isContract){
- funName = 'swapExactTokensForTokens';
- }
- if(isWBNB){
- funName = 'deposit';
- }
- List<dynamic> parameters = isWBNB?[]:[
- amount, // 要交换的代币数量(注意小数位数)
- if(funName=='swapExactTokensForTokens')BigInt.from(0), // 接收的最少代币数量
- funName=='swapExactTokensForTokens'?[tokenIn, tokenOut]:[tokenIn,tokenOut], // 路径
- toWalletAddress, // 接收地址
- BigInt.from((DateTime.now().millisecondsSinceEpoch / 1000).floor() + 60 * 20), // 截止时间
- ];
- LogUtil.d('tokenExchange=======$funName======$isContract====$parameters');
- return await signContractTransaction4(fromaddress, privatekey, fee, funName,parameters ,gas,amount: (isContract==false)?amount:null);
- }
- /*
- * 发起合约交易
- * fromaddress 发送地址
- * privatekey 私钥
- * functionname 合約调用用方法
- * parameters 合約参數
- */
- Future<Object> signContractTransaction4(String from, String privatekey,String fee, String functionname, List<dynamic> parameters, String gas,{BigInt? amount}) async {
- // bool isCheck = await setContaract(YSData().contAddress);
- LogUtil.d('amount======$amount');
- if(true){
- try {
- final credentials = EthPrivateKey.fromHex(privatekey);
- EthereumAddress fromaddress = EthereumAddress.fromHex(from);
- final networkId = await client?.getNetworkId();
- final gasprice = await client?.getGasPrice();
- // LogUtil.d(gasprice);
- // 设置交易参数
- final transaction = Transaction.callContract(
- contract: contract,
- function: contract.function(functionname),
- parameters: parameters,
- from: fromaddress,
- gasPrice: gasprice,
- maxGas: 200000,
- value: amount==null?EtherAmount.zero():EtherAmount.inWei(amount),
- );
- // return '';
- var txHash = await client?.sendTransaction(
- credentials,
- transaction,
- chainId: networkId,
- );
- LogUtil.d('hash====${txHash!}');
- await client?.dispose();
- return txHash;
- } catch (error) {
- LogUtil.d('signContractTransaction error========$error');
- ysFlutterToast('$error');
- return '';
- }
- }
- return '';
- }
- Future<Object> signContractTransaction(String from, String privatekey,String fee, String functionname, List<dynamic> parameters, String gas) async {
- // bool isCheck = await setContaract(YSData().contAddress);
- LogUtil.d('decimals======$decimals');
- if(true){
- 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(gas) * pow(10, 0));
- // LogUtil.d('decimals======${gaslimit.toInt()}');
- // BigInt feeValue = BigInt.from(double.parse(fee) * pow(10, decimals));
- LogUtil.d("gaslimit ====${gaslimit.toInt()}\n$parameters\n$gasprice");
- var transaction = Transaction.callContract(
- contract: contract,
- function: contract.function(functionname),
- parameters: parameters,
- from: fromaddress,
- gasPrice: gasprice,
- maxGas: gaslimit.toInt());
- var txHash = await client?.sendTransaction(
- credentials,
- transaction,
- chainId: networkId,
- );
- LogUtil.d('hash====${txHash!}');
- await client?.dispose();
-
- return txHash;
- } catch (error) {
- LogUtil.d('signContractTransaction error========$error');
- ysFlutterToast('$error');
- return '';
- }
- }
- return '';
- }
- Future<Object> signContractTransaction2(String from, String privatekey,String fee, String functionname, List<dynamic> parameters, String gas) async {
- // bool isCheck = await setContaract(YSData().contAddress);
- LogUtil.d('decimals======$decimals');
- if(true){
- try {
- EthereumAddress fromaddress = EthereumAddress.fromHex(from);
- final credentials = EthPrivateKey.fromHex(privatekey);
- final networkId = await client?.getNetworkId();
- final gasprice = EtherAmount.fromInt(EtherUnit.wei,int.parse(fee));
- BigInt gaslimit = BigInt.from(double.parse(gas) * pow(10, 0));
- // LogUtil.d('decimals======${gaslimit.toInt()}');
- // BigInt feeValue = BigInt.from(double.parse(fee) * pow(10, decimals));
- LogUtil.d("gaslimit ====${gaslimit.toInt()}\n$parameters\n$gasprice");
- var transaction = Transaction.callContract(
- contract: contract,
- function: contract.function(functionname),
- parameters: parameters,
- from: fromaddress,
- gasPrice: gasprice,
- maxGas: gaslimit.toInt());
- var txHash = await client?.sendTransaction(
- credentials,
- transaction,
- chainId: networkId,
- );
- LogUtil.d('hash====${txHash!}');
- await client?.dispose();
- return txHash;
- } catch (error) {
- LogUtil.d('signContractTransaction error========$error');
- ysFlutterToast('$error');
- return '';
- }
- }
- return '';
- }
- Future<Object> signContractTransaction3(String from, String privatekey,String fee, String functionname, List<dynamic> parameters, String gas) async {
- // bool isCheck = await setContaract(YSData().contAddress);
- LogUtil.d('decimals======$decimals');
- if(true){
- try {
- EthereumAddress fromaddress = EthereumAddress.fromHex(from);
- final credentials = EthPrivateKey.fromHex(privatekey);
- final networkId = await client?.getNetworkId();
- final gasprice = EtherAmount.fromInt(EtherUnit.wei,int.parse(fee));
- BigInt gaslimit = BigInt.from(double.parse(gas) * pow(10, 0));
- // LogUtil.d('decimals======${gaslimit.toInt()}');
- // BigInt feeValue = BigInt.from(double.parse(fee) * pow(10, decimals));
- LogUtil.d("gaslimit ====${gaslimit.toInt()}\n$parameters\n$gasprice");
- var transaction = Transaction.callContract(
- contract: contract,
- function: contract.function(functionname),
- parameters: parameters,
- from: fromaddress,
- gasPrice: gasprice,
- maxGas: gaslimit.toInt());
- LogUtil.d(YSData().rpc);
- LogUtil.d(transaction.data);
- return '';
- var txHash = await client?.sendTransaction(
- credentials,
- transaction,
- chainId: networkId,
- );
- LogUtil.d('hash====${txHash!}');
- await client?.dispose();
- return txHash;
- } catch (error) {
- LogUtil.d('signContractTransaction error========$error');
- ysFlutterToast('$error');
- return '';
- }
- }
- return '';
- }
- /// 获取交易状态
- /// txHash 交易hash
- Future<bool?> getTranferstate(String txHash) async {
- try {
- var transactionReceipt = await client?.getTransactionReceipt(txHash);
- if (transactionReceipt != null) {
- LogUtil.d("交易状态: ${transactionReceipt.status}");
- await client?.dispose();
- return transactionReceipt.status;
- }
- return false;
- } catch (error) {
- LogUtil.d("状态error: $error");
- return false;
- }
- }
- }
- //格式化小数点
- String formatFour(String values) {
- double value = double.tryParse(values)! / pow(10, ysdecimals);
- String newvalue = value.toStringAsFixed(8);
- return newvalue.substring(0, newvalue.indexOf('.') + 7);
- }
|