can migrate GD from Cesium wallets

This commit is contained in:
poka 2022-08-18 14:26:12 +02:00
parent dbfd033fba
commit 1b896960ea
6 changed files with 313 additions and 133 deletions

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -252,7 +252,7 @@ class SubstrateSdk with ChangeNotifier {
return certMeta;
}
Future<String> idtyStatus(String address, [bool smooth = true]) async {
Future<String> 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<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');
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() {

View File

@ -30,6 +30,7 @@ class WalletOptionsProvider with ChangeNotifier {
TextEditingController nameController = TextEditingController();
late bool isDefaultWallet;
bool canValidateNameBool = false;
Map<String, String> idtyStatusCache = {};
Future<NewWallet>? 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':
{

View File

@ -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<bool>.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<SubstrateSdk>(builder: (context, sub, _) {
return Column(children: <Widget>[
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<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.getBalanceAndIdtyStatus(
sub.g1V1NewAddress, selectedWallet.address!),
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;
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: <Widget>[
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<SubstrateSdk>(context, listen: false);
sub.csSalt.text = '';
sub.csPassword.text = '';
sub.g1V1NewAddress = '';
}
}