From 6af9199a76be71d84868d92428dbbc360f0d2b0c Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 16 Aug 2022 01:44:45 +0200 Subject: [PATCH 01/19] add methode to import Cs account --- lib/providers/substrate_sdk.dart | 50 +++++++++++++++++++++++++++++++- lib/screens/home.dart | 2 ++ pubspec.lock | 4 +-- pubspec.yaml | 2 ++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 4d476dd..09c90c4 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -1,3 +1,4 @@ +import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; @@ -13,7 +14,8 @@ import 'package:polkawallet_sdk/storage/keyring.dart'; import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:provider/provider.dart'; import 'package:truncate/truncate.dart'; -// import 'package:web_socket_channel/io.dart'; +import 'package:pointycastle/pointycastle.dart' as pc; +import "package:hex/hex.dart"; class SubstrateSdk with ChangeNotifier { final WalletSDK sdk = WalletSDK(); @@ -368,6 +370,52 @@ class SubstrateSdk with ChangeNotifier { return nodeParams; } + Future csToV2(String salt, String password) async { + final scrypt = pc.KeyDerivator('scrypt'); + + scrypt.init( + pc.ScryptParameters( + 4096, + 16, + 1, + 32, + Uint8List.fromList(salt.codeUnits), + ), + ); + final rawSeed = scrypt.process(Uint8List.fromList(password.codeUnits)); + final rawSeedHex = '0x${HEX.encode(rawSeed)}'; + + // final newAddress1 = await sdk.api.keyring.addressFromRawSeed(ss58, + // cryptoType: CryptoType.ed25519, rawSeed: '0x$rawSeedString'); + + // log.d('csconvert address: ${newAddress1.address}'); + + final json = await sdk.api.keyring + .importAccount(keyring, + keyType: KeyType.rawSeed, + key: rawSeedHex, + name: 'test', + password: 'password', + derivePath: '', + cryptoType: CryptoType.ed25519) + .catchError((e) { + importIsLoading = false; + notifyListeners(); + }); + + final keypair = await sdk.api.keyring.addAccount( + keyring, + keyType: KeyType.rawSeed, + acc: json!, + password: password, + ); + await sdk.api.keyring.deleteAccount(keyring, keypair); + + // final keypair2 = KeyPairData.fromJson(json as Map); + + log.d(keypair.address); + } + Future importAccount( {String mnemonic = '', String derivePath = '', diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 4157045..7fe309e 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -39,6 +39,8 @@ class HomeScreen extends StatelessWidget { final bool isWalletsExists = myWalletProvider.checkIfWalletExist(); + // sub.csToV2('test', 'test'); + isTall = false; ratio = 1; if (MediaQuery.of(context).size.height >= 930) { diff --git a/pubspec.lock b/pubspec.lock index 017b92e..949cbc3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -557,7 +557,7 @@ packages: source: hosted version: "2.1.0" hex: - dependency: transitive + dependency: "direct main" description: name: hex url: "https://pub.dartlang.org" @@ -1052,7 +1052,7 @@ packages: source: hosted version: "2.1.2" pointycastle: - dependency: transitive + dependency: "direct main" description: name: pointycastle url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 7ae857b..bee3f4a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -71,6 +71,8 @@ dependencies: easy_localization: ^3.0.1 flutter_markdown: ^0.6.10+2 dropdown_button2: ^1.6.3 + pointycastle: ^3.6.1 + hex: ^0.2.0 dev_dependencies: # flutter_launcher_icons: ^0.9.2 From 4d027e05556197fff76d2ec8cd9cc941cf14324e Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 16 Aug 2022 16:13:11 +0200 Subject: [PATCH 02/19] fix: import scanned wallets --- lib/providers/generate_wallets.dart | 6 +- lib/providers/substrate_sdk.dart | 87 ++++++++++++++--------------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index b47e463..a1292ba 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -409,7 +409,9 @@ class GenerateWalletsProvider with ChangeNotifier { ? 'currentWallet'.tr() : '${'wallet'.tr()} ${scanedValidWalletNumber + 1}'; await sub.importAccount( - derivePath: '//$derivationNbr', password: pin.text); + mnemonic: generatedMnemonic!, + derivePath: '//$derivationNbr', + password: pin.text); WalletData myWallet = WalletData( version: dataVersion, @@ -445,7 +447,7 @@ class GenerateWalletsProvider with ChangeNotifier { "${addressData.address!}: ${balance['transferableBalance']} $currencyName"); if (balance['transferableBalance'] != 0) { String walletName = 'myRootWallet'.tr(); - await sub.importAccount(password: pin.text); + await sub.importAccount(mnemonic: generatedMnemonic!, password: pin.text); WalletData myWallet = WalletData( version: dataVersion, diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 09c90c4..69113db 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -370,52 +370,6 @@ class SubstrateSdk with ChangeNotifier { return nodeParams; } - Future csToV2(String salt, String password) async { - final scrypt = pc.KeyDerivator('scrypt'); - - scrypt.init( - pc.ScryptParameters( - 4096, - 16, - 1, - 32, - Uint8List.fromList(salt.codeUnits), - ), - ); - final rawSeed = scrypt.process(Uint8List.fromList(password.codeUnits)); - final rawSeedHex = '0x${HEX.encode(rawSeed)}'; - - // final newAddress1 = await sdk.api.keyring.addressFromRawSeed(ss58, - // cryptoType: CryptoType.ed25519, rawSeed: '0x$rawSeedString'); - - // log.d('csconvert address: ${newAddress1.address}'); - - final json = await sdk.api.keyring - .importAccount(keyring, - keyType: KeyType.rawSeed, - key: rawSeedHex, - name: 'test', - password: 'password', - derivePath: '', - cryptoType: CryptoType.ed25519) - .catchError((e) { - importIsLoading = false; - notifyListeners(); - }); - - final keypair = await sdk.api.keyring.addAccount( - keyring, - keyType: KeyType.rawSeed, - acc: json!, - password: password, - ); - await sdk.api.keyring.deleteAccount(keyring, keypair); - - // final keypair2 = KeyPairData.fromJson(json as Map); - - log.d(keypair.address); - } - Future importAccount( {String mnemonic = '', String derivePath = '', @@ -593,6 +547,47 @@ class SubstrateSdk with ChangeNotifier { return await sdk.api.keyring.checkMnemonicValid(mnemonic); } + Future csToV2(String salt, String password) async { + final scrypt = pc.KeyDerivator('scrypt'); + + scrypt.init( + pc.ScryptParameters( + 4096, + 16, + 1, + 32, + Uint8List.fromList(salt.codeUnits), + ), + ); + final rawSeed = scrypt.process(Uint8List.fromList(password.codeUnits)); + final rawSeedHex = '0x${HEX.encode(rawSeed)}'; + + // Just get the address without keystore + // final newAddress1 = await sdk.api.keyring.addressFromRawSeed(ss58, + // cryptoType: CryptoType.ed25519, rawSeed: '0x$rawSeedString'); + // log.d('csconvert address: ${newAddress1.address}'); + + final json = await sdk.api.keyring.importAccount(keyring, + keyType: KeyType.rawSeed, + key: rawSeedHex, + name: 'test', + password: 'password', + derivePath: '', + cryptoType: CryptoType.ed25519); + + final keypair = await sdk.api.keyring.addAccount( + keyring, + keyType: KeyType.rawSeed, + acc: json!, + password: password, + ); + await sdk.api.keyring.deleteAccount(keyring, keypair); + + // final keypair2 = KeyPairData.fromJson(json as Map); + + log.d(keypair.address); + } + ////////////////////////////////////// ///////// 5: CALLS EXECUTION ///////// ////////////////////////////////////// From 4a7f68626da05f628a7e0884a9e4c7d438a70d0d Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 16 Aug 2022 19:59:53 +0200 Subject: [PATCH 03/19] fix: batch cert and validate membership --- lib/providers/substrate_sdk.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 69113db..ecb1288 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -674,8 +674,8 @@ class SubstrateSdk with ChangeNotifier { 'batchAll', sender, ); - final tx1 = 'cert.addCert($fromIndex, $toIndex)'; - final tx2 = 'identity.validateIdentity($toIndex)'; + final tx1 = 'api.tx.cert.addCert($fromIndex, $toIndex)'; + final tx2 = 'api.tx.identity.validateIdentity($toIndex)'; rawParams = '[[$tx1, $tx2]]'; } else { From 1995aaf4fb1fba6362602b66ea593df4792f3987 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 16 Aug 2022 20:00:22 +0200 Subject: [PATCH 04/19] bump 0.0.9+22 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bee3f4a..f55e8cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9+21 +version: 0.0.9+22 environment: sdk: '>=2.12.0 <3.0.0' From e8acb59f3e86918ca83a9cc9a7e38e3ff00f9b8c Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 16 Aug 2022 21:50:35 +0200 Subject: [PATCH 05/19] add ss58 test --- lib/providers/substrate_sdk.dart | 1 - lib/screens/home.dart | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index ecb1288..05338e2 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -510,7 +510,6 @@ class SubstrateSdk with ChangeNotifier { BuildContext context, String address, int number, String password) async { final keypair = getKeypair(address); - //TODO: fix null keypair after used chest import log.d('tatatata $address $number $password ${keypair.encoded}'); final seedMap = diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 7fe309e..297121b 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -40,6 +40,7 @@ class HomeScreen extends StatelessWidget { final bool isWalletsExists = myWalletProvider.checkIfWalletExist(); // sub.csToV2('test', 'test'); + // sub.getSs58Prefix(); isTall = false; ratio = 1; From 0687ae072f8600e438718514ea533bf09ae28b75 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 17 Aug 2022 17:50:05 +0200 Subject: [PATCH 06/19] get onchain consts; fix batch validate membership --- lib/providers/generate_wallets.dart | 4 +- lib/providers/substrate_sdk.dart | 70 ++++++++++++++++++----------- lib/screens/home.dart | 1 + 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index a1292ba..caeb235 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -390,7 +390,7 @@ class GenerateWalletsProvider with ChangeNotifier { for (var derivationNbr in [for (var i = 0; i < numberScan; i += 1) i]) { final addressData = await sub.sdk.api.keyring.addressFromMnemonic( - sub.ss58, + sub.currencyParameters['ss58']!, cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!, derivePath: '//$derivationNbr'); @@ -435,7 +435,7 @@ class GenerateWalletsProvider with ChangeNotifier { } Future scanRootBalance(SubstrateSdk sub, int currentChestNumber) async { - final addressData = await sub.sdk.api.keyring.addressFromMnemonic(sub.ss58, + final addressData = await sub.sdk.api.keyring.addressFromMnemonic(sub.currencyParameters['ss58']!, cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!); final balance = await sub.getBalance(addressData.address!).timeout( diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 05338e2..8e5589d 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -29,7 +29,8 @@ class SubstrateSdk with ChangeNotifier { bool isLoadingEndpoint = false; String debugConnection = ''; String transactionStatus = ''; - int ss58 = 42; + final int initSs58 = 42; + Map currencyParameters = {}; ///////////////////////////////////// ////////// 1: API METHODS /////////// @@ -66,6 +67,11 @@ class SubstrateSdk with ChangeNotifier { return await sdk.webView!.evalJavascript('api.query.$call'); } + Future getStorageConst(String call) async { + return (await sdk.webView! + .evalJavascript('api.consts.$call', wrapPromise: false))[0]; + } + TxSenderData _setSender() { return TxSenderData( keyring.current.address, @@ -108,12 +114,6 @@ class SubstrateSdk with ChangeNotifier { return 0; } - Future> getParameters() async { - final currencyParameters = - await getStorage('parameters.parametersStorage()') ?? {}; - return currencyParameters; - } - Future hasAccountConsumers(String address) async { final accountInfo = await getStorage('system.account("$address")'); final consumers = accountInfo['consumers']; @@ -136,6 +136,8 @@ class SubstrateSdk with ChangeNotifier { // } Future> getBalance(String address) async { + // log.d('currencyParameters: $currencyParameters'); + if (!nodeConnected) { return { 'transferableBalance': 0, @@ -202,17 +204,6 @@ class SubstrateSdk with ChangeNotifier { return totalAmount; } - Future getSs58Prefix() async { - final List res = await sdk.webView!.evalJavascript( - 'api.consts.system.ss58Prefix.words', - wrapPromise: false) ?? - [42]; - - ss58 = res[0]; - log.d(ss58); - return ss58; - } - Future isMemberGet(String address) async { return await idtyStatus(address) == 'Validated'; } @@ -268,7 +259,32 @@ class SubstrateSdk with ChangeNotifier { } } - Future getCurencyName() async {} + // Future addressToPubkey(String address) async { + // await sdk.api.account.decodeAddress([address]); + // } + + // Future pubkeyToAddress(String pubkey) async { + // await sdk.api.account.encodeAddress([pubkey]); + // } + + Future initCurrencyParameters() async { + currencyParameters['ss58'] = + await getStorageConst('system.ss58Prefix.words'); + currencyParameters['minCertForMembership'] = + await getStorageConst('wot.minCertForMembership.words'); + currencyParameters['newAccountPrice'] = + await getStorageConst('account.newAccountPrice.words'); + currencyParameters['existentialDeposit'] = + await getStorageConst('balances.existentialDeposit.words'); + currencyParameters['certPeriod'] = + await getStorageConst('cert.certPeriod.words'); + currencyParameters['certMaxByIssuer'] = + await getStorageConst('cert.maxByIssuer.words'); + currencyParameters['certValidityPeriod'] = + await getStorageConst('cert.validityPeriod.words'); + + log.i('currencyParameters: $currencyParameters'); + } ///////////////////////////////////// ////// 3: SUBSTRATE CONNECTION ////// @@ -276,8 +292,8 @@ class SubstrateSdk with ChangeNotifier { Future initApi() async { sdkLoading = true; - await keyring.init([ss58]); - keyring.setSS58(ss58); + await keyring.init([initSs58]); + keyring.setSS58(initSs58); await sdk.init(keyring); sdkReady = true; @@ -356,7 +372,7 @@ class SubstrateSdk with ChangeNotifier { final n = NetworkParams(); n.name = currencyName; n.endpoint = endpoint; - n.ss58 = ss58; + n.ss58 = currencyParameters['ss58'] ?? initSs58; node.add(n); } return node; @@ -366,7 +382,7 @@ class SubstrateSdk with ChangeNotifier { final nodeParams = NetworkParams(); nodeParams.name = currencyName; nodeParams.endpoint = configBox.get('customEndpoint'); - nodeParams.ss58 = ss58; + nodeParams.ss58 = currencyParameters['ss58'] ?? initSs58; return nodeParams; } @@ -476,7 +492,8 @@ class SubstrateSdk with ChangeNotifier { } Future generateMnemonic({String lang = appLang}) async { - final gen = await sdk.api.keyring.generateMnemonic(ss58); + final gen = await sdk.api.keyring + .generateMnemonic(currencyParameters['ss58'] ?? initSs58); generatedMnemonic = gen.mnemonic!; return gen.mnemonic!; @@ -654,7 +671,8 @@ class SubstrateSdk with ChangeNotifier { String? rawParams; final toCerts = await getCerts(toAddress); - final currencyParameters = await getParameters(); + + // log.d('debug: ${currencyParameters['minCertForMembership']}'); if (toIdtyStatus == 'noid') { txInfo = TxInfoData( @@ -665,7 +683,7 @@ class SubstrateSdk with ChangeNotifier { txOptions = [toAddress]; } else if (toIdtyStatus == 'Validated' || toIdtyStatus == 'ConfirmedByOwner') { - if (toCerts[0] >= currencyParameters['wotMinCertForMembership'] && + if (toCerts[0] >= currencyParameters['minCertForMembership']! - 1 && toIdtyStatus != 'Validated') { log.i('Batch cert and membership validation'); txInfo = TxInfoData( diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 297121b..464504a 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -167,6 +167,7 @@ class HomeScreen extends StatelessWidget { sub.reload(); } else { await sub.connectNode(ctx); + await sub.initCurrencyParameters(); } }); } From 0983c1d01ebad16a6ad9311fa939e100a1773fe8 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 17 Aug 2022 23:01:20 +0200 Subject: [PATCH 07/19] add messages about offline status in onboarding screens --- assets/translations/en.json | 3 +- assets/translations/es.json | 3 +- assets/translations/fr.json | 3 +- lib/providers/substrate_sdk.dart | 11 +- lib/screens/common_elements.dart | 5 +- lib/screens/home.dart | 1 - lib/screens/myWallets/restore_chest.dart | 202 ++++++++++++----------- lib/screens/onBoarding/1.dart | 21 ++- lib/screens/onBoarding/10.dart | 139 ++++++++-------- lib/screens/onBoarding/2.dart | 17 +- lib/screens/onBoarding/3.dart | 7 +- lib/screens/onBoarding/4.dart | 19 ++- lib/screens/onBoarding/5.dart | 103 ++++++------ lib/screens/onBoarding/6.dart | 164 +++++++++--------- lib/screens/onBoarding/7.dart | 19 ++- lib/screens/onBoarding/8.dart | 19 ++- lib/screens/onBoarding/9.dart | 114 +++++++------ pubspec.yaml | 2 +- 18 files changed, 447 insertions(+), 405 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index 2b3929c..bca3f5c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -174,5 +174,6 @@ "noContacts": "You don't have any contact", "addContact": "Add\nto contacts", "removeContact": "Remove\nthis contact", - "derivationsScanProgress": "Scan address {}/{}" + "derivationsScanProgress": "Scan address {}/{}", + "youAreOffline": "You are offline..." } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index 56533d0..7d985e9 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -174,5 +174,6 @@ "noContacts": "You don't have any contact", "addContact": "Add\nto contacts", "removeContact": "Remove\nthis contact", - "derivationsScanProgress": "Scan address {}/{}" + "derivationsScanProgress": "Scan address {}/{}", + "youAreOffline": "You are offline..." } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 188027a..9f03953 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -175,5 +175,6 @@ "noContacts": "Vous n'avez aucun contact", "addContact": "Ajouter\naux contacts", "removeContact": "Supprimer\nce contact", - "derivationsScanProgress": "Scan de l'adresse {}/{}" + "derivationsScanProgress": "Scan de l'adresse {}/{}", + "youAreOffline": "Vous êtes hors ligne..." } \ No newline at end of file diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 8e5589d..d814bb7 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -69,7 +69,8 @@ class SubstrateSdk with ChangeNotifier { Future getStorageConst(String call) async { return (await sdk.webView! - .evalJavascript('api.consts.$call', wrapPromise: false))[0]; + .evalJavascript('api.consts.$call', wrapPromise: false) ?? + [null])[0]; } TxSenderData _setSender() { @@ -307,6 +308,8 @@ class SubstrateSdk with ChangeNotifier { Future connectNode(BuildContext ctx) async { HomeProvider homeProvider = Provider.of(ctx, listen: false); + MyWalletsProvider myWalletProvider = + Provider.of(ctx, listen: false); homeProvider.changeMessage("connectionPending".tr(), 0); @@ -347,7 +350,7 @@ class SubstrateSdk with ChangeNotifier { notifyListeners(); }); - // currencyName = await getCurencyName(); + await initCurrencyParameters(); notifyListeners(); homeProvider.changeMessage( "wellConnectedToNode" @@ -359,7 +362,7 @@ class SubstrateSdk with ChangeNotifier { debugConnection = res.toString(); notifyListeners(); homeProvider.changeMessage("noDuniterEndointAvailable".tr(), 0); - // snackNode(ctx, false); + if (!myWalletProvider.checkIfWalletExist()) snackNode(homeContext, false); } log.d(sdk.api.connectedNode?.endpoint); @@ -795,7 +798,7 @@ void snackNode(BuildContext context, bool isConnected) { String message; if (!isConnected) { message = - "${"noDuniterNodeAvailableTryLater".tr()}:\n${configBox.get('endpoint').first}"; + "noDuniterNodeAvailableTryLater".tr(); } else { SubstrateSdk sub = Provider.of(context, listen: false); diff --git a/lib/screens/common_elements.dart b/lib/screens/common_elements.dart index b104e67..59149f7 100644 --- a/lib/screens/common_elements.dart +++ b/lib/screens/common_elements.dart @@ -159,8 +159,7 @@ class CommonElements { } Widget offlineInfo(BuildContext context) { - // SubstrateSdk _sub = Provider.of(context, listen: false); - final double screenWidth = MediaQuery.of(context).size.width; + final double screenWidth = MediaQuery.of(homeContext).size.width; return Consumer(builder: (context, sub, _) { return Visibility( visible: !sub.nodeConnected, @@ -174,7 +173,7 @@ class CommonElements { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - "Vous êtes hors ligne...", + 'youAreOffline'.tr(), style: TextStyle(color: Colors.grey[50]), textAlign: TextAlign.center, ), diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 464504a..297121b 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -167,7 +167,6 @@ class HomeScreen extends StatelessWidget { sub.reload(); } else { await sub.connectNode(ctx); - await sub.initCurrencyParameters(); } }); } diff --git a/lib/screens/myWallets/restore_chest.dart b/lib/screens/myWallets/restore_chest.dart index ddd414b..06540a5 100644 --- a/lib/screens/myWallets/restore_chest.dart +++ b/lib/screens/myWallets/restore_chest.dart @@ -49,110 +49,114 @@ class RestoreChest extends StatelessWidget { child: Text('restoreAChest'.tr()), )), body: SafeArea( - child: Column(children: [ - SizedBox(height: isTall ? 30 : 15), - bubbleSpeak('toRestoreEnterMnemonic'.tr()), - SizedBox(height: isTall ? 30 : 15), + child: Stack(children: [ Column(children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - arrayCell(context, genW.cellController0), - arrayCell(context, genW.cellController1), - arrayCell(context, genW.cellController2), - arrayCell(context, genW.cellController3), - ]), - const SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - arrayCell(context, genW.cellController4), - arrayCell(context, genW.cellController5), - arrayCell(context, genW.cellController6), - arrayCell(context, genW.cellController7), - ]), - const SizedBox(height: 15), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - arrayCell(context, genW.cellController8), - arrayCell(context, genW.cellController9), - arrayCell(context, genW.cellController10), - arrayCell(context, genW.cellController11), - ]), - ]), - // const Spacer(), - if (genW.isSentenceComplete(context)) - Expanded( - child: Align( - alignment: Alignment.center, - child: SizedBox( - width: 410, - height: 70, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 4, - primary: orangeC, // background - onPrimary: Colors.white, // foreground - ), - onPressed: () async { - if (await sub.isMnemonicValid(genW.generatedMnemonic!)) { - genW.resetImportView(); - await Navigator.push( - context, - FaderTransition( - page: skipIntro - ? const OnboardingStepNine( - scanDerivation: true) - : const OnboardingStepSeven( - scanDerivation: true), - isFast: true), - ); - } else { - await badMnemonicPopup(context); - } - }, - child: Text( - 'restoreThisChest'.tr(), - style: const TextStyle( - fontSize: 24, fontWeight: FontWeight.w600), - ), - ), - ), - // SizedBox(height: isTall ? 80 : 80), - )) - else - Column(children: [ - const SizedBox(height: 20), - SizedBox( - width: 190, - height: 60, - child: ElevatedButton( + SizedBox(height: isTall ? 30 : 15), + bubbleSpeak('toRestoreEnterMnemonic'.tr()), + SizedBox(height: isTall ? 30 : 15), + Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + arrayCell(context, genW.cellController0), + arrayCell(context, genW.cellController1), + arrayCell(context, genW.cellController2), + arrayCell(context, genW.cellController3), + ]), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + arrayCell(context, genW.cellController4), + arrayCell(context, genW.cellController5), + arrayCell(context, genW.cellController6), + arrayCell(context, genW.cellController7), + ]), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + arrayCell(context, genW.cellController8), + arrayCell(context, genW.cellController9), + arrayCell(context, genW.cellController10), + arrayCell(context, genW.cellController11), + ]), + ]), + // const Spacer(), + if (genW.isSentenceComplete(context)) + Expanded( + child: Align( + alignment: Alignment.center, + child: SizedBox( + width: 410, + height: 70, + child: ElevatedButton( style: ElevatedButton.styleFrom( elevation: 4, - primary: yellowC, // background - onPrimary: Colors.black, // foreground + primary: orangeC, // background + onPrimary: Colors.white, // foreground ), - onPressed: () { - genW.pasteMnemonic(context); + onPressed: () async { + if (await sub + .isMnemonicValid(genW.generatedMnemonic!)) { + genW.resetImportView(); + await Navigator.push( + context, + FaderTransition( + page: skipIntro + ? const OnboardingStepNine( + scanDerivation: true) + : const OnboardingStepSeven( + scanDerivation: true), + isFast: true), + ); + } else { + await badMnemonicPopup(context); + } }, - child: Row( - children: [ - const Icon( - Icons.content_paste_go, - size: 25, - ), - const SizedBox(width: 10), - Text( - 'pasteFromClipboard'.tr(), - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 17, fontWeight: FontWeight.w400), - ), - ], - )), - ) - ]) + child: Text( + 'restoreThisChest'.tr(), + style: const TextStyle( + fontSize: 24, fontWeight: FontWeight.w600), + ), + ), + ), + // SizedBox(height: isTall ? 80 : 80), + )) + else + Column(children: [ + const SizedBox(height: 20), + SizedBox( + width: 190, + height: 60, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 4, + primary: yellowC, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () { + genW.pasteMnemonic(context); + }, + child: Row( + children: [ + const Icon( + Icons.content_paste_go, + size: 25, + ), + const SizedBox(width: 10), + Text( + 'pasteFromClipboard'.tr(), + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 17, fontWeight: FontWeight.w400), + ), + ], + )), + ) + ]) + ]), + CommonElements().offlineInfo(context), ]), ), ), diff --git a/lib/screens/onBoarding/1.dart b/lib/screens/onBoarding/1.dart index 2550f47..a13257d 100644 --- a/lib/screens/onBoarding/1.dart +++ b/lib/screens/onBoarding/1.dart @@ -27,15 +27,18 @@ class OnboardingStepOne extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro( - context, - 'geckoGenerateYourWalletFromMnemonic'.tr(), - 'fabrication-de-portefeuille.png', - '>', - const OnboardingStepTwo(), - 0, - isMd: true, - ), + child: Stack(children: [ + common.infoIntro( + context, + 'geckoGenerateYourWalletFromMnemonic'.tr(), + 'fabrication-de-portefeuille.png', + '>', + const OnboardingStepTwo(), + 0, + isMd: true, + ), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/10.dart b/lib/screens/onBoarding/10.dart index ad58bac..2680d33 100644 --- a/lib/screens/onBoarding/10.dart +++ b/lib/screens/onBoarding/10.dart @@ -49,79 +49,82 @@ class OnboardingStepTen extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: Column(children: [ - SizedBox(height: isTall ? 40 : 20), - common.buildProgressBar(9), - SizedBox(height: isTall ? 40 : 20), - common.buildText("geckoWillCheckPassword".tr()), - SizedBox(height: isTall ? 80 : 20), - Visibility( - visible: generateWalletProvider.scanedValidWalletNumber != -1, - child: Padding( - padding: const EdgeInsets.only(bottom: 15), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("derivationsScanProgress".tr(args: [ - '${generateWalletProvider.scanedWalletNumber}', - '${generateWalletProvider.numberScan + 1}' - ])), - const SizedBox(width: 10), - SizedBox( - height: 22, - width: 22, - child: CircularProgressIndicator( - color: orangeC, - strokeWidth: 3, + child: Stack(children: [ + Column(children: [ + SizedBox(height: isTall ? 40 : 20), + common.buildProgressBar(9), + SizedBox(height: isTall ? 40 : 20), + common.buildText("geckoWillCheckPassword".tr()), + SizedBox(height: isTall ? 80 : 20), + Visibility( + visible: generateWalletProvider.scanedValidWalletNumber != -1, + child: Padding( + padding: const EdgeInsets.only(bottom: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("derivationsScanProgress".tr(args: [ + '${generateWalletProvider.scanedWalletNumber}', + '${generateWalletProvider.numberScan + 1}' + ])), + const SizedBox(width: 10), + SizedBox( + height: 22, + width: 22, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: 3, + ), ), - ), - ], + ], + ), ), ), - ), - Consumer(builder: (context, sub, _) { - return sub.nodeConnected - ? pinForm(context, walletOptions, pinLenght, 1, 2) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Text( - 'Vous devez vous connecter à internet\npour valider votre coffre', - style: TextStyle( - fontSize: 20, - color: Colors.redAccent, - fontWeight: FontWeight.w500, + Consumer(builder: (context, sub, _) { + return sub.nodeConnected + ? pinForm(context, walletOptions, pinLenght, 1, 2) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + 'Vous devez vous connecter à internet\npour valider votre coffre', + style: TextStyle( + fontSize: 20, + color: Colors.redAccent, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, + ]); + }), + Consumer(builder: (context, sub, _) { + return sub.nodeConnected + ? InkWell( + onTap: () { + walletOptions.changePinCacheChoice(); + }, + child: Row(children: [ + const SizedBox(height: 30), + const Spacer(), + Icon( + configBox.get('isCacheChecked') ?? false + ? Icons.check_box + : Icons.check_box_outline_blank, + color: orangeC, ), - ]); - }), - Consumer(builder: (context, sub, _) { - return sub.nodeConnected - ? InkWell( - onTap: () { - walletOptions.changePinCacheChoice(); - }, - child: Row(children: [ - const SizedBox(height: 30), - const Spacer(), - Icon( - configBox.get('isCacheChecked') ?? false - ? Icons.check_box - : Icons.check_box_outline_blank, - color: orangeC, - ), - const SizedBox(width: 8), - Text( - 'rememberPassword'.tr(), - style: - TextStyle(fontSize: 16, color: Colors.grey[700]), - ), - const Spacer() - ])) - : const Text(''); - }), - const SizedBox(height: 10), + const SizedBox(width: 8), + Text( + 'rememberPassword'.tr(), + style: TextStyle( + fontSize: 16, color: Colors.grey[700]), + ), + const Spacer() + ])) + : const Text(''); + }), + const SizedBox(height: 10), + ]), + CommonElements().offlineInfo(context), ]), )); } diff --git a/lib/screens/onBoarding/2.dart b/lib/screens/onBoarding/2.dart index ee16d16..82e21c3 100644 --- a/lib/screens/onBoarding/2.dart +++ b/lib/screens/onBoarding/2.dart @@ -29,13 +29,16 @@ class OnboardingStepTwo extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro( - context, - 'keepThisMnemonicSecure'.tr(), - 'fabrication-de-portefeuille-impossible-sans-phrase.png', - '>', - const OnboardingStepThree(), - 1), + child: Stack(children: [ + common.infoIntro( + context, + 'keepThisMnemonicSecure'.tr(), + 'fabrication-de-portefeuille-impossible-sans-phrase.png', + '>', + const OnboardingStepThree(), + 1), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/3.dart b/lib/screens/onBoarding/3.dart index 8a261d9..0099402 100644 --- a/lib/screens/onBoarding/3.dart +++ b/lib/screens/onBoarding/3.dart @@ -29,8 +29,11 @@ class OnboardingStepThree extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro(context, 'warningForgotPassword'.tr(), - 'forgot_password.png'.tr(), '>', const OnboardingStepFor(), 2), + child: Stack(children: [ + common.infoIntro(context, 'warningForgotPassword'.tr(), + 'forgot_password.png'.tr(), '>', const OnboardingStepFor(), 2), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/4.dart b/lib/screens/onBoarding/4.dart index 946f3db..d2ce061 100644 --- a/lib/screens/onBoarding/4.dart +++ b/lib/screens/onBoarding/4.dart @@ -29,14 +29,17 @@ class OnboardingStepFor extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro( - context, - 'itsTimeToUseAPenAndPaper'.tr(), - 'gecko_also_can_forget.png'.tr(), - '>', - const OnboardingStepFive(), - 3, - isMd: true), + child: Stack(children: [ + common.infoIntro( + context, + 'itsTimeToUseAPenAndPaper'.tr(), + 'gecko_also_can_forget.png'.tr(), + '>', + const OnboardingStepFive(), + 3, + isMd: true), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/5.dart b/lib/screens/onBoarding/5.dart index a2234f4..6b9426f 100644 --- a/lib/screens/onBoarding/5.dart +++ b/lib/screens/onBoarding/5.dart @@ -48,57 +48,62 @@ class _ChooseChestState extends State { ), extendBodyBehindAppBar: true, body: SafeArea( - child: Column(children: [ - SizedBox(height: isTall ? 40 : 20), - common.buildProgressBar(4), - SizedBox(height: isTall ? 40 : 20), - common.buildText('geckoGeneratedYourMnemonicKeepItSecret'.tr()), - SizedBox(height: 35 * ratio), - sentanceArray(context), - SizedBox(height: 17 * ratio), - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return PrintWallet(generateWalletProvider.generatedMnemonic); - }), - ); - }, - child: Image.asset( - 'assets/printer.png', - height: 42 * ratio, - ), - ), - const SizedBox(height: 40), - Expanded( - child: Align( - alignment: Alignment.bottomCenter, - child: SizedBox( - width: 380 * ratio, - height: 60 * ratio, - child: ElevatedButton( - key: const Key('generateMnemonic'), - style: ElevatedButton.styleFrom( - elevation: 4, - primary: const Color(0xffFFD58D), - onPrimary: Colors.black, // foreground - ), - onPressed: () { - // _generateWalletProvider.reloadBuild(); - setState(() {}); - }, - child: Text("chooseAnotherMnemonic".tr(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22 * ratio, - fontWeight: FontWeight.w600))), + child: Stack(children: [ + Column(children: [ + SizedBox(height: isTall ? 40 : 20), + common.buildProgressBar(4), + SizedBox(height: isTall ? 40 : 20), + common.buildText('geckoGeneratedYourMnemonicKeepItSecret'.tr()), + SizedBox(height: 35 * ratio), + sentanceArray(context), + SizedBox(height: 17 * ratio), + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return PrintWallet( + generateWalletProvider.generatedMnemonic); + }), + ); + }, + child: Image.asset( + 'assets/printer.png', + height: 42 * ratio, ), ), - ), - SizedBox(height: 22 * ratio), - nextButton(context, "iNotedMyMnemonic".tr(), false, widget.skipIntro), - SizedBox(height: 35 * ratio), + const SizedBox(height: 40), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: SizedBox( + width: 380 * ratio, + height: 60 * ratio, + child: ElevatedButton( + key: const Key('generateMnemonic'), + style: ElevatedButton.styleFrom( + elevation: 4, + primary: const Color(0xffFFD58D), + onPrimary: Colors.black, // foreground + ), + onPressed: () { + // _generateWalletProvider.reloadBuild(); + setState(() {}); + }, + child: Text("chooseAnotherMnemonic".tr(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22 * ratio, + fontWeight: FontWeight.w600))), + ), + ), + ), + SizedBox(height: 22 * ratio), + nextButton( + context, "iNotedMyMnemonic".tr(), false, widget.skipIntro), + SizedBox(height: 35 * ratio), + ]), + CommonElements().offlineInfo(context), ]), ), ); diff --git a/lib/screens/onBoarding/6.dart b/lib/screens/onBoarding/6.dart index 69922c3..5a58006 100644 --- a/lib/screens/onBoarding/6.dart +++ b/lib/screens/onBoarding/6.dart @@ -51,88 +51,92 @@ class OnboardingStepSix extends StatelessWidget { ), ), body: SafeArea( - child: Align( - alignment: Alignment.topCenter, - child: Column(children: [ - SizedBox(height: isTall ? 40 : 20), - common.buildProgressBar(5), - SizedBox(height: isTall ? 40 : 20), - common.buildText( - "didYouNoteMnemonicToBeSureTypeWord".tr( - args: [(generateWalletProvider.nbrWord + 1).toString()]), - 20, - true), - SizedBox(height: isTall ? 70 : 20), - Text('${generateWalletProvider.nbrWord + 1}', - key: const Key('askedWord'), - style: TextStyle( - fontSize: isTall ? 17 : 15, - color: orangeC, - fontWeight: FontWeight.w400)), - const SizedBox(height: 10), - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(7), - border: Border.all( - color: Colors.grey[600]!, - width: 3, - )), - width: 430, - child: TextFormField( - key: const Key('inputWord'), - autofocus: true, - enabled: !generateWalletProvider.isAskedWordValid, - controller: wordController, - textInputAction: TextInputAction.next, - onChanged: (value) { - generateWalletProvider.checkAskedWord( - value, _mnemonicController.text); - }, - maxLines: 1, - textAlign: TextAlign.center, - decoration: InputDecoration( - labelStyle: TextStyle( - fontSize: 22.0, - color: Colors.grey[500], - fontWeight: FontWeight.w500), - labelText: generateWalletProvider.isAskedWordValid - ? "itsTheGoodWord".tr() - : "${generateWalletProvider.nbrWordAlpha} ${"nthMnemonicWord".tr()}", - fillColor: const Color(0xffeeeedd), - filled: true, - contentPadding: const EdgeInsets.all(12), - ), - style: TextStyle( - fontSize: 40.0, - color: generateWalletProvider.askedWordColor, - fontWeight: FontWeight.w500))), - Visibility( - visible: generateWalletProvider.isAskedWordValid, - child: Expanded( - child: Align( - alignment: Alignment.bottomCenter, - child: nextButton( - context, - 'continue'.tr(), - skipIntro - ? const OnboardingStepNine() - : const OnboardingStepSeven(), - false), + child: Stack(children: [ + Align( + alignment: Alignment.topCenter, + child: Column(children: [ + SizedBox(height: isTall ? 40 : 20), + common.buildProgressBar(5), + SizedBox(height: isTall ? 40 : 20), + common.buildText( + "didYouNoteMnemonicToBeSureTypeWord".tr(args: [ + (generateWalletProvider.nbrWord + 1).toString() + ]), + 20, + true), + SizedBox(height: isTall ? 70 : 20), + Text('${generateWalletProvider.nbrWord + 1}', + key: const Key('askedWord'), + style: TextStyle( + fontSize: isTall ? 17 : 15, + color: orangeC, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + border: Border.all( + color: Colors.grey[600]!, + width: 3, + )), + width: 430, + child: TextFormField( + key: const Key('inputWord'), + autofocus: true, + enabled: !generateWalletProvider.isAskedWordValid, + controller: wordController, + textInputAction: TextInputAction.next, + onChanged: (value) { + generateWalletProvider.checkAskedWord( + value, _mnemonicController.text); + }, + maxLines: 1, + textAlign: TextAlign.center, + decoration: InputDecoration( + labelStyle: TextStyle( + fontSize: 22.0, + color: Colors.grey[500], + fontWeight: FontWeight.w500), + labelText: generateWalletProvider.isAskedWordValid + ? "itsTheGoodWord".tr() + : "${generateWalletProvider.nbrWordAlpha} ${"nthMnemonicWord".tr()}", + fillColor: const Color(0xffeeeedd), + filled: true, + contentPadding: const EdgeInsets.all(12), + ), + style: TextStyle( + fontSize: 40.0, + color: generateWalletProvider.askedWordColor, + fontWeight: FontWeight.w500))), + Visibility( + visible: generateWalletProvider.isAskedWordValid, + child: Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: nextButton( + context, + 'continue'.tr(), + skipIntro + ? const OnboardingStepNine() + : const OnboardingStepSeven(), + false), + ), ), ), - ), - // Visibility( - // visible: !_generateWalletProvider.isAskedWordValid, - // child: const Expanded( - // child: Align( - // alignment: Alignment.bottomCenter, - // child: Text(''), - // ), - // ), - // ), - SizedBox(height: 35 * ratio), - ]), - ), + // Visibility( + // visible: !_generateWalletProvider.isAskedWordValid, + // child: const Expanded( + // child: Align( + // alignment: Alignment.bottomCenter, + // child: Text(''), + // ), + // ), + // ), + SizedBox(height: 35 * ratio), + ]), + ), + CommonElements().offlineInfo(context), + ]), ), ), ); diff --git a/lib/screens/onBoarding/7.dart b/lib/screens/onBoarding/7.dart index b266009..4313930 100644 --- a/lib/screens/onBoarding/7.dart +++ b/lib/screens/onBoarding/7.dart @@ -29,14 +29,17 @@ class OnboardingStepSeven extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro( - context, - 'geckoWillGenerateAPassword'.tr(), - 'coffre-fort-code-secret-dans-telephone.png', - '>', - OnboardingStepEight(scanDerivation: scanDerivation), - 6, - boxHeight: 400), + child: Stack(children: [ + common.infoIntro( + context, + 'geckoWillGenerateAPassword'.tr(), + 'coffre-fort-code-secret-dans-telephone.png', + '>', + OnboardingStepEight(scanDerivation: scanDerivation), + 6, + boxHeight: 400), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/8.dart b/lib/screens/onBoarding/8.dart index 2172e2d..905535a 100644 --- a/lib/screens/onBoarding/8.dart +++ b/lib/screens/onBoarding/8.dart @@ -29,14 +29,17 @@ class OnboardingStepEight extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: common.infoIntro( - context, - 'thisPasswordProtectsYourWalletsInASecureChest'.tr(), - 'coffre-fort-protege-les-portefeuilles.png', - '>', - OnboardingStepNine(scanDerivation: scanDerivation), - 7, - isMd: true), + child: Stack(children: [ + common.infoIntro( + context, + 'thisPasswordProtectsYourWalletsInASecureChest'.tr(), + 'coffre-fort-protege-les-portefeuilles.png', + '>', + OnboardingStepNine(scanDerivation: scanDerivation), + 7, + isMd: true), + CommonElements().offlineInfo(context), + ]), ), ); } diff --git a/lib/screens/onBoarding/9.dart b/lib/screens/onBoarding/9.dart index 0cf8ecf..ed29fce 100644 --- a/lib/screens/onBoarding/9.dart +++ b/lib/screens/onBoarding/9.dart @@ -41,61 +41,65 @@ class OnboardingStepNine extends StatelessWidget { ), extendBodyBehindAppBar: true, body: SafeArea( - child: Column(children: [ - SizedBox(height: isTall ? 40 : 20), - common.buildProgressBar(8), - SizedBox(height: isTall ? 40 : 20), - common.buildText("hereIsThePasswordKeepIt".tr(), 20, true), - const SizedBox(height: 100), - Stack( - alignment: Alignment.centerRight, - children: [ - TextField( - key: const Key('generatedPin'), - enabled: false, - controller: generateWalletProvider.pin, - maxLines: 1, - textAlign: TextAlign.center, - decoration: const InputDecoration(), - style: const TextStyle( - letterSpacing: 5, - fontSize: 35.0, - color: Colors.black, - fontWeight: FontWeight.bold)), - IconButton( - icon: const Icon(Icons.replay), - color: orangeC, - onPressed: () { - generateWalletProvider.changePinCode(reload: true); - }, - ), - ], - ), - Expanded( - child: Align( - alignment: Alignment.bottomCenter, - child: SizedBox( - width: 380 * ratio, - height: 60 * ratio, - child: ElevatedButton( - key: const Key('changeSecretCode'), - style: ElevatedButton.styleFrom( - elevation: 4, - primary: const Color(0xffFFD58D), - onPrimary: Colors.black, // foreground - ), - onPressed: () { - generateWalletProvider.changePinCode(reload: true); - }, - child: Text("chooseAnotherPassword".tr(), - style: TextStyle( - fontSize: 22 * ratio, - fontWeight: FontWeight.w600))), - ))), - SizedBox(height: 22 * ratio), - common.nextButton(context, "iNotedMyPassword".tr(), - OnboardingStepTen(scanDerivation: scanDerivation), false), - SizedBox(height: 35 * ratio), + child: Stack(children: [ + Column(children: [ + SizedBox(height: isTall ? 40 : 20), + common.buildProgressBar(8), + SizedBox(height: isTall ? 40 : 20), + common.buildText("hereIsThePasswordKeepIt".tr(), 20, true), + const SizedBox(height: 100), + Stack( + alignment: Alignment.centerRight, + children: [ + TextField( + key: const Key('generatedPin'), + enabled: false, + controller: generateWalletProvider.pin, + maxLines: 1, + textAlign: TextAlign.center, + decoration: const InputDecoration(), + style: const TextStyle( + letterSpacing: 5, + fontSize: 35.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + IconButton( + icon: const Icon(Icons.replay), + color: orangeC, + onPressed: () { + generateWalletProvider.changePinCode(reload: true); + }, + ), + ], + ), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: SizedBox( + width: 380 * ratio, + height: 60 * ratio, + child: ElevatedButton( + key: const Key('changeSecretCode'), + style: ElevatedButton.styleFrom( + elevation: 4, + primary: const Color(0xffFFD58D), + onPrimary: Colors.black, // foreground + ), + onPressed: () { + generateWalletProvider.changePinCode( + reload: true); + }, + child: Text("chooseAnotherPassword".tr(), + style: TextStyle( + fontSize: 22 * ratio, + fontWeight: FontWeight.w600))), + ))), + SizedBox(height: 22 * ratio), + common.nextButton(context, "iNotedMyPassword".tr(), + OnboardingStepTen(scanDerivation: scanDerivation), false), + SizedBox(height: 35 * ratio), + ]), + CommonElements().offlineInfo(context), ]), )); } diff --git a/pubspec.yaml b/pubspec.yaml index f55e8cf..aad5a24 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9+22 +version: 0.0.9+23 environment: sdk: '>=2.12.0 <3.0.0' From 5ce381b1748aa505e67306411334f157d37e7adf Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 17 Aug 2022 23:28:19 +0200 Subject: [PATCH 08/19] fix: can't cert if identity is not confirmed --- assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fr.json | 1 + lib/providers/substrate_sdk.dart | 9 ++- lib/screens/wallet_view.dart | 96 ++++++++++++-------------------- 5 files changed, 46 insertions(+), 62 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index bca3f5c..cfcd2e3 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -147,6 +147,7 @@ "execTimeoutOver": "Execution timeout is over", "seeAWallet": "See a wallet", "mustWaitXBeforeCertify": "You have to wait\n{} before\ncertifying again", + "mustConfirmHisIdentity": "This person must confirm\nhis identity before can be\ncertified", "canRenewCertInX": "You can renew\nthis certification\nin {}", "executeATransfer": "Execute a transfer", "executeTheTransfer": "Execute the transfer", diff --git a/assets/translations/es.json b/assets/translations/es.json index 7d985e9..99f6f1b 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -147,6 +147,7 @@ "execTimeoutOver": "Execution timeout is over", "seeAWallet": "See a wallet", "mustWaitXBeforeCertify": "You have to wait\n{} before\ncertifying again", + "mustConfirmHisIdentity": "This person must confirm\nhis identity before can be\ncertified", "canRenewCertInX": "You can renew\nthis certification\nin {}", "executeATransfer": "Execute a transfer", "executeTheTransfer": "Execute the transfer", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 9f03953..120c128 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -148,6 +148,7 @@ "execTimeoutOver": "Le délais d'éxecution est dépassé", "seeAWallet": "Voir un portefeuille", "mustWaitXBeforeCertify": "Vous devez attendre\n{} avant\nde pouvoir certifier", + "mustConfirmHisIdentity": "Cette personne doit confirmer\nson identité avant de pouvoir\nêtre certifié", "canRenewCertInX": "Vous pourrez renouveller\ncette certification\ndans {}", "executeATransfer": "Effectuer un virement", "executeTheTransfer": "Effectuer le virement", diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index d814bb7..c06d102 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -227,9 +227,13 @@ class SubstrateSdk with ChangeNotifier { } else { result.putIfAbsent('canCert', () => 0); } - // log.d('tatatatata: ${nextIssuableOn - blocNumber}'); } + final toStatus = await idtyStatus(to); + // log.d('certMeta: $toStatus'); + + if (toStatus == 'Created') result.putIfAbsent('toStatus', () => 1); + return result; } @@ -797,8 +801,7 @@ class AddressInfo { void snackNode(BuildContext context, bool isConnected) { String message; if (!isConnected) { - message = - "noDuniterNodeAvailableTryLater".tr(); + message = "noDuniterNodeAvailableTryLater".tr(); } else { SubstrateSdk sub = Provider.of(context, listen: false); diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 1593780..994cdec 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -191,6 +191,8 @@ class WalletViewScreen extends StatelessWidget { } } + final toStatus = snapshot.data!['toStatus'] ?? 0; + return Visibility( visible: (snapshot.data != {}), child: Column(children: [ @@ -269,66 +271,13 @@ class WalletViewScreen extends StatelessWidget { fontWeight: FontWeight.w500), ), ]), - if (snapshot.data!['certDelay'] != null) - Column(children: [ - SizedBox( - height: buttonSize, - child: Padding( - padding: const EdgeInsets.only(bottom: 0), - child: Container( - foregroundDecoration: const BoxDecoration( - color: Colors.grey, - backgroundBlendMode: BlendMode.saturation, - ), - child: const Opacity( - opacity: 0.5, - child: Image( - image: AssetImage( - 'assets/gecko_certify.png')), - ), - ), - ), - ), - Text( - "mustWaitXBeforeCertify" - .tr(args: [duration.toString()]), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: buttonFontSize - 4, - fontWeight: FontWeight.w400, - color: Colors.grey[600]), - ), - ]), - if (snapshot.data!['certRenewable'] != null && + if (toStatus == 1) + waitToCert('mustConfirmHisIdentity', duration) + else if (snapshot.data!['certRenewable'] != null && duration != 'seconds'.tr(args: ['0'])) - Column(children: [ - SizedBox( - height: buttonSize, - child: Padding( - padding: const EdgeInsets.only(bottom: 0), - child: Container( - foregroundDecoration: const BoxDecoration( - color: Colors.grey, - backgroundBlendMode: BlendMode.saturation, - ), - child: const Opacity( - opacity: 0.5, - child: Image( - image: AssetImage( - 'assets/gecko_certify.png')), - ), - ), - ), - ), - Text( - "canRenewCertInX".tr(args: [duration.toString()]), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: buttonFontSize - 4, - fontWeight: FontWeight.w400, - color: Colors.grey[600]), - ), - ]), + waitToCert('canRenewCertInX', duration) + else if (snapshot.data!['certDelay'] != null) + waitToCert('mustWaitXBeforeCertify', duration) ]), ); }, @@ -415,6 +364,35 @@ class WalletViewScreen extends StatelessWidget { )); } + Widget waitToCert(String status, String duration) { + return Column(children: [ + SizedBox( + height: buttonSize, + child: Padding( + padding: const EdgeInsets.only(bottom: 0), + child: Container( + foregroundDecoration: const BoxDecoration( + color: Colors.grey, + backgroundBlendMode: BlendMode.saturation, + ), + child: const Opacity( + opacity: 0.5, + child: Image(image: AssetImage('assets/gecko_certify.png')), + ), + ), + ), + ), + Text( + status.tr(args: [duration]), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: buttonFontSize - 4, + fontWeight: FontWeight.w400, + color: Colors.grey[600]), + ), + ]); + } + void paymentPopup( BuildContext context, WalletsProfilesProvider walletViewProvider) { // WalletsProfilesProvider _walletViewProvider = From dbfd033fba3eb9a1c0b329a36eff207694373879 Mon Sep 17 00:00:00 2001 From: poka Date: Thu, 18 Aug 2022 01:31:47 +0200 Subject: [PATCH 09/19] new screen for g1V1 salt/password import --- assets/translations/en.json | 4 +- assets/translations/es.json | 4 +- assets/translations/fr.json | 4 +- lib/providers/substrate_sdk.dart | 52 +++++--- lib/screens/myWallets/import_g1_v1.dart | 156 ++++++++++++++++++++++++ lib/screens/myWallets/wallets_home.dart | 36 ++++-- 6 files changed, 226 insertions(+), 30 deletions(-) create mode 100644 lib/screens/myWallets/import_g1_v1.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index cfcd2e3..87d92a1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -176,5 +176,7 @@ "addContact": "Add\nto contacts", "removeContact": "Remove\nthis contact", "derivationsScanProgress": "Scan address {}/{}", - "youAreOffline": "You are offline..." + "youAreOffline": "You are offline...", + "importG1v1": "Import old G1v1 account", + "selectDestWallet": "Select a target wallet:" } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index 99f6f1b..ab3fb87 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -176,5 +176,7 @@ "addContact": "Add\nto contacts", "removeContact": "Remove\nthis contact", "derivationsScanProgress": "Scan address {}/{}", - "youAreOffline": "You are offline..." + "youAreOffline": "You are offline...", + "importG1v1": "Import old G1v1 account", + "selectDestWallet": "Select a target wallet:" } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 120c128..be333dc 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -177,5 +177,7 @@ "addContact": "Ajouter\naux contacts", "removeContact": "Supprimer\nce contact", "derivationsScanProgress": "Scan de l'adresse {}/{}", - "youAreOffline": "Vous êtes hors ligne..." + "youAreOffline": "Vous êtes hors ligne...", + "importG1v1": "Importer son compte G1v1", + "selectDestWallet": "Sélectionner un portefeuille cible:" } \ No newline at end of file diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index c06d102..dde57f3 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -31,6 +33,10 @@ class SubstrateSdk with ChangeNotifier { String transactionStatus = ''; final int initSs58 = 42; Map currencyParameters = {}; + TextEditingController csSalt = TextEditingController(); + TextEditingController csPassword = TextEditingController(); + String g1V1NewAddress = ''; + bool isCesiumIDVisible = true; ///////////////////////////////////// ////////// 1: API METHODS /////////// @@ -570,7 +576,7 @@ class SubstrateSdk with ChangeNotifier { return await sdk.api.keyring.checkMnemonicValid(mnemonic); } - Future csToV2(String salt, String password) async { + Future csToV2Address(String salt, String password) async { final scrypt = pc.KeyDerivator('scrypt'); scrypt.init( @@ -586,29 +592,32 @@ class SubstrateSdk with ChangeNotifier { final rawSeedHex = '0x${HEX.encode(rawSeed)}'; // Just get the address without keystore - // final newAddress1 = await sdk.api.keyring.addressFromRawSeed(ss58, - // cryptoType: CryptoType.ed25519, rawSeed: '0x$rawSeedString'); - // log.d('csconvert address: ${newAddress1.address}'); + final newAddress = await sdk.api.keyring.addressFromRawSeed( + currencyParameters['ss58']!, + cryptoType: CryptoType.ed25519, + rawSeed: rawSeedHex); - final json = await sdk.api.keyring.importAccount(keyring, - keyType: KeyType.rawSeed, - key: rawSeedHex, - name: 'test', - password: 'password', - derivePath: '', - cryptoType: CryptoType.ed25519); + // final json = await sdk.api.keyring.importAccount(keyring, + // keyType: KeyType.rawSeed, + // key: rawSeedHex, + // name: 'test', + // password: 'password', + // derivePath: '', + // cryptoType: CryptoType.ed25519); - final keypair = await sdk.api.keyring.addAccount( - keyring, - keyType: KeyType.rawSeed, - acc: json!, - password: password, - ); - await sdk.api.keyring.deleteAccount(keyring, keypair); + // final keypair = await sdk.api.keyring.addAccount( + // keyring, + // keyType: KeyType.rawSeed, + // acc: json!, + // password: password, + // ); + // await sdk.api.keyring.deleteAccount(keyring, keypair); // final keypair2 = KeyPairData.fromJson(json as Map); - log.d(keypair.address); + // g1V1NewAddress = keypair.address!; + g1V1NewAddress = newAddress.address!; + notifyListeners(); } ////////////////////////////////////// @@ -776,6 +785,11 @@ class SubstrateSdk with ChangeNotifier { return await executeCall(txInfo, txOptions, password); } + void cesiumIDisVisible() { + isCesiumIDVisible = !isCesiumIDVisible; + notifyListeners(); + } + void reload() { notifyListeners(); } diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart new file mode 100644 index 0000000..7557d49 --- /dev/null +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -0,0 +1,156 @@ +import 'dart:async'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/services.dart'; +import 'package:gecko/globals.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/providers/my_wallets.dart'; +import 'package:gecko/providers/substrate_sdk.dart'; +import 'package:gecko/providers/wallet_options.dart'; +import 'package:provider/provider.dart'; + +class ImportG1v1 extends StatelessWidget { + const ImportG1v1({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + // HomeProvider _homeProvider = Provider.of(context); + WalletOptionsProvider walletOptions = + Provider.of(context, listen: false); + MyWalletsProvider myWalletProvider = + Provider.of(context, listen: false); + + Timer? debounce; + const int debouneTime = 300; + String selectedWallet = myWalletProvider.getDefaultWallet().name!; + + return Scaffold( + backgroundColor: backgroundColor, + appBar: AppBar( + toolbarHeight: 60 * ratio, + title: const SizedBox( + height: 22, + child: Text('Importer son ancien compte'), + )), + body: + SafeArea(child: Consumer(builder: (context, sub, _) { + return Column(children: [ + const SizedBox(height: 20), + TextFormField( + autofocus: true, + onChanged: (text) { + if (debounce?.isActive ?? false) { + debounce!.cancel(); + } + debounce = Timer(const Duration(milliseconds: debouneTime), () { + sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); + }); + }, + keyboardType: TextInputType.text, + controller: sub.csSalt, + obscureText: + sub.isCesiumIDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'Entrez votre identifiant Cesium', + suffixIcon: IconButton( + icon: Icon( + sub.isCesiumIDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + sub.cesiumIDisVisible(); + }, + ), + ), + ), + const SizedBox(height: 20), + TextFormField( + autofocus: true, + onChanged: (text) { + if (debounce?.isActive ?? false) { + debounce!.cancel(); + } + debounce = Timer(const Duration(milliseconds: debouneTime), () { + sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); + }); + }, + keyboardType: TextInputType.text, + controller: sub.csPassword, + obscureText: + sub.isCesiumIDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'Entrez votre mot de passe Cesium', + suffixIcon: IconButton( + icon: Icon( + sub.isCesiumIDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + sub.cesiumIDisVisible(); + }, + ), + ), + ), + const SizedBox(height: 20), + Text( + sub.g1V1NewAddress, + style: const TextStyle( + fontSize: 14.0, + color: Colors.black, + fontWeight: FontWeight.bold, + fontFamily: 'Monospace'), + ), + const SizedBox(height: 20), + balance(context, sub.g1V1NewAddress, 17), + walletOptions.idtyStatus(context, sub.g1V1NewAddress, + isOwner: false, color: Colors.black), + getCerts(context, sub.g1V1NewAddress, 14), + const SizedBox(height: 30), + Text('selectDestWallet'.tr()), + const SizedBox(height: 10), + DropdownButtonHideUnderline( + child: DropdownButton( + // alignment: AlignmentDirectional.topStart, + value: selectedWallet, + icon: const Icon(Icons.keyboard_arrow_down), + items: myWalletProvider.listWallets.map((wallet) { + return DropdownMenuItem( + value: wallet.name, + child: Text(wallet.name!), + ); + }).toList(), + onChanged: (newSelectedWallet) { + selectedWallet = newSelectedWallet.toString(); + sub.reload(); + }, + ), + ), + const SizedBox(height: 30), + SizedBox( + width: 380 * ratio, + height: 60 * ratio, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 4, + primary: orangeC, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () { + log.d('GOOO'); + }, + child: Text( + 'validate'.tr(), + style: TextStyle( + fontSize: 23 * ratio, fontWeight: FontWeight.w600), + ), + ), + ) + ]); + }))); + } +} diff --git a/lib/screens/myWallets/wallets_home.dart b/lib/screens/myWallets/wallets_home.dart index 6fcd74f..b288f65 100644 --- a/lib/screens/myWallets/wallets_home.dart +++ b/lib/screens/myWallets/wallets_home.dart @@ -14,6 +14,7 @@ import 'package:gecko/providers/wallet_options.dart'; import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/myWallets/chest_options.dart'; import 'package:gecko/screens/myWallets/choose_chest.dart'; +import 'package:gecko/screens/myWallets/import_g1_v1.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/myWallets/wallet_options.dart'; import 'package:provider/provider.dart'; @@ -64,12 +65,10 @@ class WalletsHome extends StatelessWidget { ), bottomNavigationBar: homeProvider.bottomAppBar(context), body: SafeArea( - child: Stack( - children: [ - myWalletsTiles(context, currentChestNumber), - CommonElements().offlineInfo(context), - ], - ), + child: Stack(children: [ + myWalletsTiles(context, currentChestNumber), + CommonElements().offlineInfo(context), + ]), ), ), ); @@ -79,8 +78,30 @@ class WalletsHome extends StatelessWidget { BuildContext context, MyWalletsProvider myWalletProvider) { return Column(children: [ const SizedBox(height: 50), + InkWell( + key: const Key('importG1v1'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const ImportG1v1(); + }), + ); + }, + child: SizedBox( + width: 400, + height: 50, + child: Center( + child: Text('importG1v1'.tr(), + style: TextStyle( + fontSize: 22, + color: orangeC, + fontWeight: FontWeight.w500))), + ), + ), + const SizedBox(height: 30), SizedBox( - height: 90, + height: 80, width: 420, child: ElevatedButton.icon( icon: Image.asset( @@ -168,7 +189,6 @@ class WalletsHome extends StatelessWidget { return CustomScrollView(slivers: [ const SliverToBoxAdapter(child: SizedBox(height: 20)), - SliverGrid.count( key: const Key('listWallets'), crossAxisCount: nTule, From 1b896960eae3ecd2df550c16334008fd678986ed Mon Sep 17 00:00:00 2001 From: poka Date: Thu, 18 Aug 2022 14:26:12 +0200 Subject: [PATCH 10/19] can migrate GD from Cesium wallets --- assets/translations/en.json | 8 +- assets/translations/es.json | 8 +- assets/translations/fr.json | 8 +- lib/providers/substrate_sdk.dart | 70 ++++- lib/providers/wallet_options.dart | 2 + lib/screens/myWallets/import_g1_v1.dart | 350 +++++++++++++++--------- 6 files changed, 313 insertions(+), 133 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index 87d92a1..81e472f 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -178,5 +178,11 @@ "derivationsScanProgress": "Scan address {}/{}", "youAreOffline": "You are offline...", "importG1v1": "Import old G1v1 account", - "selectDestWallet": "Select a target wallet:" + "selectDestWallet": "Select a target wallet:", + "youMustWaitBeforeCashoutThisAccount": "You have to wait {} minutes\nbefore migrate this account", + "thisAccountIsEmpty": "This account is empty", + "youCannotMigrateIdentityToExistingIdentity": "You cannot migrate an identity\nto an account that already has an identity", + "importOldAccount": "Import your old account", + "enterCesiumId": "Enter your Cesium ID", + "enterCesiumPassword": "Enter your Cesium password" } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index ab3fb87..567af90 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -178,5 +178,11 @@ "derivationsScanProgress": "Scan address {}/{}", "youAreOffline": "You are offline...", "importG1v1": "Import old G1v1 account", - "selectDestWallet": "Select a target wallet:" + "selectDestWallet": "Select a target wallet:", + "youMustWaitBeforeCashoutThisAccount": "You have to wait {} minutes\nbefore migrate this account", + "thisAccountIsEmpty": "This account is empty", + "youCannotMigrateIdentityToExistingIdentity": "You cannot migrate an identity\nto an account that already has an identity", + "importOldAccount": "Import your old account", + "enterCesiumId": "Enter your Cesium ID", + "enterCesiumPassword": "Enter your Cesium password" } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index be333dc..b22d86b 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -179,5 +179,11 @@ "derivationsScanProgress": "Scan de l'adresse {}/{}", "youAreOffline": "Vous êtes hors ligne...", "importG1v1": "Importer son compte G1v1", - "selectDestWallet": "Sélectionner un portefeuille cible:" + "selectDestWallet": "Sélectionnez un portefeuille cible:", + "youMustWaitBeforeCashoutThisAccount": "Vous devez attendre {} minutes\navant de pouvoir migrer ce compte", + "thisAccountIsEmpty": "Ce compte est vide", + "youCannotMigrateIdentityToExistingIdentity": "Vous ne pouvez pas migrer une identité\nvers un compte disposant déjà d'une identité", + "importOldAccount": "Importer son ancien compte", + "enterCesiumId": "Entrez votre identifiant Cesium", + "enterCesiumPassword": "Entrez votre mot de passe Cesium" } \ No newline at end of file diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index dde57f3..d42a865 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -252,7 +252,7 @@ class SubstrateSdk with ChangeNotifier { return certMeta; } - Future idtyStatus(String address, [bool smooth = true]) async { + Future idtyStatus(String address) async { var idtyIndex = await getIdentityIndexOf(address); if (idtyIndex == 0) { @@ -297,6 +297,11 @@ class SubstrateSdk with ChangeNotifier { log.i('currencyParameters: $currencyParameters'); } + void cesiumIDisVisible() { + isCesiumIDVisible = !isCesiumIDVisible; + notifyListeners(); + } + ///////////////////////////////////// ////// 3: SUBSTRATE CONNECTION ////// ///////////////////////////////////// @@ -540,8 +545,6 @@ class SubstrateSdk with ChangeNotifier { BuildContext context, String address, int number, String password) async { final keypair = getKeypair(address); - log.d('tatatata $address $number $password ${keypair.encoded}'); - final seedMap = await keyring.store.getDecryptedSeed(keypair.pubKey, password); @@ -620,6 +623,24 @@ class SubstrateSdk with ChangeNotifier { notifyListeners(); } + Future getBalanceAndIdtyStatus(String address, String myAddress) async { + final balance = + address == '' ? {'transferableBalance': 0} : await getBalance(address); + final thisIdtyStatus = address == '' ? 'noid' : await idtyStatus(address); + final thisHasConsumer = + address == '' ? false : await hasAccountConsumers(address); + final myIdtyStatus = await idtyStatus(myAddress); + + log.d('tatata: $myIdtyStatus'); + + return [ + balance['transferableBalance'], + thisIdtyStatus, + myIdtyStatus, + thisHasConsumer + ]; + } + ////////////////////////////////////// ///////// 5: CALLS EXECUTION ///////// ////////////////////////////////////// @@ -785,9 +806,46 @@ class SubstrateSdk with ChangeNotifier { return await executeCall(txInfo, txOptions, password); } - void cesiumIDisVisible() { - isCesiumIDVisible = !isCesiumIDVisible; - notifyListeners(); + Future migrateCsToV2(String salt, String password, String destAddress, + {required double balance, String idtyStatus = 'noid'}) async { + final scrypt = pc.KeyDerivator('scrypt'); + + scrypt.init( + pc.ScryptParameters( + 4096, + 16, + 1, + 32, + Uint8List.fromList(salt.codeUnits), + ), + ); + final rawSeed = scrypt.process(Uint8List.fromList(password.codeUnits)); + final rawSeedHex = '0x${HEX.encode(rawSeed)}'; + + final json = await sdk.api.keyring.importAccount(keyring, + keyType: KeyType.rawSeed, + key: rawSeedHex, + name: 'test', + password: 'password', + derivePath: '', + cryptoType: CryptoType.ed25519); + + final keypair = await sdk.api.keyring.addAccount( + keyring, + keyType: KeyType.rawSeed, + acc: json!, + password: password, + ); + + if (balance != 0) { + await pay( + fromAddress: keypair.address!, + destAddress: destAddress, + amount: -1, + password: 'password'); + } + + await sdk.api.keyring.deleteAccount(keyring, keypair); } void reload() { diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index fa0c421..63a4a2d 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -30,6 +30,7 @@ class WalletOptionsProvider with ChangeNotifier { TextEditingController nameController = TextEditingController(); late bool isDefaultWallet; bool canValidateNameBool = false; + Map idtyStatusCache = {}; Future? get badWallet => null; @@ -157,6 +158,7 @@ class WalletOptionsProvider with ChangeNotifier { future: sub.idtyStatus(address), initialData: '', builder: (context, snapshot) { + idtyStatusCache[address] = snapshot.data.toString(); switch (snapshot.data.toString()) { case 'noid': { diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index 7557d49..7892d3b 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -4,9 +4,11 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; +import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallet_options.dart'; +import 'package:gecko/screens/transaction_in_progress.dart'; import 'package:provider/provider.dart'; class ImportG1v1 extends StatelessWidget { @@ -23,134 +25,234 @@ class ImportG1v1 extends StatelessWidget { Timer? debounce; const int debouneTime = 300; - String selectedWallet = myWalletProvider.getDefaultWallet().name!; + WalletData selectedWallet = myWalletProvider.getDefaultWallet(); + bool canValidate = false; + String validationStatus = ''; - return Scaffold( + return WillPopScope( + onWillPop: () { + resetScreen(context); + return Future.value(true); + }, + child: Scaffold( backgroundColor: backgroundColor, appBar: AppBar( toolbarHeight: 60 * ratio, - title: const SizedBox( - height: 22, - child: Text('Importer son ancien compte'), - )), - body: - SafeArea(child: Consumer(builder: (context, sub, _) { - return Column(children: [ - const SizedBox(height: 20), - TextFormField( - autofocus: true, - onChanged: (text) { - if (debounce?.isActive ?? false) { - debounce!.cancel(); - } - debounce = Timer(const Duration(milliseconds: debouneTime), () { - sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); - }); - }, - keyboardType: TextInputType.text, - controller: sub.csSalt, - obscureText: - sub.isCesiumIDVisible, //This will obscure text dynamically - decoration: InputDecoration( - hintText: 'Entrez votre identifiant Cesium', - suffixIcon: IconButton( - icon: Icon( - sub.isCesiumIDVisible - ? Icons.visibility - : Icons.visibility_off, - color: Colors.black, - ), - onPressed: () { - sub.cesiumIDisVisible(); - }, - ), - ), - ), - const SizedBox(height: 20), - TextFormField( - autofocus: true, - onChanged: (text) { - if (debounce?.isActive ?? false) { - debounce!.cancel(); - } - debounce = Timer(const Duration(milliseconds: debouneTime), () { - sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); - }); - }, - keyboardType: TextInputType.text, - controller: sub.csPassword, - obscureText: - sub.isCesiumIDVisible, //This will obscure text dynamically - decoration: InputDecoration( - hintText: 'Entrez votre mot de passe Cesium', - suffixIcon: IconButton( - icon: Icon( - sub.isCesiumIDVisible - ? Icons.visibility - : Icons.visibility_off, - color: Colors.black, - ), - onPressed: () { - sub.cesiumIDisVisible(); - }, - ), - ), - ), - const SizedBox(height: 20), - Text( - sub.g1V1NewAddress, - style: const TextStyle( - fontSize: 14.0, - color: Colors.black, - fontWeight: FontWeight.bold, - fontFamily: 'Monospace'), - ), - const SizedBox(height: 20), - balance(context, sub.g1V1NewAddress, 17), - walletOptions.idtyStatus(context, sub.g1V1NewAddress, - isOwner: false, color: Colors.black), - getCerts(context, sub.g1V1NewAddress, 14), - const SizedBox(height: 30), - Text('selectDestWallet'.tr()), - const SizedBox(height: 10), - DropdownButtonHideUnderline( - child: DropdownButton( - // alignment: AlignmentDirectional.topStart, - value: selectedWallet, - icon: const Icon(Icons.keyboard_arrow_down), - items: myWalletProvider.listWallets.map((wallet) { - return DropdownMenuItem( - value: wallet.name, - child: Text(wallet.name!), - ); - }).toList(), - onChanged: (newSelectedWallet) { - selectedWallet = newSelectedWallet.toString(); - sub.reload(); - }, - ), - ), - const SizedBox(height: 30), - SizedBox( - width: 380 * ratio, - height: 60 * ratio, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 4, - primary: orangeC, // background - onPrimary: Colors.white, // foreground - ), + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.black), onPressed: () { - log.d('GOOO'); - }, - child: Text( - 'validate'.tr(), - style: TextStyle( - fontSize: 23 * ratio, fontWeight: FontWeight.w600), - ), - ), - ) - ]); - }))); + resetScreen(context); + + Navigator.of(context).pop(); + }), + title: SizedBox( + height: 22, + child: Text('importOldAccount'.tr()), + )), + body: SafeArea( + child: Consumer(builder: (context, sub, _) { + return FutureBuilder( + future: sub.getBalanceAndIdtyStatus( + sub.g1V1NewAddress, selectedWallet.address!), + builder: (BuildContext context, AsyncSnapshot status) { + // log.d(_certs.data); + + final balance = status.data?[0] ?? 0; + final idtyStatus = status.data?[1]; + final myIdtyStatus = status.data?[2]; + final hasConsumer = status.data?[3] ?? false; + + if (balance != 0 && !hasConsumer) { + canValidate = true; + validationStatus = ''; + } else { + canValidate = false; + validationStatus = hasConsumer + ? 'youMustWaitBeforeCashoutThisAccount'.tr(args: ['X']) + : 'thisAccountIsEmpty'.tr(); + } + + if (idtyStatus != 'noid' && myIdtyStatus != 'noid') { + canValidate = false; + validationStatus = + 'youCannotMigrateIdentityToExistingIdentity'.tr(); + } + + if (sub.g1V1NewAddress == '') { + validationStatus = ''; + } + + log.d( + 'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address!}, $balance, $idtyStatus, $myIdtyStatus'); + + return Column(children: [ + const SizedBox(height: 20), + TextFormField( + autofocus: true, + onChanged: (text) { + if (debounce?.isActive ?? false) { + debounce!.cancel(); + } + debounce = Timer( + const Duration(milliseconds: debouneTime), () { + sub.csToV2Address( + sub.csSalt.text, sub.csPassword.text); + }); + }, + keyboardType: TextInputType.text, + controller: sub.csSalt, + obscureText: sub + .isCesiumIDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'enterCesiumId'.tr(), + suffixIcon: IconButton( + icon: Icon( + sub.isCesiumIDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + sub.cesiumIDisVisible(); + }, + ), + ), + ), + const SizedBox(height: 20), + TextFormField( + autofocus: true, + onChanged: (text) { + if (debounce?.isActive ?? false) { + debounce!.cancel(); + } + debounce = Timer( + const Duration(milliseconds: debouneTime), () { + sub.csToV2Address( + sub.csSalt.text, sub.csPassword.text); + }); + }, + keyboardType: TextInputType.text, + controller: sub.csPassword, + obscureText: sub + .isCesiumIDVisible, //This will obscure text dynamically + decoration: InputDecoration( + hintText: 'enterCesiumPassword'.tr(), + suffixIcon: IconButton( + icon: Icon( + sub.isCesiumIDVisible + ? Icons.visibility + : Icons.visibility_off, + color: Colors.black, + ), + onPressed: () { + sub.cesiumIDisVisible(); + }, + ), + ), + ), + const SizedBox(height: 20), + Text( + sub.g1V1NewAddress, + style: const TextStyle( + fontSize: 14.0, + color: Colors.black, + fontWeight: FontWeight.bold, + fontFamily: 'Monospace'), + ), + const SizedBox(height: 20), + Text( + '$balance $currencyName', + style: const TextStyle(fontSize: 17), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + walletOptions.idtyStatus(context, sub.g1V1NewAddress, + isOwner: false, color: Colors.black), + const SizedBox(width: 10), + getCerts(context, sub.g1V1NewAddress, 14) + ], + ), + const SizedBox(height: 30), + Text('selectDestWallet'.tr()), + const SizedBox(height: 5), + DropdownButtonHideUnderline( + child: DropdownButton( + // alignment: AlignmentDirectional.topStart, + value: selectedWallet, + icon: const Icon(Icons.keyboard_arrow_down), + items: myWalletProvider.listWallets.map((wallet) { + return DropdownMenuItem( + value: wallet, + child: Text( + wallet.name!, + style: const TextStyle(fontSize: 18), + ), + ); + }).toList(), + onChanged: (WalletData? newSelectedWallet) { + selectedWallet = newSelectedWallet!; + sub.reload(); + }, + ), + ), + const SizedBox(height: 30), + SizedBox( + width: 380 * ratio, + height: 60 * ratio, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 4, + primary: orangeC, // background + onPrimary: Colors.white, // foreground + ), + onPressed: canValidate + ? () async { + log.d('GOOO'); + + sub.migrateCsToV2( + sub.csSalt.text, + sub.csPassword.text, + selectedWallet.address!, + balance: balance, + idtyStatus: idtyStatus); + + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const TransactionInProgress(); + }), + ); + resetScreen(context); + } + : null, + child: Text( + 'validate'.tr(), + style: TextStyle( + fontSize: 23 * ratio, + fontWeight: FontWeight.w600), + ), + ), + ), + const SizedBox(height: 10), + Text( + validationStatus, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 15, color: Colors.grey[600]), + ) + ]); + }); + }), + ), + ), + ); + } + + void resetScreen(BuildContext context) { + SubstrateSdk sub = Provider.of(context, listen: false); + + sub.csSalt.text = ''; + sub.csPassword.text = ''; + sub.g1V1NewAddress = ''; } } From 237e581d0f990693a47fda5ea4ece94d374224ba Mon Sep 17 00:00:00 2001 From: poka Date: Thu, 18 Aug 2022 18:22:36 +0200 Subject: [PATCH 11/19] Ready to migrate identity, wait for signMessage methode in sdk https://github.com/polkawallet-io/sdk/issues/31 --- assets/translations/en.json | 3 +- assets/translations/es.json | 3 +- assets/translations/fr.json | 3 +- lib/providers/substrate_sdk.dart | 63 ++++++++++++++++++++++-- lib/screens/myWallets/import_g1_v1.dart | 5 +- lib/screens/transaction_in_progress.dart | 1 + pubspec.yaml | 2 + 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index 81e472f..3bdb47f 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -184,5 +184,6 @@ "youCannotMigrateIdentityToExistingIdentity": "You cannot migrate an identity\nto an account that already has an identity", "importOldAccount": "Import your old account", "enterCesiumId": "Enter your Cesium ID", - "enterCesiumPassword": "Enter your Cesium password" + "enterCesiumPassword": "Enter your Cesium password", + "migrateAccount": "Migrate account" } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index 567af90..a081ff7 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -184,5 +184,6 @@ "youCannotMigrateIdentityToExistingIdentity": "You cannot migrate an identity\nto an account that already has an identity", "importOldAccount": "Import your old account", "enterCesiumId": "Enter your Cesium ID", - "enterCesiumPassword": "Enter your Cesium password" + "enterCesiumPassword": "Enter your Cesium password", + "migrateAccount": "Migrate account" } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index b22d86b..43c01b4 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -185,5 +185,6 @@ "youCannotMigrateIdentityToExistingIdentity": "Vous ne pouvez pas migrer une identité\nvers un compte disposant déjà d'une identité", "importOldAccount": "Importer son ancien compte", "enterCesiumId": "Entrez votre identifiant Cesium", - "enterCesiumPassword": "Entrez votre mot de passe Cesium" + "enterCesiumPassword": "Entrez votre mot de passe Cesium", + "migrateAccount": "Migrer le compte" } \ No newline at end of file diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index d42a865..8af5406 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -270,9 +270,19 @@ class SubstrateSdk with ChangeNotifier { } } - // Future addressToPubkey(String address) async { - // await sdk.api.account.decodeAddress([address]); - // } + Future getGenesisHash() async { + final String genesisHash = await sdk.webView!.evalJavascript( + 'api.genesisHash.toHex()', + wrapPromise: false, + ) ?? + ''; + // log.d('genesisHash: $genesisHash'); + return genesisHash; + } + + Future addressToPubkey(String address) async { + await sdk.api.account.decodeAddress([address]); + } // Future pubkeyToAddress(String pubkey) async { // await sdk.api.account.encodeAddress([pubkey]); @@ -784,6 +794,45 @@ class SubstrateSdk with ChangeNotifier { return await executeCall(txInfo, txOptions, password); } + Future migrateIdentity( + {required String fromAddress, + required String destAddress, + required String password}) async { + transactionStatus = ''; + final fromPubkey = await sdk.api.account.decodeAddress([fromAddress]); + final sender = TxSenderData( + fromAddress, + fromPubkey!.keys.first, + ); + + // final globalBalance = await getBalance(fromAddress); + TxInfoData txInfo; + List txOptions = []; + String? rawParams; + // final destKeyring = getKeypair(destAddress); + + final genesisHash = await getGenesisHash(); + final idtyIndex = await getIdentityIndexOf(destAddress); + // final oldPubkey = await addressToPubkey(fromAddress); + final messageToSign = 'icok$genesisHash$idtyIndex$fromAddress'; + final newKeySig = messageToSign; + + txInfo = TxInfoData( + 'utility', + 'batchAll', + sender, + ); + const tx1 = 'api.tx.universalDividend.claimUds()'; + final tx2 = 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; + const tx3 = 'api.tx.balances.transferAll(false)'; + + rawParams = '[[$tx1, $tx2, $tx3]]'; + + log.d( + 'g1migration args: ${txInfo.module}, ${txInfo.call}, $txOptions, $rawParams'); + return await executeCall(txInfo, txOptions, password, rawParams); + } + Future revokeIdentity(String address, String password) async { final idtyIndex = await getIdentityIndexOf(address); @@ -837,7 +886,13 @@ class SubstrateSdk with ChangeNotifier { password: password, ); - if (balance != 0) { + log.d('g1migration idtyStatus: $idtyStatus'); + if (idtyStatus != 'noid') { + await migrateIdentity( + fromAddress: keypair.address!, + destAddress: destAddress, + password: 'password'); + } else if (balance != 0) { await pay( fromAddress: keypair.address!, destAddress: destAddress, diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index 7892d3b..259ec6e 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -62,6 +62,8 @@ class ImportG1v1 extends StatelessWidget { final myIdtyStatus = status.data?[2]; final hasConsumer = status.data?[3] ?? false; + // log.d('hasconsumer: $hasConsumer'); + if (balance != 0 && !hasConsumer) { canValidate = true; validationStatus = ''; @@ -216,7 +218,6 @@ class ImportG1v1 extends StatelessWidget { selectedWallet.address!, balance: balance, idtyStatus: idtyStatus); - Navigator.push( context, MaterialPageRoute(builder: (context) { @@ -227,7 +228,7 @@ class ImportG1v1 extends StatelessWidget { } : null, child: Text( - 'validate'.tr(), + 'migrateAccount'.tr(), style: TextStyle( fontSize: 23 * ratio, fontWeight: FontWeight.w600), diff --git a/lib/screens/transaction_in_progress.dart b/lib/screens/transaction_in_progress.dart index 548ba06..d63e166 100644 --- a/lib/screens/transaction_in_progress.dart +++ b/lib/screens/transaction_in_progress.dart @@ -88,6 +88,7 @@ class TransactionInProgress extends StatelessWidget { if (result.contains('blockHash: ')) { isValid = true; resultText = 'extrinsicValidated'.tr(args: [actionName]); + log.i('Bloc of last transaction: ${sub.blocNumber} --- $result'); } else { isValid = false; resultText = "${"anErrorOccured".tr()}:\n"; diff --git a/pubspec.yaml b/pubspec.yaml index aad5a24..a04320a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,6 +62,8 @@ dependencies: package_info_plus: ^1.4.2 polkawallet_sdk: #^0.4.9 git: + # url: https://github.com/polkawallet-io/sdk.git + # ref: develop url: https://github.com/poka-IT/sdk.git ref: gecko-old dots_indicator: ^2.1.0 From d42e7154829971645e2561efc9d8107a9f70e6a6 Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 19 Aug 2022 14:10:27 +0200 Subject: [PATCH 12/19] WIP: continue digging identity migration --- lib/providers/substrate_sdk.dart | 90 ++++++++++++++---------- lib/screens/home.dart | 3 +- lib/screens/myWallets/import_g1_v1.dart | 19 +++++ lib/screens/transaction_in_progress.dart | 3 +- 4 files changed, 75 insertions(+), 40 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 8af5406..34571f3 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; +import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; @@ -14,6 +15,7 @@ import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/polkawallet_sdk.dart'; import 'package:polkawallet_sdk/storage/keyring.dart'; import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; +import 'package:polkawallet_sdk/webviewWithExtension/types/signExtrinsicParam.dart'; import 'package:provider/provider.dart'; import 'package:truncate/truncate.dart'; import 'package:pointycastle/pointycastle.dart' as pc; @@ -280,8 +282,14 @@ class SubstrateSdk with ChangeNotifier { return genesisHash; } - Future addressToPubkey(String address) async { - await sdk.api.account.decodeAddress([address]); + Future addressToPubkey(String address, + [bool toBase58 = false]) async { + final pubkey = await sdk.api.account.decodeAddress([address]); + final String pubkeyHex = pubkey!.keys.first; + final pubkeyByte = HEX.decode(pubkeyHex.substring(2)) as Uint8List; + final pubkey58 = Base58Encode(pubkeyByte); + + return toBase58 ? pubkey58 : pubkeyHex; } // Future pubkeyToAddress(String pubkey) async { @@ -610,25 +618,6 @@ class SubstrateSdk with ChangeNotifier { cryptoType: CryptoType.ed25519, rawSeed: rawSeedHex); - // final json = await sdk.api.keyring.importAccount(keyring, - // keyType: KeyType.rawSeed, - // key: rawSeedHex, - // name: 'test', - // password: 'password', - // derivePath: '', - // cryptoType: CryptoType.ed25519); - - // final keypair = await sdk.api.keyring.addAccount( - // keyring, - // keyType: KeyType.rawSeed, - // acc: json!, - // password: password, - // ); - // await sdk.api.keyring.deleteAccount(keyring, keypair); - - // final keypair2 = KeyPairData.fromJson(json as Map); - - // g1V1NewAddress = keypair.address!; g1V1NewAddress = newAddress.address!; notifyListeners(); } @@ -794,10 +783,26 @@ class SubstrateSdk with ChangeNotifier { return await executeCall(txInfo, txOptions, password); } + Future signMessage( + String message, String address, String password) async { + final params = SignAsExtensionParam(); + params.msgType = "pub(bytes.sign)"; + params.request = { + "address": address, + "data": message, + }; + + final res = await sdk.api.keyring.signAsExtension(password, params); + // log.d('signaturee: ${res?.signature}'); + + return res?.signature ?? ''; + } + Future migrateIdentity( {required String fromAddress, required String destAddress, - required String password}) async { + required String formPassword, + required String destPassword}) async { transactionStatus = ''; final fromPubkey = await sdk.api.account.decodeAddress([fromAddress]); final sender = TxSenderData( @@ -810,27 +815,35 @@ class SubstrateSdk with ChangeNotifier { List txOptions = []; String? rawParams; // final destKeyring = getKeypair(destAddress); + // await sdk.api.keyring.signatureVerify(message, signature, address) final genesisHash = await getGenesisHash(); - final idtyIndex = await getIdentityIndexOf(destAddress); - // final oldPubkey = await addressToPubkey(fromAddress); - final messageToSign = 'icok$genesisHash$idtyIndex$fromAddress'; - final newKeySig = messageToSign; + final idtyIndex = await getIdentityIndexOf(fromAddress); + final oldPubkey = await addressToPubkey(fromAddress, true); + final messageToSign = 'icok$genesisHash$idtyIndex$oldPubkey'; + final newKeySig = + await signMessage(messageToSign, destAddress, destPassword); txInfo = TxInfoData( - 'utility', - 'batchAll', + 'identity', + 'changeOwnerKey', sender, ); - const tx1 = 'api.tx.universalDividend.claimUds()'; - final tx2 = 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; - const tx3 = 'api.tx.balances.transferAll(false)'; - rawParams = '[[$tx1, $tx2, $tx3]]'; + txOptions = [destAddress, newKeySig]; - log.d( - 'g1migration args: ${txInfo.module}, ${txInfo.call}, $txOptions, $rawParams'); - return await executeCall(txInfo, txOptions, password, rawParams); + // const tx1 = 'api.tx.universalDividend.claimUds()'; + // final tx2 = 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; + // const tx3 = 'api.tx.balances.transferAll(false)'; + + // rawParams = '[[$tx1, $tx2, $tx3]]'; + + log.d("""g1migration args:${txInfo.module}, ${txInfo.call}, + txOptions: $txOptions + rawParams: $rawParams + messageToSign: $messageToSign + newKeySig: $newKeySig"""); + return await executeCall(txInfo, txOptions, formPassword, rawParams); } Future revokeIdentity(String address, String password) async { @@ -856,7 +869,9 @@ class SubstrateSdk with ChangeNotifier { } Future migrateCsToV2(String salt, String password, String destAddress, - {required double balance, String idtyStatus = 'noid'}) async { + {required destPassword, + required double balance, + String idtyStatus = 'noid'}) async { final scrypt = pc.KeyDerivator('scrypt'); scrypt.init( @@ -891,7 +906,8 @@ class SubstrateSdk with ChangeNotifier { await migrateIdentity( fromAddress: keypair.address!, destAddress: destAddress, - password: 'password'); + formPassword: 'password', + destPassword: destPassword); } else if (balance != 0) { await pay( fromAddress: keypair.address!, diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 297121b..f586685 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -39,8 +39,7 @@ class HomeScreen extends StatelessWidget { final bool isWalletsExists = myWalletProvider.checkIfWalletExist(); - // sub.csToV2('test', 'test'); - // sub.getSs58Prefix(); + // sub.addressToPubkey('5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn'); isTall = false; ratio = 1; diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index 259ec6e..a9fbc21 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:async'; import 'package:easy_localization/easy_localization.dart'; @@ -8,6 +10,7 @@ import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallet_options.dart'; +import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/transaction_in_progress.dart'; import 'package:provider/provider.dart'; @@ -211,11 +214,27 @@ class ImportG1v1 extends StatelessWidget { onPressed: canValidate ? () async { log.d('GOOO'); + WalletData? defaultWallet = + myWalletProvider.getDefaultWallet(); + + String? pin; + if (myWalletProvider.pinCode == '') { + pin = await Navigator.push( + context, + MaterialPageRoute( + builder: (homeContext) { + return UnlockingWallet( + wallet: defaultWallet); + }, + ), + ); + } sub.migrateCsToV2( sub.csSalt.text, sub.csPassword.text, selectedWallet.address!, + destPassword: pin ?? myWalletProvider.pinCode, balance: balance, idtyStatus: idtyStatus); Navigator.push( diff --git a/lib/screens/transaction_in_progress.dart b/lib/screens/transaction_in_progress.dart index d63e166..6ab820b 100644 --- a/lib/screens/transaction_in_progress.dart +++ b/lib/screens/transaction_in_progress.dart @@ -88,7 +88,8 @@ class TransactionInProgress extends StatelessWidget { if (result.contains('blockHash: ')) { isValid = true; resultText = 'extrinsicValidated'.tr(args: [actionName]); - log.i('Bloc of last transaction: ${sub.blocNumber} --- $result'); + log.i( + 'g1migration Bloc of last transaction: ${sub.blocNumber} --- $result'); } else { isValid = false; resultText = "${"anErrorOccured".tr()}:\n"; From 506110cfc8fcd7fdb91922c4d2294378d0401305 Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 19 Aug 2022 19:23:38 +0200 Subject: [PATCH 13/19] use binary concatenation instead of string --- lib/providers/substrate_sdk.dart | 36 +++++++++++++++++++------------- lib/screens/home.dart | 2 -- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 34571f3..2a89879 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; -import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; @@ -282,14 +281,13 @@ class SubstrateSdk with ChangeNotifier { return genesisHash; } - Future addressToPubkey(String address, - [bool toBase58 = false]) async { + Future addressToPubkey(String address) async { final pubkey = await sdk.api.account.decodeAddress([address]); final String pubkeyHex = pubkey!.keys.first; final pubkeyByte = HEX.decode(pubkeyHex.substring(2)) as Uint8List; - final pubkey58 = Base58Encode(pubkeyByte); + // final pubkey58 = Base58Encode(pubkeyByte); - return toBase58 ? pubkey58 : pubkeyHex; + return pubkeyByte; } // Future pubkeyToAddress(String pubkey) async { @@ -784,7 +782,7 @@ class SubstrateSdk with ChangeNotifier { } Future signMessage( - String message, String address, String password) async { + Uint8List message, String address, String password) async { final params = SignAsExtensionParam(); params.msgType = "pub(bytes.sign)"; params.request = { @@ -817,13 +815,26 @@ class SubstrateSdk with ChangeNotifier { // final destKeyring = getKeypair(destAddress); // await sdk.api.keyring.signatureVerify(message, signature, address) - final genesisHash = await getGenesisHash(); - final idtyIndex = await getIdentityIndexOf(fromAddress); - final oldPubkey = await addressToPubkey(fromAddress, true); - final messageToSign = 'icok$genesisHash$idtyIndex$oldPubkey'; + final prefix = 'icok'.codeUnits; + final genesisHash = (await getGenesisHash()).substring(2).codeUnits; + final idtyIndex = [await getIdentityIndexOf(fromAddress)]; + final oldPubkey = await addressToPubkey(fromAddress); + // final messageToSign = 'icok$genesisHash$idtyIndex$oldPubkey'; + final messageToSign = + Uint8List.fromList(prefix + genesisHash + idtyIndex + oldPubkey); final newKeySig = await signMessage(messageToSign, destAddress, destPassword); + log.d(""" +prefix: $prefix +genesisHash: $genesisHash +idtyIndex: $idtyIndex +oldPubkey: $oldPubkey +messageToSign: $messageToSign +newKeySig: $newKeySig"""); + + // [105, 99, 111, 107, 48, 55, 99, 49, 49, 50, 102, 102, 54, 97, 98, 57, 100, 55, 100, 48, 100, 53, 51, 49, 101, 98, 101, 53, 57, 102, 57, 56, 98, 51, 53, 51, 49, 56, 98, 50, 56, 49, 51, 98, 49, 54, 53, 53, 53, 55, 55, 51, 56, 48, 56, 49, 57, 100, 51, 56, 100, 54, 49, 56, 50, 100, 57, 57, 21, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] + // [105, 99, 111, 107, 48, 55, 99, 49, 49, 50, 102, 102, 54, 97, 98, 57, 100, 55, 100, 48, 100, 53, 51, 49, 101, 98, 101, 53, 57, 102, 57, 56, 98, 51, 53, 51, 49, 56, 98, 50, 56, 49, 51, 98, 49, 54, 53, 53, 53, 55, 55, 51, 56, 48, 56, 49, 57, 100, 51, 56, 100, 54, 49, 56, 50, 100, 57, 57, 21, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] txInfo = TxInfoData( 'identity', 'changeOwnerKey', @@ -838,11 +849,6 @@ class SubstrateSdk with ChangeNotifier { // rawParams = '[[$tx1, $tx2, $tx3]]'; - log.d("""g1migration args:${txInfo.module}, ${txInfo.call}, - txOptions: $txOptions - rawParams: $rawParams - messageToSign: $messageToSign - newKeySig: $newKeySig"""); return await executeCall(txInfo, txOptions, formPassword, rawParams); } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index f586685..4157045 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -39,8 +39,6 @@ class HomeScreen extends StatelessWidget { final bool isWalletsExists = myWalletProvider.checkIfWalletExist(); - // sub.addressToPubkey('5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn'); - isTall = false; ratio = 1; if (MediaQuery.of(context).size.height >= 930) { From 99f939d5a21838015e22217961a8b9285dbac108 Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 19 Aug 2022 23:15:41 +0200 Subject: [PATCH 14/19] WIP: message to sign is ok, but bad use of Uint8List signature --- lib/providers/substrate_sdk.dart | 84 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 2a89879..94696c2 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; +import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; @@ -43,7 +44,7 @@ class SubstrateSdk with ChangeNotifier { ////////// 1: API METHODS /////////// ///////////////////////////////////// - Future executeCall(TxInfoData txInfo, txOptions, String password, + Future _executeCall(TxInfoData txInfo, txOptions, String password, [String? rawParams]) async { try { final hash = await sdk.api.tx @@ -70,11 +71,11 @@ class SubstrateSdk with ChangeNotifier { } } - Future getStorage(String call) async { + Future _getStorage(String call) async { return await sdk.webView!.evalJavascript('api.query.$call'); } - Future getStorageConst(String call) async { + Future _getStorageConst(String call) async { return (await sdk.webView! .evalJavascript('api.consts.$call', wrapPromise: false) ?? [null])[0]; @@ -92,13 +93,13 @@ class SubstrateSdk with ChangeNotifier { //////////////////////////////////////////// Future getIdentityIndexOf(String address) async { - return await getStorage('identity.identityIndexOf("$address")') ?? 0; + return await _getStorage('identity.identityIndexOf("$address")') ?? 0; } Future> getCerts(String address) async { final idtyIndex = await getIdentityIndexOf(address); final certsReceiver = - await getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? []; + await _getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? []; return [certsReceiver['receivedCount'], certsReceiver['issuedCount']]; } @@ -110,7 +111,7 @@ class SubstrateSdk with ChangeNotifier { if (idtyIndexFrom == 0 || idtyIndexTo == 0) return 0; final List certData = - await getStorage('cert.certsByReceiver($idtyIndexTo)') ?? []; + await _getStorage('cert.certsByReceiver($idtyIndexTo)') ?? []; if (certData.isEmpty) return 0; for (List certInfo in certData) { @@ -123,7 +124,7 @@ class SubstrateSdk with ChangeNotifier { } Future hasAccountConsumers(String address) async { - final accountInfo = await getStorage('system.account("$address")'); + final accountInfo = await _getStorage('system.account("$address")'); final consumers = accountInfo['consumers']; return consumers == 0 ? false : true; } @@ -156,16 +157,16 @@ class SubstrateSdk with ChangeNotifier { } // Get onchain storage values - final Map balanceGlobal = await getStorage('system.account("$address")'); + final Map balanceGlobal = await _getStorage('system.account("$address")'); final int? idtyIndex = - await getStorage('identity.identityIndexOf("$address")'); + await _getStorage('identity.identityIndexOf("$address")'); final Map? idtyData = idtyIndex == null ? null - : await getStorage('identity.identities($idtyIndex)'); + : await _getStorage('identity.identities($idtyIndex)'); final int currentUdIndex = - int.parse(await getStorage('universalDividend.currentUdIndex()')); + int.parse(await _getStorage('universalDividend.currentUdIndex()')); final List pastReevals = - await getStorage('universalDividend.pastReevals()'); + await _getStorage('universalDividend.pastReevals()'); // Compute amount of claimable UDs final int unclaimedUds = _computeUnclaimUds(currentUdIndex, @@ -248,7 +249,7 @@ class SubstrateSdk with ChangeNotifier { var idtyIndex = await getIdentityIndexOf(address); final certMeta = - await getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? ''; + await _getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? ''; return certMeta; } @@ -260,7 +261,7 @@ class SubstrateSdk with ChangeNotifier { return 'noid'; } - final idtyStatus = await getStorage('identity.identities($idtyIndex)'); + final idtyStatus = await _getStorage('identity.identities($idtyIndex)'); if (idtyStatus != null) { final String status = idtyStatus['status']; @@ -276,8 +277,9 @@ class SubstrateSdk with ChangeNotifier { 'api.genesisHash.toHex()', wrapPromise: false, ) ?? - ''; + []; // log.d('genesisHash: $genesisHash'); + // log.d('genesisHash: ${HEX.decode(genesisHash.substring(2))}'); return genesisHash; } @@ -285,7 +287,8 @@ class SubstrateSdk with ChangeNotifier { final pubkey = await sdk.api.account.decodeAddress([address]); final String pubkeyHex = pubkey!.keys.first; final pubkeyByte = HEX.decode(pubkeyHex.substring(2)) as Uint8List; - // final pubkey58 = Base58Encode(pubkeyByte); + final pubkey58 = Base58Encode(pubkeyByte); + log.d('tatatatata: $pubkey58'); return pubkeyByte; } @@ -296,19 +299,19 @@ class SubstrateSdk with ChangeNotifier { Future initCurrencyParameters() async { currencyParameters['ss58'] = - await getStorageConst('system.ss58Prefix.words'); + await _getStorageConst('system.ss58Prefix.words'); currencyParameters['minCertForMembership'] = - await getStorageConst('wot.minCertForMembership.words'); + await _getStorageConst('wot.minCertForMembership.words'); currencyParameters['newAccountPrice'] = - await getStorageConst('account.newAccountPrice.words'); + await _getStorageConst('account.newAccountPrice.words'); currencyParameters['existentialDeposit'] = - await getStorageConst('balances.existentialDeposit.words'); + await _getStorageConst('balances.existentialDeposit.words'); currencyParameters['certPeriod'] = - await getStorageConst('cert.certPeriod.words'); + await _getStorageConst('cert.certPeriod.words'); currencyParameters['certMaxByIssuer'] = - await getStorageConst('cert.maxByIssuer.words'); + await _getStorageConst('cert.maxByIssuer.words'); currencyParameters['certValidityPeriod'] = - await getStorageConst('cert.validityPeriod.words'); + await _getStorageConst('cert.validityPeriod.words'); log.i('currencyParameters: $currencyParameters'); } @@ -680,7 +683,7 @@ class SubstrateSdk with ChangeNotifier { } // log.d('pay args: ${txInfo.module}, ${txInfo.call}, $txOptions, $rawParams'); - return await executeCall(txInfo, txOptions, password, rawParams); + return await _executeCall(txInfo, txOptions, password, rawParams); } Future certify( @@ -744,7 +747,7 @@ class SubstrateSdk with ChangeNotifier { } log.d('Cert action: ${txInfo.call!}'); - return await executeCall(txInfo, txOptions, password, rawParams); + return await _executeCall(txInfo, txOptions, password, rawParams); } // Future claimUDs(String password) async { @@ -778,7 +781,7 @@ class SubstrateSdk with ChangeNotifier { ); final txOptions = [name]; - return await executeCall(txInfo, txOptions, password); + return await _executeCall(txInfo, txOptions, password); } Future signMessage( @@ -791,8 +794,6 @@ class SubstrateSdk with ChangeNotifier { }; final res = await sdk.api.keyring.signAsExtension(password, params); - // log.d('signaturee: ${res?.signature}'); - return res?.signature ?? ''; } @@ -808,33 +809,37 @@ class SubstrateSdk with ChangeNotifier { fromPubkey!.keys.first, ); - // final globalBalance = await getBalance(fromAddress); TxInfoData txInfo; List txOptions = []; String? rawParams; - // final destKeyring = getKeypair(destAddress); - // await sdk.api.keyring.signatureVerify(message, signature, address) final prefix = 'icok'.codeUnits; - final genesisHash = (await getGenesisHash()).substring(2).codeUnits; - final idtyIndex = [await getIdentityIndexOf(fromAddress)]; + final genesisHashString = await getGenesisHash(); + final genesisHash = HEX.decode(genesisHashString.substring(2)) as Uint8List; + final idtyIndex = int32bytes(await getIdentityIndexOf(fromAddress)); final oldPubkey = await addressToPubkey(fromAddress); - // final messageToSign = 'icok$genesisHash$idtyIndex$oldPubkey'; final messageToSign = Uint8List.fromList(prefix + genesisHash + idtyIndex + oldPubkey); + final messageToSignHex = HEX.encode(messageToSign); final newKeySig = await signMessage(messageToSign, destAddress, destPassword); + // messageToSign: [105, 99, 111, 107, 7, 193, 18, 255, 106, 185, 215, 208, 213, 49, 235, 229, 159, 152, 179, 83, 24, 178, 129, 59, 22, 85, 87, 115, 128, 129, 157, 56, 214, 24, 45, 153, 21, 0, 0, 0, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] + log.d(""" +fromAddress: $fromAddress +destAddress: $destAddress +genesisHashString: $genesisHashString + prefix: $prefix genesisHash: $genesisHash idtyIndex: $idtyIndex oldPubkey: $oldPubkey + messageToSign: $messageToSign +messageToSignHex: $messageToSignHex newKeySig: $newKeySig"""); - // [105, 99, 111, 107, 48, 55, 99, 49, 49, 50, 102, 102, 54, 97, 98, 57, 100, 55, 100, 48, 100, 53, 51, 49, 101, 98, 101, 53, 57, 102, 57, 56, 98, 51, 53, 51, 49, 56, 98, 50, 56, 49, 51, 98, 49, 54, 53, 53, 53, 55, 55, 51, 56, 48, 56, 49, 57, 100, 51, 56, 100, 54, 49, 56, 50, 100, 57, 57, 21, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] - // [105, 99, 111, 107, 48, 55, 99, 49, 49, 50, 102, 102, 54, 97, 98, 57, 100, 55, 100, 48, 100, 53, 51, 49, 101, 98, 101, 53, 57, 102, 57, 56, 98, 51, 53, 51, 49, 56, 98, 50, 56, 49, 51, 98, 49, 54, 53, 53, 53, 55, 55, 51, 56, 48, 56, 49, 57, 100, 51, 56, 100, 54, 49, 56, 50, 100, 57, 57, 21, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] txInfo = TxInfoData( 'identity', 'changeOwnerKey', @@ -849,7 +854,7 @@ newKeySig: $newKeySig"""); // rawParams = '[[$tx1, $tx2, $tx3]]'; - return await executeCall(txInfo, txOptions, formPassword, rawParams); + return await _executeCall(txInfo, txOptions, formPassword, rawParams); } Future revokeIdentity(String address, String password) async { @@ -871,7 +876,7 @@ newKeySig: $newKeySig"""); final txOptions = [idtyIndex]; - return await executeCall(txInfo, txOptions, password); + return await _executeCall(txInfo, txOptions, password); } Future migrateCsToV2(String salt, String password, String destAddress, @@ -976,3 +981,6 @@ class PasswordException implements Exception { String cause; PasswordException(this.cause); } + +Uint8List int32bytes(int value) => + Uint8List(4)..buffer.asInt32List()[0] = value; From c840753f4a4c33d352f34181531c7dfe1da35954 Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 20 Aug 2022 16:55:55 +0200 Subject: [PATCH 15/19] identity migration is working --- lib/providers/substrate_sdk.dart | 38 +++++++++++++++++++++----------- pubspec.lock | 4 ++-- pubspec.yaml | 3 ++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 94696c2..6f43a5c 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -598,7 +598,7 @@ class SubstrateSdk with ChangeNotifier { return await sdk.api.keyring.checkMnemonicValid(mnemonic); } - Future csToV2Address(String salt, String password) async { + Future csToV2Address(String salt, String password) async { final scrypt = pc.KeyDerivator('scrypt'); scrypt.init( @@ -621,6 +621,7 @@ class SubstrateSdk with ChangeNotifier { g1V1NewAddress = newAddress.address!; notifyListeners(); + return g1V1NewAddress; } Future getBalanceAndIdtyStatus(String address, String myAddress) async { @@ -801,7 +802,8 @@ class SubstrateSdk with ChangeNotifier { {required String fromAddress, required String destAddress, required String formPassword, - required String destPassword}) async { + required String destPassword, + bool withBalance = false}) async { transactionStatus = ''; final fromPubkey = await sdk.api.account.decodeAddress([fromAddress]); final sender = TxSenderData( @@ -840,19 +842,28 @@ messageToSign: $messageToSign messageToSignHex: $messageToSignHex newKeySig: $newKeySig"""); - txInfo = TxInfoData( - 'identity', - 'changeOwnerKey', - sender, - ); + if (withBalance) { + txInfo = TxInfoData( + 'utility', + 'batchAll', + sender, + ); - txOptions = [destAddress, newKeySig]; + const tx1 = 'api.tx.universalDividend.claimUds()'; + final tx2 = + 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; + const tx3 = 'api.tx.balances.transferAll(false)'; - // const tx1 = 'api.tx.universalDividend.claimUds()'; - // final tx2 = 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; - // const tx3 = 'api.tx.balances.transferAll(false)'; + rawParams = '[[$tx1, $tx2, $tx3]]'; + } else { + txInfo = TxInfoData( + 'identity', + 'changeOwnerKey', + sender, + ); - // rawParams = '[[$tx1, $tx2, $tx3]]'; + txOptions = [destAddress, newKeySig]; + } return await _executeCall(txInfo, txOptions, formPassword, rawParams); } @@ -918,7 +929,8 @@ newKeySig: $newKeySig"""); fromAddress: keypair.address!, destAddress: destAddress, formPassword: 'password', - destPassword: destPassword); + destPassword: destPassword, + withBalance: true); } else if (balance != 0) { await pay( fromAddress: keypair.address!, diff --git a/pubspec.lock b/pubspec.lock index 949cbc3..d404e72 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1062,8 +1062,8 @@ packages: dependency: "direct main" description: path: "." - ref: gecko-old - resolved-ref: "87096351fb187614b6386343615db39a2f2b5b9b" + ref: gecko-unwrapbytes + resolved-ref: b019cc2a6e77b6989f94b1bef8259298410cd82a url: "https://github.com/poka-IT/sdk.git" source: git version: "0.4.8" diff --git a/pubspec.yaml b/pubspec.yaml index a04320a..58d1deb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,7 +65,8 @@ dependencies: # url: https://github.com/polkawallet-io/sdk.git # ref: develop url: https://github.com/poka-IT/sdk.git - ref: gecko-old + # ref: gecko-old + ref: gecko-unwrapbytes dots_indicator: ^2.1.0 web_socket_channel: ^2.2.0 connectivity_plus: ^2.3.3 From ad601be19ce9e40ef9b137828187c63d9bf5d22a Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 20 Aug 2022 20:08:02 +0200 Subject: [PATCH 16/19] can migrate identity from standart mnemonic derivation --- assets/skull_Icon.png | Bin 0 -> 2280 bytes assets/translations/en.json | 5 +- assets/translations/es.json | 5 +- assets/translations/fr.json | 5 +- lib/providers/substrate_sdk.dart | 99 ++++---- lib/providers/wallet_options.dart | 7 +- lib/screens/myWallets/import_g1_v1.dart | 21 +- lib/screens/myWallets/manage_membership.dart | 50 +++- lib/screens/myWallets/migrate_identity.dart | 251 +++++++++++++++++++ lib/screens/transaction_in_progress.dart | 23 +- 10 files changed, 384 insertions(+), 82 deletions(-) create mode 100755 assets/skull_Icon.png create mode 100644 lib/screens/myWallets/migrate_identity.dart diff --git a/assets/skull_Icon.png b/assets/skull_Icon.png new file mode 100755 index 0000000000000000000000000000000000000000..3a789faff538ef15afac47e1a7651b99daf2c05c GIT binary patch literal 2280 zcmeH|`&$x*8plCF&A`hUI%P<56fdRA3u@?51iT?$2wQ2UDXF0*nls8=k$NP>ENxyA zI|x{aW)AU2rlz%3UP?^oa;Ov0g&r$QE5n&{KkPr)vtQ2nJkR(2KJW9qzr5e~hqs6l z76{dc>jMA)C@IK~y6uOym7u4+UB6#H5(5Be{f82Az<;~_KYvLAT7L_`{~5NnwuEE< zKyTk>I*S?>0RU=ggTOkvdOP%YLZAkQM#i7POiVvFGlzeHus~X({%K{6wzae0?cliA z$=Ssf7FM9Xu3yIQmFT>`~gWgrwv22~vXEz;Juj!xN~uDjj6_xk$pfB(b7M*~B{Po9p*N1u(2|2Xk{@@K`=^vo}_$~o2i z!mlsXi%b7qe);P4%A2>VYwzBFSpTTm_-*r(^vhfLo8s>{=4 z+U)}>r>}Y!`<32MykSg^vBrTVd4#OThi6)CmO+1c*0eUlGg_C-kXYvwJGm}q7qpY; zk#ljDz3i@PrjCtvO2FnL0QOhGEue>)q_Rvs=LMgw@=?#nz-hYO&@>SWF*dsZfM&YF z^an7*o@drHCG2Fl-ee|RO_o(RkNUm`1yPg5h@h}BN@!U|i#*OeV?fm3NR$gW0X3lh zRm@bqQNptf79pejVJkous7lltanTFDPz}k8_O;3HGcWOmuwe+AQxgH4kJ|ad43aHQ zaDu5Y`AX|SGsyA%emHD;#R4O`me=e2Vk6annF+6zw08BRCY7AojZp8xon%b3=q@+* zyj2y&ub4@d#y#c7&^?=6xK{cx9~NQn2iIEs@duxTROhSeL{@s1o8*#yjuoFq@G|Ko zw0*08T0;zdo;G;7nxC@E#2xUHSOQ;?+SNc$eMgB0mWE&H2ojTpCjjHsj8PTZvIJQ# zK=Byv^hr{6yN6L?{Rt}!L>RrZts5VO1|7E}v)RVw{=^4ygG_=XSE`gdRY>2+sezq~ zM%^JEfp(ZC!3oE<>vcD7<3OUE@^K>BInhK;4IVI;eM2N!VAj%Z4EuoK9Q%PhG8}Cv zi1#s(3IwHBtz~|bc4t9Q+lCCB*3x;t7z-1+a1iknx9V6Xej3XOwv56Tfm6;Nz45ss zQrs0bN)6(5L|_b4IwHmy_3Ec_Vs&a=u{WGyYd6T|m>6`mp+hCqtOabATahrLv?p{l zJF9($v>&(vM!&OH(_H<{OABy<;#F+cv(7>Wsqah|mRWGW=A)^K3iDUnXw1kntrf*D9|LuK%U<7h?^j#vOLg~?TPgy-6jEc~XHY<{$+oj$p5 z=sICfMTaldAFNPbYFj&JsCG2@(tepu2;w%>x9>Wl!9*POv34B)TK_6_NdX-2UYZ0A zcrHbQNZ@xNxd{%Zuov;t3Qz8aFO9+H1a74MUMyMq=WJrDUv literal 0 HcmV?d00001 diff --git a/assets/translations/en.json b/assets/translations/en.json index 3bdb47f..d3d510a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -185,5 +185,8 @@ "importOldAccount": "Import your old account", "enterCesiumId": "Enter your Cesium ID", "enterCesiumPassword": "Enter your Cesium password", - "migrateAccount": "Migrate account" + "migrateAccount": "Migrate account", + "migrateIdentity": "Migrate identity", + "identityMigration": "Identity migration", + "areYouSureMigrateIdentity": "Are you sure you want to permanently migrate identity **{}** with balance of **{}** ?" } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index a081ff7..8994665 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -185,5 +185,8 @@ "importOldAccount": "Import your old account", "enterCesiumId": "Enter your Cesium ID", "enterCesiumPassword": "Enter your Cesium password", - "migrateAccount": "Migrate account" + "migrateAccount": "Migrate account", + "migrateIdentity": "Migrate identity", + "identityMigration": "Identity migration", + "areYouSureMigrateIdentity": "Are you sure you want to permanently migrate identity **{}** with balance of **{}** ?" } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 43c01b4..26b93ad 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -186,5 +186,8 @@ "importOldAccount": "Importer son ancien compte", "enterCesiumId": "Entrez votre identifiant Cesium", "enterCesiumPassword": "Entrez votre mot de passe Cesium", - "migrateAccount": "Migrer le compte" + "migrateAccount": "Migrer le compte", + "migrateIdentity": "Migrer l'identité", + "identityMigration": "Migration de l'identité", + "areYouSureMigrateIdentity": "Êtes-vous certain de vouloir migrer définitivement l'identité **{}** et son solde de **{}** ?" } \ No newline at end of file diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 6f43a5c..377dc21 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:easy_localization/easy_localization.dart'; -import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; @@ -88,16 +87,29 @@ class SubstrateSdk with ChangeNotifier { ); } + Future _signMessage( + Uint8List message, String address, String password) async { + final params = SignAsExtensionParam(); + params.msgType = "pub(bytes.sign)"; + params.request = { + "address": address, + "data": message, + }; + + final res = await sdk.api.keyring.signAsExtension(password, params); + return res?.signature ?? ''; + } + //////////////////////////////////////////// ////////// 2: GET ONCHAIN STORAGE ////////// //////////////////////////////////////////// - Future getIdentityIndexOf(String address) async { + Future _getIdentityIndexOf(String address) async { return await _getStorage('identity.identityIndexOf("$address")') ?? 0; } Future> getCerts(String address) async { - final idtyIndex = await getIdentityIndexOf(address); + final idtyIndex = await _getIdentityIndexOf(address); final certsReceiver = await _getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? []; @@ -105,8 +117,8 @@ class SubstrateSdk with ChangeNotifier { } Future getCertValidityPeriod(String from, String to) async { - final idtyIndexFrom = await getIdentityIndexOf(from); - final idtyIndexTo = await getIdentityIndexOf(to); + final idtyIndexFrom = await _getIdentityIndexOf(from); + final idtyIndexTo = await _getIdentityIndexOf(to); if (idtyIndexFrom == 0 || idtyIndexTo == 0) return 0; @@ -246,7 +258,7 @@ class SubstrateSdk with ChangeNotifier { } Future getCertMeta(String address) async { - var idtyIndex = await getIdentityIndexOf(address); + var idtyIndex = await _getIdentityIndexOf(address); final certMeta = await _getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? ''; @@ -255,7 +267,7 @@ class SubstrateSdk with ChangeNotifier { } Future idtyStatus(String address) async { - var idtyIndex = await getIdentityIndexOf(address); + var idtyIndex = await _getIdentityIndexOf(address); if (idtyIndex == 0) { return 'noid'; @@ -287,8 +299,7 @@ class SubstrateSdk with ChangeNotifier { final pubkey = await sdk.api.account.decodeAddress([address]); final String pubkeyHex = pubkey!.keys.first; final pubkeyByte = HEX.decode(pubkeyHex.substring(2)) as Uint8List; - final pubkey58 = Base58Encode(pubkeyByte); - log.d('tatatatata: $pubkey58'); + // final pubkey58 = Base58Encode(pubkeyByte); return pubkeyByte; } @@ -624,22 +635,18 @@ class SubstrateSdk with ChangeNotifier { return g1V1NewAddress; } - Future getBalanceAndIdtyStatus(String address, String myAddress) async { - final balance = - address == '' ? {'transferableBalance': 0} : await getBalance(address); - final thisIdtyStatus = address == '' ? 'noid' : await idtyStatus(address); - final thisHasConsumer = - address == '' ? false : await hasAccountConsumers(address); - final myIdtyStatus = await idtyStatus(myAddress); + Future getBalanceAndIdtyStatus( + String fromAddress, String toAddress) async { + final fromBalance = fromAddress == '' + ? {'transferableBalance': 0} + : await getBalance(fromAddress); + final fromIdtyStatus = + fromAddress == '' ? 'noid' : await idtyStatus(fromAddress); + final fromHasConsumer = + fromAddress == '' ? false : await hasAccountConsumers(fromAddress); + final toIdtyStatus = await idtyStatus(toAddress); - log.d('tatata: $myIdtyStatus'); - - return [ - balance['transferableBalance'], - thisIdtyStatus, - myIdtyStatus, - thisHasConsumer - ]; + return [fromBalance, fromIdtyStatus, toIdtyStatus, fromHasConsumer]; } ////////////////////////////////////// @@ -694,8 +701,8 @@ class SubstrateSdk with ChangeNotifier { final myIdtyStatus = await idtyStatus(fromAddress); final toIdtyStatus = await idtyStatus(toAddress); - final fromIndex = await getIdentityIndexOf(fromAddress); - final toIndex = await getIdentityIndexOf(toAddress); + final fromIndex = await _getIdentityIndexOf(fromAddress); + final toIndex = await _getIdentityIndexOf(toAddress); if (myIdtyStatus != 'Validated') { transactionStatus = 'notMember'; @@ -785,24 +792,12 @@ class SubstrateSdk with ChangeNotifier { return await _executeCall(txInfo, txOptions, password); } - Future signMessage( - Uint8List message, String address, String password) async { - final params = SignAsExtensionParam(); - params.msgType = "pub(bytes.sign)"; - params.request = { - "address": address, - "data": message, - }; - - final res = await sdk.api.keyring.signAsExtension(password, params); - return res?.signature ?? ''; - } - Future migrateIdentity( {required String fromAddress, required String destAddress, - required String formPassword, + required String fromPassword, required String destPassword, + required Map fromBalance, bool withBalance = false}) async { transactionStatus = ''; final fromPubkey = await sdk.api.account.decodeAddress([fromAddress]); @@ -818,13 +813,13 @@ class SubstrateSdk with ChangeNotifier { final prefix = 'icok'.codeUnits; final genesisHashString = await getGenesisHash(); final genesisHash = HEX.decode(genesisHashString.substring(2)) as Uint8List; - final idtyIndex = int32bytes(await getIdentityIndexOf(fromAddress)); + final idtyIndex = _int32bytes(await _getIdentityIndexOf(fromAddress)); final oldPubkey = await addressToPubkey(fromAddress); final messageToSign = Uint8List.fromList(prefix + genesisHash + idtyIndex + oldPubkey); final messageToSignHex = HEX.encode(messageToSign); final newKeySig = - await signMessage(messageToSign, destAddress, destPassword); + await _signMessage(messageToSign, destAddress, destPassword); // messageToSign: [105, 99, 111, 107, 7, 193, 18, 255, 106, 185, 215, 208, 213, 49, 235, 229, 159, 152, 179, 83, 24, 178, 129, 59, 22, 85, 87, 115, 128, 129, 157, 56, 214, 24, 45, 153, 21, 0, 0, 0, 181, 82, 178, 99, 198, 4, 156, 190, 78, 35, 102, 137, 255, 7, 162, 31, 16, 79, 255, 132, 130, 237, 230, 222, 176, 88, 245, 217, 237, 78, 196, 239] @@ -852,9 +847,10 @@ newKeySig: $newKeySig"""); const tx1 = 'api.tx.universalDividend.claimUds()'; final tx2 = 'api.tx.identity.changeOwnerKey("$destAddress", "$newKeySig")'; - const tx3 = 'api.tx.balances.transferAll(false)'; + // const tx3 = 'api.tx.balances.transferAll(false)'; - rawParams = '[[$tx1, $tx2, $tx3]]'; + rawParams = + fromBalance['unclaimedUds'] == 0 ? '[[$tx2]]' : '[[$tx1, $tx2]]'; } else { txInfo = TxInfoData( 'identity', @@ -865,11 +861,11 @@ newKeySig: $newKeySig"""); txOptions = [destAddress, newKeySig]; } - return await _executeCall(txInfo, txOptions, formPassword, rawParams); + return await _executeCall(txInfo, txOptions, fromPassword, rawParams); } Future revokeIdentity(String address, String password) async { - final idtyIndex = await getIdentityIndexOf(address); + final idtyIndex = await _getIdentityIndexOf(address); final sender = TxSenderData( keyring.current.address, @@ -892,7 +888,7 @@ newKeySig: $newKeySig"""); Future migrateCsToV2(String salt, String password, String destAddress, {required destPassword, - required double balance, + required Map balance, String idtyStatus = 'noid'}) async { final scrypt = pc.KeyDerivator('scrypt'); @@ -928,10 +924,11 @@ newKeySig: $newKeySig"""); await migrateIdentity( fromAddress: keypair.address!, destAddress: destAddress, - formPassword: 'password', + fromPassword: 'password', destPassword: destPassword, - withBalance: true); - } else if (balance != 0) { + withBalance: true, + fromBalance: balance); + } else if (balance['transferableBalance'] != 0) { await pay( fromAddress: keypair.address!, destAddress: destAddress, @@ -994,5 +991,5 @@ class PasswordException implements Exception { PasswordException(this.cause); } -Uint8List int32bytes(int value) => +Uint8List _int32bytes(int value) => Uint8List(4)..buffer.asInt32List()[0] = value; diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index 63a4a2d..bb8a6ea 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -302,8 +302,11 @@ class WalletOptionsProvider with ChangeNotifier { Navigator.push( context, MaterialPageRoute(builder: (context) { - return const TransactionInProgress( - transType: 'comfirmIdty'); + return TransactionInProgress( + transType: 'comfirmIdty', + fromAddress: wallet.address, + toAddress: wallet.address, + ); }), ); } diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index a9fbc21..3833be9 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -60,14 +60,14 @@ class ImportG1v1 extends StatelessWidget { builder: (BuildContext context, AsyncSnapshot status) { // log.d(_certs.data); - final balance = status.data?[0] ?? 0; - final idtyStatus = status.data?[1]; - final myIdtyStatus = status.data?[2]; - final hasConsumer = status.data?[3] ?? false; + final Map balance = status.data?[0] ?? 0; + final String idtyStatus = status.data?[1]; + final String myIdtyStatus = status.data?[2]; + final bool hasConsumer = status.data?[3] ?? false; // log.d('hasconsumer: $hasConsumer'); - if (balance != 0 && !hasConsumer) { + if (balance['transferableBalance'] != 0 && !hasConsumer) { canValidate = true; validationStatus = ''; } else { @@ -87,9 +87,6 @@ class ImportG1v1 extends StatelessWidget { validationStatus = ''; } - log.d( - 'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address!}, $balance, $idtyStatus, $myIdtyStatus'); - return Column(children: [ const SizedBox(height: 20), TextFormField( @@ -234,13 +231,17 @@ class ImportG1v1 extends StatelessWidget { sub.csSalt.text, sub.csPassword.text, selectedWallet.address!, - destPassword: pin ?? myWalletProvider.pinCode, + destPassword: + pin ?? myWalletProvider.pinCode, balance: balance, idtyStatus: idtyStatus); Navigator.push( context, MaterialPageRoute(builder: (context) { - return const TransactionInProgress(); + return TransactionInProgress( + transType: 'identityMigration', + fromAddress: sub.g1V1NewAddress, + toAddress: selectedWallet.address); }), ); resetScreen(context); diff --git a/lib/screens/myWallets/manage_membership.dart b/lib/screens/myWallets/manage_membership.dart index 5f4759f..4a05ec0 100644 --- a/lib/screens/myWallets/manage_membership.dart +++ b/lib/screens/myWallets/manage_membership.dart @@ -1,6 +1,8 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; +import 'package:gecko/screens/myWallets/migrate_identity.dart'; // import 'package:gecko/models/wallet_data.dart'; // import 'package:gecko/providers/my_wallets.dart'; // import 'package:gecko/providers/substrate_sdk.dart'; @@ -22,19 +24,44 @@ class ManageMembership extends StatelessWidget { backgroundColor: backgroundColor, appBar: AppBar( toolbarHeight: 60 * ratio, - title: const SizedBox( + title: SizedBox( height: 22, - child: Text('manageMembership'), + child: const Text('manageMembership').tr(), )), body: SafeArea( child: Column(children: [ const SizedBox(height: 20), - revokeMyIdentity(context), + migrateIdentity(context), + const SizedBox(height: 10), + revokeMyIdentity(context) // const SizedBox(height: 20), ]), )); } + Widget migrateIdentity(BuildContext context) { + return InkWell( + key: const Key('migrateIdentity'), + onTap: () async { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const MigrateIdentityScreen(); + }), + ); + }, + child: SizedBox( + height: 60, + child: Row(children: const [ + SizedBox(width: 16), + Icon(Icons.change_circle_outlined, size: 35), + SizedBox(width: 11.5), + Text('Migrer mon identité', style: TextStyle(fontSize: 20)), + ]), + ), + ); + } + Widget revokeMyIdentity(BuildContext context) { return InkWell( key: const Key('revokeIdty'), @@ -79,14 +106,15 @@ class ManageMembership extends StatelessWidget { // } }, child: SizedBox( - height: 40, - child: Row(children: const [ - SizedBox(width: 32), - // Image.asset( - // 'assets/medal.png', - // height: 45, - // ), - Text('Révoquer mon adhésion', style: TextStyle(fontSize: 20)), + height: 60, + child: Row(children: [ + const SizedBox(width: 20), + Image.asset( + 'assets/skull_Icon.png', + height: 30, + ), + const SizedBox(width: 16), + const Text('Révoquer mon adhésion', style: TextStyle(fontSize: 20)), ]), ), ); diff --git a/lib/screens/myWallets/migrate_identity.dart b/lib/screens/myWallets/migrate_identity.dart new file mode 100644 index 0000000..2bb0624 --- /dev/null +++ b/lib/screens/myWallets/migrate_identity.dart @@ -0,0 +1,251 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:gecko/globals.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/models/wallet_data.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; +import 'package:gecko/providers/my_wallets.dart'; +import 'package:gecko/providers/substrate_sdk.dart'; +import 'package:gecko/providers/wallet_options.dart'; +import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; +import 'package:gecko/screens/transaction_in_progress.dart'; +import 'package:provider/provider.dart'; + +class MigrateIdentityScreen extends StatelessWidget { + const MigrateIdentityScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + // HomeProvider _homeProvider = Provider.of(context); + WalletOptionsProvider walletOptions = + Provider.of(context, listen: false); + MyWalletsProvider myWalletProvider = + Provider.of(context, listen: false); + DuniterIndexer duniterIndexer = + Provider.of(context, listen: false); + + final fromAddress = walletOptions.address.text; + final defaultWallet = myWalletProvider.getDefaultWallet(); + final walletsList = myWalletProvider.listWallets.toList(); + late WalletData selectedWallet; + + if (fromAddress == defaultWallet.address) { + selectedWallet = + walletsList[fromAddress == walletsList[0].address ? 1 : 0]; + } else { + selectedWallet = defaultWallet; + } + bool canValidate = false; + String validationStatus = ''; + + final mdStyle = MarkdownStyleSheet( + p: const TextStyle(fontSize: 18, color: Colors.black, letterSpacing: 0.3), + textAlign: WrapAlignment.center, + ); + + if (walletsList.length < 2) { + return Column( + children: [ + const SizedBox(height: 80), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + 'Vous devez avoir au moins 2 portefeuilles\npour effecter cette opération', + style: TextStyle(fontSize: 20), + ) + ], + ) + ], + ); + } + + return Scaffold( + backgroundColor: backgroundColor, + appBar: AppBar( + toolbarHeight: 60 * ratio, + title: SizedBox( + height: 22, + child: Text('importOldAccount'.tr()), + )), + body: SafeArea( + child: Consumer(builder: (context, sub, _) { + return FutureBuilder( + future: sub.getBalanceAndIdtyStatus( + fromAddress, selectedWallet.address!), + builder: (BuildContext context, AsyncSnapshot status) { + if (status.data == null) { + return Column(children: [ + const SizedBox(height: 80), + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + SizedBox( + height: 35, + width: 35, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: 4, + ), + ), + ]), + ]); + } + + // log.d('statusData: ${status.data}'); + + final Map balance = status.data?[0] ?? {}; + final String idtyStatus = status.data?[1]; + final String myIdtyStatus = status.data?[2]; + final bool hasConsumer = status.data?[3] ?? false; + + // log.d('hasconsumer: $hasConsumer'); + + if (balance['transferableBalance'] != 0 && !hasConsumer) { + canValidate = true; + validationStatus = ''; + } else { + canValidate = false; + validationStatus = hasConsumer + ? 'youMustWaitBeforeCashoutThisAccount'.tr(args: ['X']) + : 'thisAccountIsEmpty'.tr(); + } + + if (idtyStatus != 'noid' && myIdtyStatus != 'noid') { + canValidate = false; + validationStatus = + 'youCannotMigrateIdentityToExistingIdentity'.tr(); + } + + log.d( + 'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address!}, $balance, $idtyStatus, $myIdtyStatus'); + + final walletsList = myWalletProvider.listWallets.toList(); + + walletsList + .removeWhere((element) => element.address == fromAddress); + // walletsList.add(WalletData(address: 'custom', name: 'custom')); + + return Column(children: [ + Row(children: const []), + const SizedBox(height: 20), + + SizedBox( + width: 350, + child: MarkdownBody( + data: 'areYouSureMigrateIdentity'.tr(args: [ + duniterIndexer.walletNameIndexer[fromAddress] ?? + '???', + '${balance['transferableBalance']} $currencyName' + ]), + styleSheet: mdStyle), + ), + // Text( + // 'areYouSureMigrateIdentity'.tr(args: [ + // duniterIndexer + // .walletNameIndexer[fromAddress]!, + // '$balance $currencyName' + // ]), + // textAlign: TextAlign.center, + // ), + const SizedBox(height: 20), + Text( + sub.g1V1NewAddress, + style: const TextStyle( + fontSize: 14.0, + color: Colors.black, + fontWeight: FontWeight.bold, + fontFamily: 'Monospace'), + ), + const SizedBox(height: 30), + Text('selectDestWallet'.tr()), + const SizedBox(height: 5), + DropdownButtonHideUnderline( + child: DropdownButton( + // alignment: AlignmentDirectional.topStart, + value: selectedWallet, + icon: const Icon(Icons.keyboard_arrow_down), + items: walletsList.map((wallet) { + return DropdownMenuItem( + value: wallet, + child: Text( + wallet.name!, + style: const TextStyle(fontSize: 18), + ), + ); + }).toList(), + onChanged: (WalletData? newSelectedWallet) { + selectedWallet = newSelectedWallet!; + sub.reload(); + }, + ), + ), + const SizedBox(height: 30), + SizedBox( + width: 380 * ratio, + height: 60 * ratio, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 4, + primary: orangeC, // background + onPrimary: Colors.white, // foreground + ), + onPressed: canValidate + ? () async { + log.d('GOOO'); + WalletData? defaultWallet = + myWalletProvider.getDefaultWallet(); + + String? pin; + if (myWalletProvider.pinCode == '') { + pin = await Navigator.push( + context, + MaterialPageRoute( + builder: (homeContext) { + return UnlockingWallet( + wallet: defaultWallet); + }, + ), + ); + } + + sub.migrateIdentity( + fromAddress: fromAddress, + destAddress: selectedWallet.address!, + fromPassword: pin ?? myWalletProvider.pinCode, + destPassword: pin ?? myWalletProvider.pinCode, + withBalance: true, + fromBalance: balance); + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return TransactionInProgress( + transType: 'identityMigration', + fromAddress: fromAddress, + toAddress: selectedWallet.address); + }), + ); + } + : null, + child: Text( + 'migrateIdentity'.tr(), + style: TextStyle( + fontSize: 23 * ratio, fontWeight: FontWeight.w600), + ), + ), + ), + const SizedBox(height: 10), + Text( + validationStatus, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 15, color: Colors.grey[600]), + ) + ]); + }); + }), + ), + ); + } +} diff --git a/lib/screens/transaction_in_progress.dart b/lib/screens/transaction_in_progress.dart index 6ab820b..dafd381 100644 --- a/lib/screens/transaction_in_progress.dart +++ b/lib/screens/transaction_in_progress.dart @@ -11,9 +11,12 @@ import 'package:provider/provider.dart'; // ignore: must_be_immutable class TransactionInProgress extends StatelessWidget { - const TransactionInProgress({Key? key, this.transType = 'pay'}) + const TransactionInProgress( + {Key? key, this.transType = 'pay', this.fromAddress, this.toAddress}) : super(key: key); final String transType; + final String? fromAddress; + final String? toAddress; @override Widget build(BuildContext context) { @@ -32,8 +35,8 @@ class TransactionInProgress extends StatelessWidget { log.d(walletViewProvider.address!); - final from = myWalletProvider.getDefaultWallet().name!; - final to = getShortPubkey(walletViewProvider.address!); + final from = fromAddress ?? myWalletProvider.getDefaultWallet().name!; + final to = toAddress ?? getShortPubkey(walletViewProvider.address!); final amount = walletViewProvider.payAmount.text; String actionName = ''; @@ -58,6 +61,11 @@ class TransactionInProgress extends StatelessWidget { actionName = "revokeAdhesion".tr(); } break; + case 'identityMigration': + { + actionName = "identityMigration".tr(); + } + break; default: { actionName = 'strangeTransaction'.tr(); @@ -148,7 +156,9 @@ class TransactionInProgress extends StatelessWidget { onWillPop: () { sub.transactionStatus = ''; Navigator.pop(context); - if (transType == 'pay') Navigator.pop(context); + if (transType == 'pay' || transType == 'identityMigration') { + Navigator.pop(context); + } return Future.value(true); }, child: Scaffold( @@ -261,7 +271,10 @@ class TransactionInProgress extends StatelessWidget { onPressed: () { Navigator.pop(context); sub.transactionStatus = ''; - if (transType == 'pay') Navigator.pop(context); + if (transType == 'pay' || + transType == 'identityMigration') { + Navigator.pop(context); + } }, child: Text( 'close'.tr(), From 92992c2f69a77d51e45e72ec8930e7492c7182cf Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 20 Aug 2022 20:40:33 +0200 Subject: [PATCH 17/19] fix cesium account import --- assets/translations/fr.json | 2 +- lib/screens/myWallets/import_g1_v1.dart | 32 +++++++++++--- lib/screens/myWallets/migrate_identity.dart | 5 ++- lib/screens/myWallets/wallets_home.dart | 46 ++++++++++----------- pubspec.yaml | 2 +- 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 26b93ad..ba9d0f5 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -178,7 +178,7 @@ "removeContact": "Supprimer\nce contact", "derivationsScanProgress": "Scan de l'adresse {}/{}", "youAreOffline": "Vous êtes hors ligne...", - "importG1v1": "Importer son compte G1v1", + "importG1v1": "Importer un ancien compte G1v1", "selectDestWallet": "Sélectionnez un portefeuille cible:", "youMustWaitBeforeCashoutThisAccount": "Vous devez attendre {} minutes\navant de pouvoir migrer ce compte", "thisAccountIsEmpty": "Ce compte est vide", diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index 3833be9..0bb14fe 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -60,7 +60,25 @@ class ImportG1v1 extends StatelessWidget { builder: (BuildContext context, AsyncSnapshot status) { // log.d(_certs.data); - final Map balance = status.data?[0] ?? 0; + if (status.data == null) { + return Column(children: [ + const SizedBox(height: 80), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 35, + width: 35, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: 4, + ), + ), + ]), + ]); + } + + final Map balance = status.data?[0] ?? {}; final String idtyStatus = status.data?[1]; final String myIdtyStatus = status.data?[2]; final bool hasConsumer = status.data?[3] ?? false; @@ -154,16 +172,16 @@ class ImportG1v1 extends StatelessWidget { ), const SizedBox(height: 20), Text( - sub.g1V1NewAddress, + getShortPubkey(sub.g1V1NewAddress), style: const TextStyle( - fontSize: 14.0, + fontSize: 18, color: Colors.black, fontWeight: FontWeight.bold, fontFamily: 'Monospace'), ), const SizedBox(height: 20), Text( - '$balance $currencyName', + '${balance['transferableBalance']} $currencyName', style: const TextStyle(fontSize: 17), ), Row( @@ -240,8 +258,10 @@ class ImportG1v1 extends StatelessWidget { MaterialPageRoute(builder: (context) { return TransactionInProgress( transType: 'identityMigration', - fromAddress: sub.g1V1NewAddress, - toAddress: selectedWallet.address); + fromAddress: + getShortPubkey(sub.g1V1NewAddress), + toAddress: getShortPubkey( + selectedWallet.address!)); }), ); resetScreen(context); diff --git a/lib/screens/myWallets/migrate_identity.dart b/lib/screens/myWallets/migrate_identity.dart index 2bb0624..b8fa00d 100644 --- a/lib/screens/myWallets/migrate_identity.dart +++ b/lib/screens/myWallets/migrate_identity.dart @@ -223,8 +223,9 @@ class MigrateIdentityScreen extends StatelessWidget { MaterialPageRoute(builder: (context) { return TransactionInProgress( transType: 'identityMigration', - fromAddress: fromAddress, - toAddress: selectedWallet.address); + fromAddress: getShortPubkey(fromAddress), + toAddress: getShortPubkey( + selectedWallet.address!)); }), ); } diff --git a/lib/screens/myWallets/wallets_home.dart b/lib/screens/myWallets/wallets_home.dart index b288f65..19a324c 100644 --- a/lib/screens/myWallets/wallets_home.dart +++ b/lib/screens/myWallets/wallets_home.dart @@ -78,28 +78,6 @@ class WalletsHome extends StatelessWidget { BuildContext context, MyWalletsProvider myWalletProvider) { return Column(children: [ const SizedBox(height: 50), - InkWell( - key: const Key('importG1v1'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return const ImportG1v1(); - }), - ); - }, - child: SizedBox( - width: 400, - height: 50, - child: Center( - child: Text('importG1v1'.tr(), - style: TextStyle( - fontSize: 22, - color: orangeC, - fontWeight: FontWeight.w500))), - ), - ), - const SizedBox(height: 30), SizedBox( height: 80, width: 420, @@ -129,6 +107,28 @@ class WalletsHome extends StatelessWidget { ), )), const SizedBox(height: 30), + InkWell( + key: const Key('importG1v1'), + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const ImportG1v1(); + }), + ); + }, + child: SizedBox( + width: 400, + height: 60, + child: Center( + child: Text('importG1v1'.tr(), + style: TextStyle( + fontSize: 22, + color: Colors.blue[900], + fontWeight: FontWeight.w500))), + ), + ), + const SizedBox(height: 5), InkWell( key: const Key('changeChest'), onTap: () { @@ -141,7 +141,7 @@ class WalletsHome extends StatelessWidget { }, child: SizedBox( width: 400, - height: 50, + height: 60, child: Center( child: Text('changeChest'.tr(), style: TextStyle( diff --git a/pubspec.yaml b/pubspec.yaml index 58d1deb..0be3548 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9+23 +version: 0.0.9+24 environment: sdk: '>=2.12.0 <3.0.0' From 3100dc512608aa2881c985867384f06b62fe9b62 Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 20 Aug 2022 22:46:21 +0200 Subject: [PATCH 18/19] fix: bad rendering canCert if identity is created --- lib/providers/substrate_sdk.dart | 9 +++++---- lib/providers/wallets_profiles.dart | 3 +-- lib/screens/wallet_view.dart | 4 ++-- pubspec.yaml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 377dc21..13a85cf 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -231,6 +231,8 @@ class SubstrateSdk with ChangeNotifier { Future> certState(String from, String to) async { Map result = {}; + final toStatus = await idtyStatus(to); + if (from != to && await isMemberGet(from)) { final removableOn = await getCertValidityPeriod(from, to); final certMeta = await getCertMeta(from); @@ -244,15 +246,14 @@ class SubstrateSdk with ChangeNotifier { } else if (nextIssuableOn > blocNumber) { final certDelayDuration = (nextIssuableOn - blocNumber) * 6; result.putIfAbsent('certDelay', () => certDelayDuration); + } else if (toStatus == 'Created') { + result.putIfAbsent('toStatus', () => 1); } else { result.putIfAbsent('canCert', () => 0); } } - final toStatus = await idtyStatus(to); - // log.d('certMeta: $toStatus'); - - if (toStatus == 'Created') result.putIfAbsent('toStatus', () => 1); + // if (toStatus == 'Created') result.putIfAbsent('toStatus', () => 1); return result; } diff --git a/lib/providers/wallets_profiles.dart b/lib/providers/wallets_profiles.dart index f1fcc50..ce181c5 100644 --- a/lib/providers/wallets_profiles.dart +++ b/lib/providers/wallets_profiles.dart @@ -138,10 +138,9 @@ class WalletsProfilesProvider with ChangeNotifier { Provider.of(context, listen: false); // SubstrateSdk _sub = Provider.of(context, listen: false); - bool isAccountExist = balanceCache[address] != 0; - return Stack(children: [ Consumer(builder: (context, sub, _) { + bool isAccountExist = balanceCache[address] != 0; return Container( height: 180, decoration: BoxDecoration( diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 994cdec..bbe47d7 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -270,8 +270,8 @@ class WalletViewScreen extends StatelessWidget { fontSize: buttonFontSize, fontWeight: FontWeight.w500), ), - ]), - if (toStatus == 1) + ]) + else if (toStatus == 1) waitToCert('mustConfirmHisIdentity', duration) else if (snapshot.data!['certRenewable'] != null && duration != 'seconds'.tr(args: ['0'])) diff --git a/pubspec.yaml b/pubspec.yaml index 0be3548..2becac7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9+24 +version: 0.0.10+26 environment: sdk: '>=2.12.0 <3.0.0' From ae5fe3b128a5ba970f35457487c94c4425b070d4 Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 20 Aug 2022 23:18:59 +0200 Subject: [PATCH 19/19] fix: flutter format --- lib/providers/generate_wallets.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/providers/generate_wallets.dart b/lib/providers/generate_wallets.dart index caeb235..24aef78 100644 --- a/lib/providers/generate_wallets.dart +++ b/lib/providers/generate_wallets.dart @@ -435,8 +435,10 @@ class GenerateWalletsProvider with ChangeNotifier { } Future scanRootBalance(SubstrateSdk sub, int currentChestNumber) async { - final addressData = await sub.sdk.api.keyring.addressFromMnemonic(sub.currencyParameters['ss58']!, - cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!); + final addressData = await sub.sdk.api.keyring.addressFromMnemonic( + sub.currencyParameters['ss58']!, + cryptoType: CryptoType.sr25519, + mnemonic: generatedMnemonic!); final balance = await sub.getBalance(addressData.address!).timeout( const Duration(seconds: 1),