diff --git a/assets/gecko_certify.png b/assets/gecko_certify.png new file mode 100644 index 0000000..6fa5f33 Binary files /dev/null and b/assets/gecko_certify.png differ diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 1306584..8567c71 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -254,33 +254,6 @@ class SubstrateSdk with ChangeNotifier { return gen.mnemonic!; } - // Future pay(BuildContext context, String address, double amount, - // String password) async { - // final sender = TxSenderData( - // keyring.current.address, - // keyring.current.pubKey, - // ); - // final txInfo = TxInfoData('balances', 'transfer', sender); - // try { - // final hash = await sdk.api.tx.signAndSend( - // txInfo, - // [address, amount * 100], - // password, - // onStatusChange: (status) { - // print('status: ' + status); - // if (status == 'Ready') { - // snack(context, 'Transaction terminé'); - // } - // }, - // ); - // print(hash.toString()); - // return true; - // } catch (err) { - // print(err.toString()); - // return false; - // } - // } - String setCurrentWallet(String address) { try { final acc = getKeypair(address); @@ -300,7 +273,7 @@ class SubstrateSdk with ChangeNotifier { } } - Future pay(BuildContext context, + Future pay( {required String fromAddress, required String destAddress, required double amount, @@ -329,14 +302,89 @@ class SubstrateSdk with ChangeNotifier { if (status == 'Ready') { transactionStatus = 'sent'; notifyListeners(); - // snack(context, 'Transaction terminé'); } }, ).timeout( const Duration(seconds: 12), onTimeout: () => {}, ); - print(hash.toString()); + log.d(hash.toString()); + if (hash.isEmpty) { + transactionStatus = 'timeout'; + notifyListeners(); + + return 'timeout'; + } else { + transactionStatus = hash.toString(); + notifyListeners(); + return hash.toString(); + } + } catch (e) { + transactionStatus = e.toString(); + notifyListeners(); + return e.toString(); + } + } + + Future certify( + String fromAddress, String password, String toAddress) async { + transactionStatus = ''; + + setCurrentWallet(fromAddress); + log.d('me: ' + fromAddress); + log.d('to: ' + toAddress); + + final _myIdtyStatus = await idtyStatus(fromAddress); + final _toIdtyStatus = await idtyStatus(toAddress); + + log.d(_myIdtyStatus); + log.d(_toIdtyStatus); + + if (_myIdtyStatus != 'Validated') { + transactionStatus = 'notMember'; + notifyListeners(); + return 'notMember'; + } + + final sender = TxSenderData( + keyring.current.address, + keyring.current.pubKey, + ); + TxInfoData txInfo; + + if (_toIdtyStatus == 'noid') { + txInfo = TxInfoData( + 'identity', + 'createIdentity', + sender, + ); + } else if (_toIdtyStatus == 'Validated' || + _toIdtyStatus == 'ConfirmedByOwner') { + txInfo = TxInfoData( + 'cert', + 'addCert', + sender, + ); + } else { + transactionStatus = 'cantBeCert'; + notifyListeners(); + return 'cantBeCert'; + } + + log.d('Cert action: ' + txInfo.call!); + + try { + final hash = await sdk.api.tx + .signAndSend( + txInfo, + [toAddress], + password, + ) + .timeout( + const Duration(seconds: 12), + onTimeout: () => {}, + ); + log.d(hash); if (hash.isEmpty) { transactionStatus = 'timeout'; notifyListeners(); @@ -378,10 +426,10 @@ class SubstrateSdk with ChangeNotifier { } Future confirmIdentity( - String address, String name, String password) async { + String fromAddress, String name, String password) async { // Confirm identity - setCurrentWallet(address); - log.d('idty: ' + keyring.current.address!); + setCurrentWallet(fromAddress); + log.d('me: ' + keyring.current.address!); final sender = TxSenderData( keyring.current.address, @@ -404,13 +452,14 @@ class SubstrateSdk with ChangeNotifier { return 'confirmed'; } on Exception catch (e) { log.e(e); - // if (e.toString() == 'Exception: password check failed') { - // throw PasswordException('Bad password'); - // } return e.toString(); } } + Future isMember(String address) async { + return await idtyStatus(address) == 'Validated'; + } + Future derive( BuildContext context, String address, int number, String password) async { final keypair = getKeypair(address); diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index ee6acef..178c9a9 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -247,6 +247,7 @@ class WalletOptionsProvider with ChangeNotifier { child: Column(children: [ const Text('Nom:'), TextField( + autofocus: true, controller: idtyName, ) ]), diff --git a/lib/providers/wallets_profiles.dart b/lib/providers/wallets_profiles.dart index f32cb35..27ac874 100644 --- a/lib/providers/wallets_profiles.dart +++ b/lib/providers/wallets_profiles.dart @@ -106,6 +106,7 @@ class WalletsProfilesProvider with ChangeNotifier { } String getShortPubkey(String pubkey) { + // log.d(pubkey); List pubkeyByte = Base58Decode(pubkey); Digest pubkeyS256 = sha256.convert(sha256.convert(pubkeyByte).bytes); String pubkeyCheksum = Base58Encode(pubkeyS256.bytes); diff --git a/lib/screens/myWallets/unlocking_wallet.dart b/lib/screens/myWallets/unlocking_wallet.dart index 3962dc3..210d268 100644 --- a/lib/screens/myWallets/unlocking_wallet.dart +++ b/lib/screens/myWallets/unlocking_wallet.dart @@ -232,29 +232,41 @@ class UnlockingWallet extends StatelessWidget { ); break; case "pay": - // Navigator.pop(context); - // Navigator.pop(context); // Payment workflow ! WalletsProfilesProvider _walletViewProvider = Provider.of(context, listen: false); final acc = _sub.getCurrentWallet(); log.d( - "fromAddress: ${acc.address!},destAddress: ${_walletViewProvider.outputPubkey.text}, amount: ${double.parse(_walletViewProvider.payAmount.text)}, password: $_pin"); - _sub.pay(context, + "fromAddress: ${acc.address!},destAddress: ${_walletViewProvider.pubkey!}, amount: ${double.parse(_walletViewProvider.payAmount.text)}, password: $_pin"); + _sub.pay( fromAddress: acc.address!, - destAddress: _walletViewProvider.outputPubkey.text, + destAddress: _walletViewProvider.pubkey!, amount: double.parse(_walletViewProvider.payAmount.text), password: _pin.toUpperCase()); - // await paymentsResult(context, resultPay); Navigator.push( context, MaterialPageRoute(builder: (context) { - return TransactionInProgress( - chest: currentChestNumber, pin: _pin.toUpperCase()); + return const TransactionInProgress(); }), ); + break; + case "cert": + WalletsProfilesProvider _walletViewProvider = + Provider.of(context, + listen: false); + final acc = _sub.getCurrentWallet(); + _sub.certify(acc.address!, _pin.toUpperCase(), + _walletViewProvider.pubkey!); + + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const TransactionInProgress(transType: 'cert'); + }), + ); + break; } } diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 6eddab7..3614935 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -4,6 +4,7 @@ import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/models/wallet_data.dart'; +import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallet_options.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/history.dart'; @@ -114,7 +115,7 @@ class WalletOptions extends StatelessWidget { SizedBox(height: 10 * ratio), historyWidget(context, _historyProvider, walletProvider), SizedBox(height: 12 * ratio), - setDefaultWallet(walletProvider, _myWalletProvider, + setDefaultWallet(context, walletProvider, _myWalletProvider, _walletOptions, _currentChest), SizedBox(height: 17 * ratio), if (!walletProvider.isDefaultWallet) @@ -332,11 +333,13 @@ class WalletOptions extends StatelessWidget { } Widget setDefaultWallet( + BuildContext context, WalletOptionsProvider walletProvider, MyWalletsProvider _myWalletProvider, WalletOptionsProvider _walletOptions, int _currentChest) { WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!; + SubstrateSdk _sub = Provider.of(context, listen: false); _walletOptions.isDefaultWallet = (defaultWallet.number == wallet.id()[1]); @@ -348,6 +351,7 @@ class WalletOptions extends StatelessWidget { ChestData _newChestData = chestBox.get(_currentChest)!; _newChestData.defaultWallet = wallet.number; await chestBox.put(_currentChest, _newChestData); + _sub.setCurrentWallet(wallet.address!); _myWalletProvider.readAllWallets(_currentChest); _myWalletProvider.rebuildWidget(); } diff --git a/lib/screens/transaction_in_progress.dart b/lib/screens/transaction_in_progress.dart index 1adb453..9a275a3 100644 --- a/lib/screens/transaction_in_progress.dart +++ b/lib/screens/transaction_in_progress.dart @@ -10,11 +10,9 @@ import 'package:provider/provider.dart'; // ignore: must_be_immutable class TransactionInProgress extends StatelessWidget { - const TransactionInProgress( - {Key? key, required this.chest, required this.pin}) + const TransactionInProgress({Key? key, this.transType = 'pay'}) : super(key: key); - final int chest; - final String pin; + final String transType; @override Widget build(BuildContext context) { @@ -30,10 +28,29 @@ class TransactionInProgress extends StatelessWidget { // Map jsonResult; final _result = _sub.transactionStatus; + log.d(_walletViewProvider.pubkey!); + final from = _myWalletProvider.getDefaultWallet()!.name!; - final to = _walletViewProvider - .getShortPubkey(_walletViewProvider.outputPubkey.text); + final to = _walletViewProvider.getShortPubkey(_walletViewProvider.pubkey!); final amount = _walletViewProvider.payAmount.text; + String _actionName = ''; + + switch (transType) { + case 'pay': + { + _actionName = 'Transaction'; + } + break; + case 'cert': + { + _actionName = 'Certification'; + } + break; + default: + { + _actionName = 'Transaction étrange'; + } + } switch (_result) { case '': @@ -52,7 +69,7 @@ class TransactionInProgress extends StatelessWidget { // jsonResult = json.decode(_result); log.d(_result); if (_result.contains('blockHash: ')) { - _resultText = 'Transcation validé !'; + _resultText = '$_actionName validé !'; } else { _resultText = "Une erreur s'est produite:\n\n$_result"; } @@ -64,7 +81,9 @@ class TransactionInProgress extends StatelessWidget { _sub.transactionStatus = ''; Navigator.pop(context); Navigator.pop(context); - Navigator.pop(context); + if (_actionName == 'pay') { + Navigator.pop(context); + } return Future.value(true); }, child: Scaffold( @@ -76,7 +95,7 @@ class TransactionInProgress extends StatelessWidget { height: 22, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: const [Text('Transaction en cours')]), + children: [Text('$_actionName en cours')]), )), body: SafeArea( child: Align( @@ -95,13 +114,14 @@ class TransactionInProgress extends StatelessWidget { )), child: Column(children: [ const SizedBox(height: 10), - Text( - '$amount $currencyName', - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 18, fontWeight: FontWeight.w600), - ), - const SizedBox(height: 10), + if (transType == 'pay') + Text( + '$amount $currencyName', + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.w600), + ), + if (transType == 'pay') const SizedBox(height: 10), const Text( 'de', textAlign: TextAlign.center, @@ -130,23 +150,24 @@ class TransactionInProgress extends StatelessWidget { ), // const SizedBox(height: 20, width: double.infinity), const Spacer(), - Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - _resultText, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 19 * ratio), - ), + Column(children: [ Visibility( visible: isLoading, child: SizedBox( - height: 15, - width: 15, + height: 18, + width: 18, child: CircularProgressIndicator( color: orangeC, strokeWidth: 2, ), ), ), + const SizedBox(height: 10), + Text( + _resultText, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 19 * ratio), + ), ]), const Spacer(), Expanded( @@ -164,7 +185,9 @@ class TransactionInProgress extends StatelessWidget { onPressed: () { Navigator.pop(context); Navigator.pop(context); - Navigator.pop(context); + if (_actionName == 'pay') { + Navigator.pop(context); + } }, child: Text( 'Fermer', diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index d66d62f..63b2d34 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -29,6 +29,12 @@ class WalletViewScreen extends StatelessWidget { CesiumPlusProvider _cesiumPlusProvider = Provider.of(context, listen: false); _walletViewProvider.pubkey = pubkey!; + SubstrateSdk _sub = Provider.of(context, listen: false); + + MyWalletsProvider _myWalletProvider = + Provider.of(context, listen: false); + WalletData? defaultWallet = _myWalletProvider.getDefaultWallet(); + _sub.setCurrentWallet(defaultWallet!.address!); return Scaffold( resizeToAvoidBottomInset: true, @@ -89,6 +95,56 @@ class WalletViewScreen extends StatelessWidget { fontSize: buttonFontSize, fontWeight: FontWeight.w500), ), ]), + Consumer(builder: (context, _sub, _) { + return FutureBuilder( + future: _sub.isMember(defaultWallet.address!), + builder: (context, AsyncSnapshot snapshot) { + return Visibility( + visible: (snapshot.data ?? false), + child: Column(children: [ + SizedBox( + height: buttonSize, + child: ClipOval( + child: Material( + color: const Color(0xffFFD58D), // button color + child: InkWell( + key: const Key('copyKey'), + splashColor: orangeC, // inkwell color + child: const Padding( + padding: EdgeInsets.only(bottom: 0), + child: Image( + image: AssetImage( + 'assets/gecko_certify.png')), + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return UnlockingWallet( + wallet: defaultWallet, + action: "cert"); + }, + ), + ); + // _sub.certify(fromAddress, password, toAddress); + }), + ), + ), + ), + const SizedBox(height: 9), + Text( + "Certifier", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: buttonFontSize, + fontWeight: FontWeight.w500), + ), + ]), + ); + }, + ); + }), Column(children: [ SizedBox( height: buttonSize, diff --git a/pubspec.yaml b/pubspec.yaml index a1c2e93..855c706 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.6+4 +version: 0.0.6+5 environment: sdk: '>=2.12.0 <3.0.0'