Skip to content
Snippets Groups Projects
Commit ad601be1 authored by poka's avatar poka
Browse files

can migrate identity from standart mnemonic derivation

parent c840753f
No related branches found
No related tags found
1 merge request!27Import cs accounts
Pipeline #16847 failed
assets/skull_Icon.png

2.23 KiB

......@@ -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
......@@ -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
......@@ -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
......@@ -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<String> _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<int> getIdentityIndexOf(String address) async {
Future<int> _getIdentityIndexOf(String address) async {
return await _getStorage('identity.identityIndexOf("$address")') ?? 0;
}
Future<List<int>> 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<int> 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<Map> 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<String> 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<List> 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');
Future<List> 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);
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<String> 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<String> 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;
......@@ -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,
);
}),
);
}
......
......@@ -60,14 +60,14 @@ class ImportG1v1 extends StatelessWidget {
builder: (BuildContext context, AsyncSnapshot<List> 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: <Widget>[
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);
......
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: <Widget>[
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 <Widget>[
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 <Widget>[
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: <Widget>[
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)),
]),
),
);
......
// 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<HomeProvider>(context);
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(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<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.getBalanceAndIdtyStatus(
fromAddress, selectedWallet.address!),
builder: (BuildContext context, AsyncSnapshot<List> 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: <Widget>[
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]),
)
]);
});
}),
),
);
}
}
......@@ -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<bool>.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(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment