YSBtc.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import 'dart:convert';
  2. import 'dart:math';
  3. import 'dart:typed_data';
  4. import 'package:bs58check/bs58check.dart';
  5. // import 'package:dartsv/dartsv.dart' as dartsv;
  6. import 'package:flutter_bitcoin/flutter_bitcoin.dart';
  7. import 'package:flutter_wallet/tools/YSNetWork.dart';
  8. import 'package:flutter_wallet/tools/YSTools.dart';
  9. import 'package:http/http.dart' as http;
  10. import 'package:web3dart/web3dart.dart' as web3;
  11. import 'YSAes.dart';
  12. const baseUrl = 'https://btcscan.org/api/';
  13. class YSBtc{
  14. static Future<String> getBalance(String address) async{
  15. try{
  16. final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=$address'));
  17. double balance = 0.00;
  18. List utxos = jsonDecode(utxosRes.body)['unspent_outputs']??[];
  19. for (var element in utxos) {
  20. balance += element['value']??0.00;
  21. }
  22. // final response = await http.get(Uri.parse('https://blockchain.info/q/addressbalance/$address'));
  23. balance = balance / 100000000;
  24. LogUtil.d('余额: $balance BTC');
  25. return '$balance';
  26. }catch(error){
  27. LogUtil.d('余额: https://blockchain.info/q/addressbalance/$address BTC');
  28. return '0.0';
  29. }
  30. }
  31. static Future<String> transferData({required String from,required String to,required String private,required String amount}) async{
  32. LogUtil.d(YSData().rpc);
  33. LogUtil.d('transferData======$from====$to====$private====$amount');
  34. try{
  35. // transferContractData3(from: from, to: to, private: private, amount: amount);
  36. // return '';
  37. // transferData2(from: from, to: to, private: private, amount: amount);
  38. // return '';
  39. // 创建一个网络对象
  40. final network = bitcoin;
  41. final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=$from'));
  42. List utxos = jsonDecode(utxosRes.body)['unspent_outputs']??[];
  43. if(utxos.isNotEmpty){
  44. LogUtil.d('transferData======$utxos');
  45. Map utxo = utxos.first;
  46. int total = utxo['value'];
  47. final txb = TransactionBuilder(network: network);
  48. // int number = (double.parse(amount) * pow(10, 8))~/1;
  49. // 添加输入(来自哪个地址的比特币)
  50. txb.addInput(utxo['tx_hash'], 0);
  51. // LogUtil.d('transferData======$number');
  52. // 添加输出(要发送到哪个地址)
  53. Uint8List toList = base58.decode(to);
  54. // 计算交易费
  55. const byteCount = 180 + (2 * 34) + 10;
  56. const feeSatoshis = byteCount * 15;
  57. // //console.log(feeSatoshis)
  58. // // 添加输出
  59. int sendSatoshis = total - feeSatoshis;
  60. txb.addOutput(toList, sendSatoshis);
  61. // 创建一个私钥对象
  62. final keyPair = ECPair.fromWIF(private, network: network);
  63. // return '';
  64. // 对交易进行签名
  65. txb.sign(vin: 0, keyPair: keyPair);
  66. // 构建交易
  67. final tx = txb.build();
  68. // 打印交易的十六进制表示
  69. LogUtil.d('交易数据: ${tx.ins} ====== ${tx.outs}');
  70. final rawTx = tx.toHex();
  71. final url = YSData().rpc;
  72. final headers = {'Content-Type': 'application/json'};
  73. final body = jsonEncode({
  74. 'jsonrpc': '1.0',
  75. 'id': 'curltest',
  76. 'method': 'sendrawtransaction',
  77. 'params': [rawTx]
  78. });
  79. final response = await http.post(Uri.parse(url), headers: headers, body: body);
  80. final data = jsonDecode(response.body);
  81. LogUtil.d('交易结果: $data');
  82. if(data['result']!=null){
  83. return data['result'];
  84. }else{
  85. return '';
  86. }
  87. }else{
  88. return '';
  89. }
  90. }catch(error){
  91. LogUtil.d('transferData======$error');
  92. return '';
  93. }
  94. }
  95. static Future<String> transferData3({required String from,required String to,required String private,required String amount}) async{
  96. LogUtil.d('transferData3======$from====$to====$private====$amount');
  97. Map request = {};
  98. String privateS = YSAes.aesEncode3('${private}_${DateTime.now().microsecond}');
  99. request['prikey'] = privateS;
  100. request['to'] = to;
  101. int number = (double.parse(amount) * pow(10, 8))~/1;
  102. request['value'] = number;
  103. Map dict = await YSNetWork.httpNetwork(api: 'bithash', request: request);
  104. if(dict.isNotEmpty){
  105. Map data = dict['data']??'';
  106. final pushTxRes = await http.post(Uri.parse('https://blockchain.info/pushtx'), body: {'tx': data['hex']});
  107. LogUtil.d('Transaction ID: https://blockchain.info/pushtx ======= ${pushTxRes.body}');
  108. // Map body = jsonDecode(pushTxRes.body);
  109. if(pushTxRes.body=='Transaction Submitted'){
  110. return data['hash']??'';
  111. }else{
  112. return '';
  113. }
  114. }
  115. return '';
  116. }
  117. static Future<String> transferContractData3({required String from,required String to,required String private,required String amount}) async{
  118. LogUtil.d('transferContractData3======$from====$to====$private====$amount');
  119. Map request = {};
  120. String privateS = YSAes.aesEncode3('${private}_${DateTime.now().microsecond}');
  121. request['prikey'] = privateS;
  122. request['to'] = to;
  123. int number = (double.parse(amount) * pow(10, 8))~/1;
  124. request['value'] = number;
  125. Map dict = await YSNetWork.httpNetwork(api: 'bithash', request: request);
  126. if(dict.isNotEmpty){
  127. Map data = dict['data']??'';
  128. final pushTxRes = await http.post(Uri.parse('ttps://api.omniwallet.org/v1/transaction/pushtx/'), body: {'tx': data['hex']});
  129. LogUtil.d('Transaction ID: ttps://api.omniwallet.org/v1/transaction/pushtx/ ======= ${pushTxRes.body}');
  130. // Map body = jsonDecode(pushTxRes.body);
  131. if(pushTxRes.body=='Transaction Submitted'){
  132. return data['hash']??'';
  133. }else{
  134. return '';
  135. }
  136. }
  137. return '';
  138. // final httpClient = http.Client();
  139. // final ethClient = web3.Web3Client('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID', httpClient);
  140. // final tokenAddress = web3.EthereumAddress.fromHex('TOKEN_CONTRACT_ADDRESS');
  141. // final tokenAbi = jsonDecode('TOKEN_CONTRACT_ABI');
  142. // final tokenContract = web3.DeployedContract(web3.ContractAbi.fromJson(tokenAbi, 'Token'), tokenAddress);
  143. // final transferFunction = tokenContract.function('transfer');
  144. // final transferArgs = [web3.EthereumAddress.fromHex('RECIPIENT_ADDRESS'), BigInt.from(100)]; // 将100个代币转账给RECIPIENT_ADDRESS
  145. // final transferTx = await ethClient.sendTransaction(
  146. // credentials,
  147. // web3.Transaction.callContract(
  148. // contract: tokenContract,
  149. // function: transferFunction,
  150. // parameters: transferArgs,
  151. // ),
  152. // );
  153. }
  154. static transferData2({required String from,required String to,required String private,required String amount}) async {
  155. final config = {
  156. 'privateKey': private,
  157. 'network': 'bitcoin', // 更改为主网络
  158. 'toAddress': to,
  159. 'fromAddress': from,
  160. 'satoshisPerByte': double.parse(amount),
  161. 'fee': 1000,
  162. };
  163. final network = config['network'] == 'testnet' ? testnet : bitcoin;
  164. final keyPair = ECPair.fromWIF('${config['privateKey']}', network: network);
  165. // final psbt = Psbt(network: network);
  166. final txb = TransactionBuilder(network: network);
  167. // 获取UTXO
  168. final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=${config['fromAddress']}'));
  169. final utxos = jsonDecode(utxosRes.body)['unspent_outputs'];//
  170. LogUtil.d('transferData======$utxos');
  171. // for (var i = 0; i < utxos.length; i++) {
  172. // Map value = txb.sign(keyPair: keyPair, vin: i);
  173. // LogUtil.d('transferData======$value');
  174. // }
  175. // return;
  176. int totalSatoshis = 0;
  177. for (var utxo in utxos) {
  178. // final txRes = await http.get(Uri.parse('https://blockchain.info/rawtx/${utxo['tx_hash_big_endian']}?format=hex'));
  179. // final nonWitnessUtxo = HEX.decode(txRes.body);
  180. totalSatoshis += txb.addInput(utxo['tx_hash'], utxo['tx_output_n']);
  181. // txb.addInput(txHash, vout)
  182. // psbt.addInput({
  183. // 'hash': utxo['tx_hash_big_endian'],
  184. // 'index': utxo['tx_output_n'],
  185. // 'nonWitnessUtxo': nonWitnessUtxo,
  186. // });
  187. //
  188. // totalSatoshis += int.parse('${utxo['value']}');
  189. }
  190. //
  191. // 计算交易费
  192. final byteCount = (utxos.length * 180) + (2 * 34) + 10;
  193. final feeSatoshis = byteCount * config['satoshisPerByte'];
  194. // 添加输出
  195. final sendSatoshis = totalSatoshis - feeSatoshis;
  196. txb.addOutput(config['toAddress'], sendSatoshis~/1);
  197. // psbt.addOutput({
  198. // 'address': config['toAddress'],
  199. // 'value': sendSatoshis,
  200. // });
  201. // 签名所有的输入
  202. for (var i = 0; i < utxos.length; i++) {
  203. txb.sign(vin: i, keyPair: keyPair);
  204. // psbt.signInput(i, keyPair);
  205. }
  206. // 完成交易并将其转换为十六进制
  207. // psbt.finalizeAllInputs();
  208. // final txHex = psbt.extractTransaction().toHex();
  209. //
  210. // // 广播交易
  211. // final pushTxRes = await http.post(Uri.parse('https://blockchain.info/pushtx'), body: {'tx': txHex});
  212. //
  213. // LogUtil.d('Transaction ID: ${pushTxRes.body}');
  214. }
  215. }