evm.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. import 'dart:convert';
  2. import 'package:flutter/material.dart';
  3. import 'package:polkawallet_sdk/api/types/addressIconData.dart';
  4. import 'package:polkawallet_sdk/ethers/apiEthers.dart';
  5. import 'package:polkawallet_sdk/polkawallet_sdk.dart';
  6. import 'package:polkawallet_sdk/storage/keyringEVM.dart';
  7. import 'package:polkawallet_sdk/storage/types/ethWalletData.dart';
  8. import 'package:polkawallet_sdk_example/pages/keyring.dart';
  9. class EVMPage extends StatefulWidget {
  10. EVMPage(this.sdk, this.keyring, this.showResult);
  11. final WalletSDK sdk;
  12. final KeyringEVM keyring;
  13. final Function(BuildContext, String, String) showResult;
  14. static const String route = '/keyring/evm';
  15. @override
  16. _EVMPageState createState() => _EVMPageState();
  17. }
  18. class _EVMPageState extends State<EVMPage> {
  19. final String _testJson = '''{
  20. "crypto": {"cipher": "aes-128-ctr", "cipherparams": {"iv": "3be45c336ce8cd771061e3b5ec9460ec"}, "ciphertext": "b4e181f629e480d4073edfe6f0ad7bc8c201ac3975eb0232150e4550f59af1c0", "kdf": "scrypt", "kdfparams": {"dklen": 32, "n": 8192, "r": 8, "p": 1, "salt": "4771ff99bf695bab6d292330678a800f8acb1831134678df45b6911fab94f38c"}, "mac": "ed5cec3eed91ab251650657cff87c693a2672413658ff7da4c2f38598f21984a"},
  21. "id": "3228f3c9-dfee-4e65-9569-5c8a7afc3921",
  22. "version": 3,
  23. "address": "0x4b248f45dfbea07de1bbd69180f6695b78250caf"
  24. }''';
  25. final String _testPass = 'a123456';
  26. EthWalletData? _testAcc;
  27. bool _submitting = false;
  28. Future<void> _generateMnemonic() async {
  29. setState(() {
  30. _submitting = true;
  31. });
  32. final AddressIconDataWithMnemonic seed =
  33. await widget.sdk.ethers.generateMnemonic();
  34. widget.showResult(context, 'generateMnemonic', seed.mnemonic!);
  35. setState(() {
  36. _submitting = false;
  37. });
  38. }
  39. Future<void> _getAccountList() async {
  40. final List<EthWalletData> ls = widget.keyring.keyPairs;
  41. widget.showResult(
  42. context,
  43. 'getAccountList',
  44. JsonEncoder.withIndent(' ')
  45. .convert(ls.map((e) => '${e.name}: ${e.address}').toList()),
  46. );
  47. }
  48. Future<void> _getDecryptedSeed() async {
  49. if (_testAcc == null) {
  50. widget.showResult(
  51. context,
  52. 'getDecryptedSeeds',
  53. 'should import keyPair to init test account.',
  54. );
  55. return;
  56. }
  57. setState(() {
  58. _submitting = true;
  59. });
  60. final seed =
  61. await widget.sdk.ethers.getDecryptedSeed(widget.keyring, _testPass);
  62. // await widget.sdk.evm.getDecryptedSeed(widget.keyring, 'a654321');
  63. widget.showResult(
  64. context,
  65. 'getDecryptedSeeds',
  66. seed == null
  67. ? 'null'
  68. : JsonEncoder.withIndent(' ').convert({
  69. 'address': _testAcc?.address,
  70. 'type': seed.type,
  71. 'seed': seed.seed,
  72. 'error': seed.error,
  73. }),
  74. );
  75. setState(() {
  76. _submitting = false;
  77. });
  78. }
  79. Future<void> _importFromMnemonic() async {
  80. setState(() {
  81. _submitting = true;
  82. });
  83. final json = await widget.sdk.ethers.importAccount(
  84. keyType: EVMKeyType.mnemonic,
  85. key:
  86. 'wing know chapter eight shed lens mandate lake twenty useless bless glory',
  87. name: 'testName01',
  88. password: _testPass,
  89. );
  90. print(json);
  91. final acc = await widget.sdk.ethers.addAccount(
  92. widget.keyring,
  93. keyType: EVMKeyType.mnemonic,
  94. acc: json,
  95. password: _testPass,
  96. );
  97. widget.showResult(
  98. context,
  99. 'importFromMnemonic',
  100. JsonEncoder.withIndent(' ').convert(acc.toJson()),
  101. );
  102. setState(() {
  103. _submitting = false;
  104. _testAcc = acc;
  105. });
  106. }
  107. Future<void> _importFromPrivateKey() async {
  108. setState(() {
  109. _submitting = true;
  110. });
  111. final json = await widget.sdk.ethers.importAccount(
  112. keyType: EVMKeyType.privateKey,
  113. key: '0x2defc5ff7c700eb3a39a702e9b38534e8ea3419b93b1836dc6ccc891ce359290',
  114. name: 'testName02',
  115. password: _testPass,
  116. );
  117. print(json);
  118. final acc = await widget.sdk.ethers.addAccount(
  119. widget.keyring,
  120. keyType: EVMKeyType.privateKey,
  121. acc: json,
  122. password: _testPass,
  123. );
  124. widget.showResult(
  125. context,
  126. 'importFromPrivateKey',
  127. JsonEncoder.withIndent(' ').convert(acc.toJson()),
  128. );
  129. setState(() {
  130. _submitting = false;
  131. _testAcc = acc;
  132. });
  133. }
  134. Future<void> _importFromKeystore() async {
  135. setState(() {
  136. _submitting = true;
  137. });
  138. final json = await widget.sdk.ethers.importAccount(
  139. keyType: EVMKeyType.keystore,
  140. key: _testJson,
  141. name: 'testName03',
  142. password: _testPass,
  143. );
  144. final acc = await widget.sdk.ethers.addAccount(
  145. widget.keyring,
  146. keyType: EVMKeyType.keystore,
  147. acc: json,
  148. password: _testPass,
  149. );
  150. widget.showResult(
  151. context,
  152. 'importFromKeystore',
  153. JsonEncoder.withIndent(' ').convert(acc.toJson()),
  154. );
  155. setState(() {
  156. _submitting = false;
  157. _testAcc = acc;
  158. });
  159. }
  160. Future<void> _deleteAccount() async {
  161. if (_testAcc == null) {
  162. widget.showResult(
  163. context,
  164. 'deleteAccount',
  165. 'should import keyPair to init test account.',
  166. );
  167. return;
  168. }
  169. setState(() {
  170. _submitting = true;
  171. });
  172. await widget.sdk.ethers.deleteAccount(widget.keyring, _testAcc!);
  173. widget.showResult(
  174. context,
  175. 'deleteAccount',
  176. 'ok',
  177. );
  178. setState(() {
  179. _submitting = false;
  180. });
  181. }
  182. Future<void> _checkPassword() async {
  183. if (_testAcc == null) {
  184. widget.showResult(
  185. context,
  186. 'checkPassword',
  187. 'should import keyPair to init test account.',
  188. );
  189. return;
  190. }
  191. setState(() {
  192. _submitting = true;
  193. });
  194. final bool passed =
  195. await widget.sdk.ethers.checkPassword(_testAcc!, _testPass);
  196. // await widget.sdk.evm.checkPassword(_testAcc, 'a654321');
  197. widget.showResult(
  198. context,
  199. 'checkPassword',
  200. passed.toString(),
  201. );
  202. setState(() {
  203. _submitting = false;
  204. });
  205. }
  206. Future<void> _changePassword() async {
  207. if (_testAcc == null) {
  208. widget.showResult(
  209. context,
  210. 'changePassword',
  211. 'should import keyPair to init test account.',
  212. );
  213. return;
  214. }
  215. setState(() {
  216. _submitting = true;
  217. });
  218. final res = await widget.sdk.ethers
  219. // .changePassword(widget.keyring, _testPass, 'a654321');
  220. .changePassword(widget.keyring, 'a654321', _testPass);
  221. widget.showResult(
  222. context,
  223. 'changePassword',
  224. res == null ? 'null' : JsonEncoder.withIndent(' ').convert(res.toJson()),
  225. );
  226. setState(() {
  227. _submitting = false;
  228. _testAcc = res;
  229. });
  230. }
  231. Future<void> _changeName() async {
  232. if (_testAcc == null) {
  233. widget.showResult(
  234. context,
  235. 'changeName',
  236. 'should import keyPair to init test account.',
  237. );
  238. return;
  239. }
  240. setState(() {
  241. _submitting = true;
  242. });
  243. final res = await widget.sdk.ethers.changeName(widget.keyring, 'newName');
  244. widget.showResult(
  245. context,
  246. 'changeName', JsonEncoder.withIndent(' ').convert(res.toJson()),
  247. );
  248. setState(() {
  249. _submitting = false;
  250. });
  251. }
  252. @override
  253. void initState() {
  254. super.initState();
  255. WidgetsBinding.instance.addPostFrameCallback((_) {
  256. if (widget.keyring.keyPairs.length > 0) {
  257. setState(() {
  258. _testAcc = widget.keyring.keyPairs[0];
  259. });
  260. }
  261. });
  262. }
  263. @override
  264. Widget build(BuildContext context) {
  265. return Scaffold(
  266. appBar: AppBar(
  267. title: Text('keyring API'),
  268. ),
  269. body: SafeArea(
  270. child: ListView(
  271. children: [
  272. // Padding(
  273. // padding: EdgeInsets.all(16),
  274. // child: Column(
  275. // crossAxisAlignment: CrossAxisAlignment.start,
  276. // children: [
  277. // Text('address ss58Format: ${widget.keyring.ss58}'),
  278. // Row(
  279. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  280. // children: [
  281. // RaisedButton(
  282. // child: Text('Polkadot: 0'),
  283. // color:
  284. // _ss58 == 0 ? Theme.of(context).primaryColor : null,
  285. // onPressed: () => _setSS58(0),
  286. // ),
  287. // RaisedButton(
  288. // child: Text('Kusama: 2'),
  289. // color:
  290. // _ss58 == 2 ? Theme.of(context).primaryColor : null,
  291. // onPressed: () => _setSS58(2),
  292. // ),
  293. // RaisedButton(
  294. // child: Text('Substrate: 42'),
  295. // color:
  296. // _ss58 == 42 ? Theme.of(context).primaryColor : null,
  297. // onPressed: () => _setSS58(42),
  298. // )
  299. // ],
  300. // )
  301. // ],
  302. // ),
  303. // ),
  304. // Divider(),
  305. ListTile(
  306. title: Text('getAccountList'),
  307. subtitle: Text('''
  308. sdk.api.keyring.accountList'''),
  309. trailing: SubmitButton(
  310. submitting: _submitting,
  311. call: _getAccountList,
  312. ),
  313. ),
  314. Divider(),
  315. ListTile(
  316. title: Text('generateMnemonic'),
  317. subtitle: Text('sdk.api.keyring.generateMnemonic()'),
  318. trailing: SubmitButton(
  319. submitting: _submitting,
  320. call: _generateMnemonic,
  321. ),
  322. ),
  323. Divider(),
  324. ListTile(
  325. title: Text('importFromMnemonic'),
  326. subtitle: Text('''
  327. sdk.api.keyring.importAccount(
  328. keyType: KeyType.mnemonic,
  329. key: 'wing know chapter eight shed lens mandate lake twenty useless bless glory',
  330. name: 'testName01',
  331. password: 'a123456',
  332. )'''),
  333. trailing: SubmitButton(
  334. submitting: _submitting,
  335. call: _importFromMnemonic,
  336. ),
  337. ),
  338. Divider(),
  339. ListTile(
  340. title: Text('importFromPrivateKey'),
  341. subtitle: Text('''
  342. sdk.api.keyring.importAccount(
  343. keyType: KeyType.privateKey,
  344. key: 'Alice',
  345. name: 'testName02',
  346. password: 'a123456',
  347. )'''),
  348. trailing: SubmitButton(
  349. submitting: _submitting,
  350. call: _importFromPrivateKey,
  351. ),
  352. ),
  353. Divider(),
  354. ListTile(
  355. title: Text('importFromKeystore'),
  356. subtitle: Text('''
  357. sdk.api.keyring.importAccount(
  358. keyType: KeyType.keystore,
  359. key: '{xxx...xxx}',
  360. name: 'testName03',
  361. password: 'a123456',
  362. )'''),
  363. trailing: SubmitButton(
  364. submitting: _submitting,
  365. call: _importFromKeystore,
  366. ),
  367. ),
  368. Divider(),
  369. ListTile(
  370. title: Text('getDecryptedSeed'),
  371. subtitle: Text('''
  372. sdk.api.keyring.getDecryptedSeed(
  373. '${_testAcc?.toString()}',
  374. 'a123456',
  375. )'''),
  376. trailing: SubmitButton(
  377. submitting: _submitting,
  378. call: _getDecryptedSeed,
  379. ),
  380. ),
  381. Divider(),
  382. ListTile(
  383. title: Text('deleteAccount'),
  384. subtitle: Text('''
  385. sdk.api.keyring.deleteAccount'''),
  386. trailing: SubmitButton(
  387. submitting: _submitting,
  388. call: _deleteAccount,
  389. ),
  390. ),
  391. Divider(),
  392. ListTile(
  393. title: Text('checkPassword'),
  394. subtitle: Text('''
  395. sdk.api.keyring.checkPassword(
  396. '${_testAcc?.toString()}',
  397. 'a123456',
  398. )'''),
  399. trailing: SubmitButton(
  400. submitting: _submitting,
  401. call: _checkPassword,
  402. ),
  403. ),
  404. Divider(),
  405. ListTile(
  406. title: Text('changePassword'),
  407. subtitle: Text('''
  408. sdk.api.keyring.changePassword(
  409. '${_testAcc?.toString()}',
  410. 'a123456',
  411. 'a654321',
  412. )'''),
  413. trailing: SubmitButton(
  414. submitting: _submitting,
  415. call: _changePassword,
  416. ),
  417. ),
  418. Divider(),
  419. ListTile(
  420. title: Text('changeName'),
  421. subtitle: Text('''
  422. sdk.api.keyring.changeName(
  423. '${_testAcc?.toString()}',
  424. 'newName',
  425. )'''),
  426. trailing: SubmitButton(
  427. submitting: _submitting,
  428. call: _changeName,
  429. ),
  430. ),
  431. Divider(),
  432. ],
  433. ),
  434. ), // This trailing comma makes auto-formatting nicer for build methods.
  435. );
  436. }
  437. }