YSWalletTransfer.dart 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. import 'dart:math';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_wallet/base/YSBase.dart';
  5. import 'package:flutter_wallet/generated/l10n.dart';
  6. import 'package:flutter_wallet/login/view/YSHelpView.dart';
  7. import 'package:flutter_wallet/setting/YSAlwayAddress.dart';
  8. import 'package:flutter_wallet/tools/YSAlertView.dart';
  9. import 'package:flutter_wallet/tools/YSBip.dart';
  10. import 'package:flutter_wallet/tools/YSColors.dart';
  11. import 'package:flutter_wallet/tools/YSNetWork.dart';
  12. import 'package:flutter_wallet/tools/YSTools.dart';
  13. import 'package:flutter_wallet/wallet/YSTansDetail.dart';
  14. import 'package:flutter_wallet/wallet/YSWalletManager.dart';
  15. import 'package:flutter_wallet/wallet/view/YSWalletMineTokenChoose.dart';
  16. import 'package:web3dart/web3dart.dart';
  17. import 'package:http/http.dart';
  18. import '../tools/YSBip2.dart';
  19. import '../tools/YSBtc.dart';
  20. import '../tools/YSSqflite.dart';
  21. import '../tools/YSTron.dart';
  22. class YSWalletTransfer extends StatefulWidget {
  23. final String? address;
  24. const YSWalletTransfer({Key? key, this.address}) : super(key: key);
  25. @override
  26. YSWalletTransferState createState() => YSWalletTransferState();
  27. }
  28. class YSWalletTransferState extends State<YSWalletTransfer> {
  29. Map _wallet = {};
  30. List _walletArray = [];
  31. List _netArray = [];
  32. int _selectedIndex = 0;
  33. String _address = '';
  34. String _number = '';
  35. double _fee = 0.000021;
  36. Map _token = {};
  37. double _gas = 100000;
  38. String _hash = '';
  39. @override
  40. void initState() {
  41. _address = widget.address??'';
  42. _getWalletData();
  43. _getTokenData();
  44. super.initState();
  45. }
  46. _getGasPrice() async{
  47. if(_token['address']==YSData().wallet['public']){
  48. _gas = 21000;
  49. }else{
  50. _gas = 100000;
  51. }
  52. Web3Client? client = Web3Client(YSData().rpc, Client());
  53. EtherAmount etherAmount = await client.getGasPrice();
  54. double value1 = etherAmount.getValueInUnit(EtherUnit.gwei);
  55. double value2 = value1+1;
  56. double value3 = value2+1;
  57. double numValue1 = value1*_gas/pow(10, 9);
  58. double numValue2 = value2*_gas/pow(10, 9);
  59. double numValue3 = value3*_gas/pow(10, 9);
  60. _netArray = [
  61. {'image':'步行','speed':S.current.MAN,'price':numValue1,'time':'1${S.current.FENZHONG}','dollar':'0.015'},
  62. {'image':'自行车','speed':S.current.TUIJIAN,'price':numValue2,'time':'15${S.current.MIAO}','dollar':'0.030'},
  63. {'image':'飞行','speed':S.current.KUAI,'price':numValue3,'time':'3${S.current.MIAO}','dollar':'0.045'}
  64. ];
  65. _fee = _netArray[0]['price'];
  66. setState(() {});
  67. }
  68. _getWalletData() async{
  69. YSSqflite sqflite = YSSqflite().init();
  70. _walletArray = await sqflite.rawQuery();
  71. if(!mounted)return;
  72. if(YSData().wallet.isNotEmpty){
  73. // _wallet = YSData().wallet;
  74. // _address = _wallet['public'];
  75. // setState(() {});
  76. }
  77. }
  78. _getTokenData() async{
  79. YSSqflite2 sqflite2 = YSSqflite2().init();
  80. List tokenArray = await sqflite2.rawQuery();
  81. // LogUtil.d('tokenArray======$tokenArray');
  82. // LogUtil.d('contAddress======${YSData().contAddress}');
  83. if(!mounted)return;
  84. if(tokenArray.isNotEmpty){
  85. _token = tokenArray.firstWhere((element) => element['address']==YSData().contAddress,orElse: ()=>{});
  86. if(_token.isEmpty){
  87. _token = tokenArray.first;
  88. }
  89. setState(() {});
  90. _getGasPrice();
  91. }
  92. }
  93. @override
  94. Widget build(BuildContext context) {
  95. return YSBase(
  96. ysTitle: S.current.ZHUANZHANG,
  97. ysChild: Container(
  98. height: ysHeight(context)-ysTOP(context)-hsp(75),
  99. padding: EdgeInsets.only(left: hsp(20),right: hsp(20),top: hsp(15)),
  100. child: Column(
  101. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  102. children: [
  103. Column(
  104. crossAxisAlignment: CrossAxisAlignment.start,
  105. children: [
  106. Row(
  107. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  108. children: [
  109. Text(S.current.JIESHOUDIZHI,style: YSColors.contentStyle(context),),
  110. GestureDetector(
  111. onTap: (){
  112. ysShowBottomAlertView(context, Container(
  113. height: hsp(150),
  114. width: ysWidth(context),
  115. decoration: const BoxDecoration(
  116. color: Colors.white,
  117. borderRadius: BorderRadius.only(topLeft: Radius.circular(10),topRight: Radius.circular(10))
  118. ),
  119. child: Column(
  120. children: [
  121. Container(
  122. height: hsp(50),
  123. alignment: Alignment.center,
  124. child: Text('地 址 类 型',style: YSColors.titleStyle(context),),
  125. ),
  126. SizedBox(
  127. height: hsp(100),
  128. child: Column(
  129. children: [
  130. Divider(height: hsp(1),color: YSColors.lineColor(context),),
  131. GestureDetector(
  132. onTap: (){
  133. Navigator.pop(context);
  134. Navigator.of(context).push(
  135. CupertinoPageRoute(builder: (context){
  136. return const YSWalletManager(isChoose: true,);
  137. })
  138. ).then((value) {
  139. if(value!=null){
  140. _wallet = value;
  141. _address = value['public'];
  142. _getGasPrice();
  143. setState(() {});
  144. }
  145. });
  146. },
  147. behavior: HitTestBehavior.opaque,
  148. child: Container(
  149. height: hsp(49),
  150. alignment: Alignment.center,
  151. child: Text('钱包',style: YSColors.contentStyle(context),),
  152. ),
  153. ),
  154. Divider(height: hsp(1),color: YSColors.lineColor(context),),
  155. GestureDetector(
  156. onTap: (){
  157. Navigator.pop(context);
  158. Navigator.of(context).push(
  159. CupertinoPageRoute(builder: (context){
  160. return const YSAlwayAddress(isChoose: true,);
  161. })
  162. ).then((value) {
  163. if(value!=null){
  164. _wallet = value;
  165. _address = value['address'];
  166. _getGasPrice();
  167. setState(() {});
  168. }
  169. });
  170. },
  171. behavior: HitTestBehavior.opaque,
  172. child: Container(
  173. height: hsp(49),
  174. alignment: Alignment.center,
  175. child: Text('常用地址',style: YSColors.contentStyle(context),),
  176. ),
  177. ),
  178. ],
  179. ),
  180. )
  181. ],
  182. ),
  183. ),isBarr: true);
  184. },
  185. behavior: HitTestBehavior.opaque,
  186. child: Row(
  187. children: [
  188. Text(S.current.XUANZEQIANBAO,style: TextStyle(fontSize: zsp(14),color: const Color(0xFF3D5AFF)),),
  189. Icon(Icons.chevron_right,size: hsp(20),color: const Color(0xFF3D5AFF),)
  190. ],
  191. ),
  192. )
  193. ],
  194. ),
  195. YSInputView(tips: S.current.QINGSHURUHUOXUANZENINDEMUBIAOQIANBAODIZHI,rightWidget: GestureDetector(
  196. onTap: () async{
  197. _address = await YSCodeImage.scanCode();
  198. setState(() {});
  199. },
  200. child: Image.asset(YSColors.imageStyle(context, '编组 23'),height: hsp(15),width: hsp(15),),
  201. ),valueSetter: (value){
  202. _address = value;
  203. },value: _address,),
  204. SizedBox(
  205. height: hsp(50),
  206. child: Row(
  207. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  208. children: [
  209. Text(S.current.ZHUANZHANGSHULIANG,style: YSColors.contentStyle(context),),
  210. GestureDetector(
  211. onTap: (){
  212. Navigator.of(context).push(
  213. CupertinoPageRoute(builder: (context){
  214. return const YSWalletMineTokenChoose();
  215. })
  216. ).then((value){
  217. if(value!=null){
  218. _token = value;
  219. _getGasPrice();
  220. setState(() {});
  221. }
  222. });
  223. },
  224. behavior: HitTestBehavior.opaque,
  225. child: Row(
  226. children: [
  227. Text(_token['name']??'',style: YSColors.content3Style(context),),
  228. Icon(Icons.chevron_right,size: hsp(20),color: YSColors.shadowColor(context),)
  229. ],
  230. ),
  231. )
  232. ],
  233. ),
  234. ),
  235. Container(
  236. decoration: BoxDecoration(
  237. color: YSColors.containColor(context),
  238. borderRadius: const BorderRadius.all(Radius.circular(10))
  239. ),
  240. child: Column(
  241. children: [
  242. YSInputView(tips: S.current.QINGSHURUZHUANZHANGSHULIANG,isNumber: true,valueSetter: (value){
  243. _number = value;
  244. }),
  245. Divider(color: YSColors.lineColor(context),height: hsp(1),indent: hsp(15),endIndent: hsp(15),),
  246. if(_token.isNotEmpty)Container(
  247. height: hsp(50),
  248. padding: EdgeInsets.only(left: hsp(15),right: hsp(15)),
  249. child: Row(
  250. children: [
  251. Text(S.current.ZHANGHUYUE,style: YSColors.contentStyle(context),),
  252. Expanded(
  253. child: Container(
  254. alignment: Alignment.centerRight,
  255. child: _token['address']==YSData().wallet['public']?YSBalanceView(
  256. public: YSData().wallet['public'],
  257. style: YSColors.content3Style(context),
  258. ):YSBalanceView(
  259. public: _token['address'],
  260. style: YSColors.content3Style(context),
  261. type: 1,
  262. walletAddress: YSData().wallet['public'],
  263. key: Key(_token['address']),
  264. ),
  265. )
  266. )
  267. ],
  268. ),
  269. )
  270. ],
  271. ),
  272. ),
  273. SizedBox(
  274. height: hsp(40),
  275. child: Row(
  276. children: [
  277. Text('${S.current.WANGLUOFEI} ',style: YSColors.contentStyle(context),),
  278. GestureDetector(
  279. onTap: (){},
  280. child: Image.asset(YSColors.imageStyle(context, '说明 (3)'),height: hsp(15),width: hsp(15),),
  281. )
  282. ],
  283. ),
  284. ),
  285. Container(
  286. padding: EdgeInsets.all(hsp(15)),
  287. decoration: BoxDecoration(
  288. color: YSColors.containColor(context),
  289. borderRadius: const BorderRadius.all(Radius.circular(10))
  290. ),
  291. child: GridView.builder(
  292. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  293. crossAxisCount: 4,
  294. childAspectRatio: ((ysWidth(context)-hsp(100))/4)/hsp(85),
  295. crossAxisSpacing: hsp(10)
  296. ),
  297. itemBuilder: (context,index){
  298. Map item = {};
  299. if(index<_netArray.length){
  300. item = _netArray[index];
  301. }
  302. return GestureDetector(
  303. onTap: (){
  304. if(item.isEmpty){
  305. }else{
  306. _fee = item['price'];
  307. _selectedIndex = index;
  308. setState(() {});
  309. }
  310. },
  311. behavior: HitTestBehavior.opaque,
  312. child: Container(
  313. alignment: Alignment.center,
  314. decoration: BoxDecoration(
  315. border: Border.all(color: const Color(0xFFE9EEFF),width: hsp(1)),
  316. borderRadius: const BorderRadius.all(Radius.circular(5))
  317. ),
  318. padding: EdgeInsets.only(top: hsp(5)),
  319. child: item.isEmpty?Center(
  320. child: Column(
  321. mainAxisSize: MainAxisSize.min,
  322. children: [
  323. Image.asset(YSColors.imageStyle(context, '编组 3'),height: hsp(25),width: hsp(25),),
  324. Padding(
  325. padding: EdgeInsets.only(top: hsp(5)),
  326. child: Text(S.current.ZIDINGYI,style: TextStyle(color: YSColors.shadowColor(context),fontSize: zsp(12)),),
  327. )
  328. ],
  329. )
  330. ):Column(
  331. mainAxisSize: MainAxisSize.min,
  332. children: [
  333. Image.asset(YSColors.imageStyle(context, item['image']),height: hsp(20),width: hsp(20),),
  334. Padding(
  335. padding: EdgeInsets.only(top: hsp(2),bottom: hsp(2)),
  336. child: SizedBox(
  337. height: hsp(10),
  338. child: Text(item['speed'],style: TextStyle(color: YSColors.shadowColor(context),fontSize: zsp(8)),),
  339. ),
  340. ),
  341. SizedBox(
  342. height: hsp(15),//\n\$${item['dollar']}
  343. child: Text('${item['price']}',style: TextStyle(color: YSColors.shadowColor(context),fontSize: zsp(8)),textAlign: TextAlign.center,),
  344. ),
  345. Container(
  346. height: hsp(25),
  347. color: Color(_selectedIndex==index?0xFFE9EEFF:0xFFF6F6F6),
  348. margin: EdgeInsets.only(top: hsp(4)),
  349. alignment: Alignment.center,
  350. child: Text(item['time'],style: TextStyle(color: YSColors.shadowColor(context),fontSize: zsp(8)),),
  351. )
  352. ],
  353. ),
  354. ),
  355. );
  356. },
  357. shrinkWrap: true,
  358. padding: const EdgeInsets.all(0),
  359. physics: const NeverScrollableScrollPhysics(),
  360. itemCount: _netArray.length,
  361. ),
  362. ),
  363. // Container(
  364. // height: hsp(50),
  365. // width: ysWidth(context),
  366. // alignment: Alignment.centerRight,
  367. // child: GestureDetector(
  368. // onTap: (){},
  369. // behavior: HitTestBehavior.opaque,
  370. // child: Row(
  371. // mainAxisSize: MainAxisSize.min,
  372. // children: [
  373. // Text('高级模式',style: YSColors.content3Style(context),),
  374. // Icon(Icons.chevron_right,size: hsp(20),color: YSColors.shadowColor(context),)
  375. // ],
  376. // ),
  377. // )
  378. // ,
  379. // )
  380. ],
  381. ),
  382. GestureDetector(
  383. onTap: () {
  384. if(_address.isEmpty){
  385. ysFlutterToast('请选择转账地址');
  386. return;
  387. }
  388. if(_address.isEmpty){
  389. ysFlutterToast('请完善接收地址');
  390. return;
  391. }
  392. if(_number.isEmpty){
  393. ysFlutterToast('请填写转账数量');
  394. return;
  395. }
  396. ysShowCenterAlertView(context, YSLoadView(funAction: _transferData,wallet: YSData().wallet,valueSetter: (type){
  397. if(type==1&&_hash.isNotEmpty){
  398. Map map = {
  399. 'from_addr':YSData().wallet['public'],
  400. 'to_addr':_address,
  401. 'hash':_hash,
  402. 'status':'2',
  403. 'type':'2',
  404. 'nonce':'0',
  405. 'amount':_number
  406. };
  407. if(!mounted)return;
  408. Navigator.pop(context);
  409. Navigator.of(context).push(
  410. CupertinoPageRoute(builder: (context){
  411. return YSTansDetail(item: map,tokenAddress: _token['address'],);
  412. })
  413. );
  414. }
  415. },),isTrans: false);
  416. },
  417. child: Container(
  418. height: hsp(50),
  419. decoration: BoxDecoration(
  420. color: YSColors.buttonColor(context),
  421. borderRadius: const BorderRadius.all(Radius.circular(10))
  422. ),
  423. alignment: Alignment.center,
  424. child: Text(S.current.QUEDING,style: YSColors.buttonStyle(context),),
  425. ),
  426. )
  427. ],
  428. ),
  429. ),
  430. );
  431. }
  432. Future<bool> _transferData() async{
  433. Wbe3Api? web = await Wbe3Api().getInstances();
  434. String public = YSData().wallet['public'];
  435. String private = YSData().wallet['private'];
  436. String tokenAddress = _token['address'];
  437. String address = _address;
  438. if(public.substring(0,1)=='T'){
  439. if(!mounted) return false;
  440. if(tokenAddress==public){
  441. String resultStr = await YSTron.transferData(context, from: public, to: address, private: private, amount: _number,);
  442. if(resultStr.isNotEmpty){
  443. Map map = {};
  444. map['public'] = YSData().wallet['public']??'';
  445. map['balance'] = await YSTron.getBalance(YSData().wallet['public']);
  446. if(!mounted)return false;
  447. YSBalanceManager.notifier(context,map);
  448. insertTable(resultStr);
  449. _hash = resultStr;
  450. return true;
  451. }else{
  452. return false;
  453. }
  454. }else{
  455. String resultStr = await YSTron.transferContractData(
  456. context,
  457. from: public,
  458. to: address,
  459. private: private,
  460. amount: _number,
  461. tokenId: _token['hid'],
  462. tokenAddress: tokenAddress
  463. );
  464. if(resultStr.isNotEmpty){
  465. Map map = {};
  466. map['public'] = YSData().wallet['public']??'';
  467. map['balance'] = await YSTron.getBalance(YSData().wallet['public']);
  468. if(!mounted)return false;
  469. YSBalanceManager.notifier(context,map);
  470. insertTable(resultStr);
  471. _hash = resultStr;
  472. return true;
  473. }else{
  474. return false;
  475. }
  476. }
  477. }else if(public.substring(0,1)=='3'){
  478. String resultStr = '';
  479. // LogUtil.d(tokenAddress);
  480. // LogUtil.d(public);
  481. // return false;
  482. if(true){//tokenAddress==public
  483. resultStr = await YSBtc.transferData3(from: public, to: address, private: private,amount: _number);
  484. }else{
  485. resultStr = await YSBtc.transferContractData3(from: public, to: address, private: private,amount: _number);
  486. }
  487. if(resultStr.isNotEmpty){
  488. Map map = {};
  489. map['public'] = YSData().wallet['public']??'';
  490. map['balance'] = await YSBtc.getBalance(YSData().wallet['public']);
  491. if(!mounted)return false;
  492. YSBalanceManager.notifier(context,map);
  493. insertTable(resultStr);
  494. _hash = resultStr;
  495. return true;
  496. }else{
  497. return false;
  498. }
  499. }else{
  500. if(tokenAddress==public){
  501. var feeI = _fee*pow(10, 9)/_gas;
  502. String feeS = '${feeI * pow(10, 9) ~/1}';
  503. var result = await web?.signETHTransaction(public, address, private, _number,'$_gas',fee: feeS);
  504. String resultStr = '$result';
  505. if(resultStr.isNotEmpty){
  506. Map map = {};
  507. map['public'] = YSData().wallet['public']??'';
  508. map['balance'] = await Wbe3Api.getBalance(YSData().wallet['public']);
  509. if(!mounted)return false;
  510. YSBalanceManager.notifier(context,map);
  511. insertTable(resultStr);
  512. _hash = resultStr;
  513. return true;
  514. }else{
  515. return false;
  516. }
  517. }else{
  518. bool? isCheck = await web?.setContaract(tokenAddress,decimal: 18);
  519. if(isCheck!){
  520. var feeI = _fee*pow(10, 9)/_gas;
  521. String feeS = '${feeI * pow(10, 9) ~/1}';
  522. var result = await web?.tokenTransfer(public, address, private, feeS,_number,'$_gas');
  523. String resultStr = '$result';
  524. if(!mounted)return false;
  525. if(resultStr.isNotEmpty){
  526. Map map = {};
  527. map['public'] = tokenAddress;
  528. map['balance'] = await Wbe3Api().getTokenBalance(public,tokenAddress);
  529. if(!mounted)return false;
  530. YSBalanceManager.notifier(context,map);
  531. insertTable(resultStr);
  532. _hash = resultStr;
  533. return true;
  534. }else{
  535. return false;
  536. }
  537. }
  538. }
  539. }
  540. return false;
  541. }
  542. insertTable(resultStr) async{
  543. String public = YSData().wallet['public'];
  544. String address = _address;
  545. YSTansTable ysTansTable = YSTansTable().init();
  546. await ysTansTable.rawInsert(from: public, to: address, hash: resultStr, status: '2', type: '2', nonce: '0', amount: _number);
  547. }
  548. }