Newer
Older
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:polkawallet_sdk/api/types/networkParams.dart';
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:provider/provider.dart';
// import 'package:web_socket_channel/io.dart';
class SubstrateSdk with ChangeNotifier {
final WalletSDK sdk = WalletSDK();
final Keyring keyring = Keyring();
bool sdkReady = false;
bool nodeConnected = false;
int blocNumber = 0;
bool isLoadingEndpoint = false;
TextEditingController jsonKeystore = TextEditingController();
TextEditingController keystorePassword = TextEditingController();
Future<void> initApi() async {
await sdk.init(keyring);
sdkReady = true;
notifyListeners();
}
Future<void> connectNode(BuildContext ctx) async {
HomeProvider _homeProvider = Provider.of<HomeProvider>(ctx, listen: false);
_homeProvider.changeMessage("Connexion en cours...", 0);
for (String _endpoint in configBox.get('endpoint')) {
final n = NetworkParams();
n.name = currencyName;
n.endpoint = _endpoint;
n.ss58 = ss58;
node.add(n);
}
// if (n.endpoint!.startsWith('ws://')) {
// timeout = 5000;
// }
//// Check websocket conenction - only for wss
// final channel = IOWebSocketChannel.connect(
// Uri.parse('wss://192.168.1.72:9944'),
// );
// channel.stream.listen(
// (dynamic message) {
// log.d('message $message');
// },
// onDone: () {
// log.d('ws channel closed');
// },
// onError: (error) {
// log.d('ws error $error');
// },
// );
if (sdk.api.connectedNode?.endpoint != null) {
await sdk.api.setting.unsubscribeBestNumber();
isLoadingEndpoint = true;
notifyListeners();
final res = await sdk.api.connectNode(keyring, node).timeout(
isLoadingEndpoint = false;
notifyListeners();
if (res != null) {
nodeConnected = true;
// Subscribe bloc number
sdk.api.setting.subscribeBestNumber((res) {
blocNumber = int.parse(res.toString());
if (sdk.api.connectedNode?.endpoint == null) {
_homeProvider.changeMessage("Le réseau a été perdu...", 0);
}
notifyListeners();
_homeProvider.changeMessage(
'Vous êtes bien connecté aux noeud\n${getConnectedEndpoint()!.split('/')[2]}',
5);
} else {
nodeConnected = false;
_homeProvider.changeMessage("Aucun server disponible...", 0);
}
log.d(sdk.api.connectedNode?.endpoint);
Future<String> importAccount(
{String mnemonic = '',
bool fromMnemonic = false,
String derivePath = '',
String password = ''}) async {
// toy exercise immense month enter answer table prefer speed cycle gold phone
final clipboardData = await Clipboard.getData(Clipboard.kTextPlain);
if (mnemonic != '') {
fromMnemonic = true;
generatedMnemonic = mnemonic;
} else if (clipboardData!.text!.split(' ').length == 12) {
fromMnemonic = true;
generatedMnemonic = clipboardData.text!;
}
if (password == '') {
password = keystorePassword.text;
}
final KeyType keytype;
final String keyToImport;
if (fromMnemonic) {
keytype = KeyType.mnemonic;
keyToImport = generatedMnemonic;
} else {
keytype = KeyType.keystore;
keyToImport = jsonKeystore.text.replaceAll("'", "\\'");
}
if (clipboardData?.text != null) jsonKeystore.text = clipboardData!.text!;
var json = await sdk.api.keyring
.importAccount(keyring,
keyType: keytype,
key: keyToImport,
name: derivePath,
password: password,
derivePath: derivePath,
cryptoType: CryptoType.sr25519)
.catchError((e) {
importIsLoading = false;
notifyListeners();
});
// Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
return keyring.allAccounts.last.address!;
Future<List<AddressInfo>> getKeyStoreAddress() async {
List<AddressInfo> result = [];
// sdk.api.account.unsubscribeBalance();
for (var element in keyring.allAccounts) {
// Clipboard.setData(ClipboardData(text: jsonEncode(element)));
final account = AddressInfo(address: element.address);
// await sdk.api.account.subscribeBalance(element.address, (p0) {
// account.balance = int.parse(p0.freeBalance) / 100;
// });
// sdk.api.setting.unsubscribeBestNumber();
account.balance = await getBalance(element.address!);
Future<List<int>> getCerts(String address) async {
final idtyIndex = await sdk.webView!
.evalJavascript('api.query.identity.identityIndexOf("$address")');
log.d('u32: ' + idtyIndex.toString());
final _certsReceiver = await sdk.webView!
.evalJavascript('api.query.cert.storageIdtyCertMeta($idtyIndex)') ??
[];
return [_certsReceiver['receivedCount'], _certsReceiver['issuedCount']];
}
Future<Map> getCertData(String from, String to) async {
final idtyIndexFrom = await sdk.webView!
.evalJavascript('api.query.identity.identityIndexOf("$from")');
final idtyIndexTo = await sdk.webView!
.evalJavascript('api.query.identity.identityIndexOf("$to")');
final _certData = await sdk.webView!.evalJavascript(
'api.query.cert.storageCertsByIssuer($idtyIndexFrom, $idtyIndexTo)') ??
'';
log.d(_certData);
if (_certData == '') return {};
return _certData;
}
// Future<bool> isAccountExit(String address) async {
// final _accountInfo = await sdk.webView!
// .evalJavascript('api.query.system.account("$address")');
// final _randomId = _accountInfo['data']['randomId'];
// return _randomId == null ? false : true;
// }
Future<double> getBalance(String address, {bool isUd = false}) async {
double balance = 0.0;
if (nodeConnected) {
final brutBalance = await sdk.api.account.queryBalance(address);
balance = int.parse(brutBalance!.freeBalance) / 100;
}
return balance;
}
Future<double> subscribeBalance(String address, {bool isUd = false}) async {
double balance = 0.0;
if (nodeConnected) {
await sdk.api.account.subscribeBalance(address, (_balance) {
balance = int.parse(_balance.freeBalance) / 100;
notifyListeners();
});
}
return balance;
}
KeyPairData getKeypair(String address) {
return keyring.keyPairs.firstWhere((kp) => kp.address == address,
orElse: (() => KeyPairData()));
}
Future<bool> checkPassword(String address, String pass) async {
final account = getKeypair(address);

poka
committed
// log.d(account.address);
return await sdk.api.keyring.checkPassword(account, pass);
}
Future<String> getSeed(String address, String _pin) async {
final account = getKeypair(address);
keyring.setCurrent(account);
final _seed = await sdk.api.keyring.getDecryptedSeed(keyring, _pin);
String _seedText;
if (_seed == null) {
_seedText = '';
} else {
_seedText = _seed.seed!.split('//')[0];
}
log.d(_seedText);
return _seedText;
}
int getDerivationNumber(String address) {
final account = getKeypair(address);
final deriveNbr = account.name!.split('//')[1];
return int.parse(deriveNbr);
}
Future<KeyPairData?> changePassword(BuildContext context, String address,
String passOld, String? passNew) async {
final account = getKeypair(address);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
_myWalletProvider.resetPinCode();
return await sdk.api.keyring.changePassword(keyring, passOld, passNew);
}
Future<void> deleteAllAccounts() async {
for (var account in keyring.allAccounts) {
await sdk.api.keyring.deleteAccount(keyring, account);
}
}
Future<void> deleteAccounts(List<String> address) async {
for (var a in address) {
final account = getKeypair(a);
await sdk.api.keyring.deleteAccount(keyring, account);
}
}
Future<String> generateMnemonic({String lang = appLang}) async {
final gen = await sdk.api.keyring.generateMnemonic(ss58);
// await Clipboard.setData(ClipboardData(text: generatedMnemonic));
Future<String> setCurrentWallet(WalletData _wallet) async {
final currentChestNumber = configBox.get('currentChest');
ChestData _newChestData = chestBox.get(currentChestNumber)!;
_newChestData.defaultWallet = _wallet.number;
await chestBox.put(currentChestNumber, _newChestData);
keyring.setCurrent(acc);
return acc.address!;
} catch (e) {
return (e.toString());
}
}
KeyPairData getCurrentWallet() {
try {
final acc = keyring.current;
return acc;
} catch (e) {
return KeyPairData();
}
}
{required String fromAddress,
required String destAddress,
required double amount,
required String password}) async {
log.d(keyring.current.address);
log.d(fromAddress);
log.d(password);
log.d(await checkPassword(fromAddress, password));
final sender = TxSenderData(
keyring.current.address,
keyring.current.pubKey,
);
final txInfo = TxInfoData('balances', 'transfer', sender);
try {
final hash = await sdk.api.tx.signAndSend(
txInfo,
).timeout(
const Duration(seconds: 12),
onTimeout: () => {},
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<String> certify(
String fromAddress, String password, String toAddress) async {
transactionStatus = '';
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
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();
return 'timeout';
} else {
transactionStatus = hash.toString();
notifyListeners();
return hash.toString();
}
transactionStatus = e.toString();
notifyListeners();
Future<String> idtyStatus(String address) async {
// var tata = await sdk.webView!
// .evalJavascript('api.query.system.account("$address")');
var idtyIndex = await sdk.webView!
.evalJavascript('api.query.identity.identityIndexOf("$address")');
if (idtyIndex == null) {
return 'noid';
}
final idtyStatus = await sdk.webView!
.evalJavascript('api.query.identity.identities($idtyIndex)');
if (idtyStatus != null) {
final String _status = idtyStatus['status'];
log.d(_status);
return (_status);
} else {
return 'expired';
}
}
Future<String> confirmIdentity(
String fromAddress, String name, String password) async {
log.d('me: ' + keyring.current.address!);
final sender = TxSenderData(
keyring.current.address,
keyring.current.pubKey,
);
final txInfo = TxInfoData(
'identity',
'confirmIdentity',
sender,
);
try {
return 'confirmed';
} on Exception catch (e) {
log.e(e);
return e.toString();
}
}
Future<bool> isMember(String address) async {
return await idtyStatus(address) == 'Validated';
}
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
Future<bool> canCertify(String from, String to) async {
bool _result = false;
if (from != to && await isMember(from)) {
final _certData = await getCertData(from, to);
final _certMeta = await getCertMeta(from);
final int _removableOn = _certData['removableOn'] ?? 0;
final int _nextIssuableOn = _certMeta['nextIssuableOn'] ?? 0;
log.d(_removableOn);
if (_removableOn == 0 && _nextIssuableOn == 0) {
_result = true;
}
}
return _result;
}
Future<Map> getCertMeta(String address) async {
var idtyIndex = await sdk.webView!
.evalJavascript('api.query.identity.identityIndexOf("$address")');
final _certMeta = await sdk.webView!
.evalJavascript('api.query.cert.storageIdtyCertMeta($idtyIndex)') ??
'';
// if (_certMeta['nextIssuableOn'] != 0) return {};
log.d(_certMeta);
return _certMeta;
}
BuildContext context, String address, int number, String password) async {
final keypair = getKeypair(address);
final seedMap =
await keyring.store.getDecryptedSeed(keypair.pubKey, password);
if (seedMap?['type'] != 'mnemonic') return '';
final List seedList = seedMap!['seed'].split('//');

poka
committed
mnemonic: generatedMnemonic,
fromMnemonic: true,
derivePath: '//$number',
password: password);
}
Future<String> generateRootKeypair(String address, String password) async {
final keypair = getKeypair(address);
final seedMap =
await keyring.store.getDecryptedSeed(keypair.pubKey, password);
if (seedMap?['type'] != 'mnemonic') return '';
final List seedList = seedMap!['seed'].split('//');
generatedMnemonic = seedList[0];
return await importAccount(fromMnemonic: true, password: password);
Future<bool> isMnemonicValid(String mnemonic) async {
// Needed for bad encoding of UTF-8
mnemonic = mnemonic.replaceAll('é', 'é');
mnemonic = mnemonic.replaceAll('è', 'è');
return await sdk.api.keyring.checkMnemonicValid(mnemonic);
}
String? getConnectedEndpoint() {
return sdk.api.connectedNode?.endpoint;
}
}
void snack(BuildContext context, String message, {int duration = 2}) {
final snackBar =
SnackBar(content: Text(message), duration: Duration(seconds: duration));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
class AddressInfo {
final String? address;
double balance;
AddressInfo({@required this.address, this.balance = 0});
}
void snackNode(BuildContext context, bool isConnected) {
String _message;
if (!isConnected) {
_message =
"Aucun noeud Duniter disponible, veuillez réessayer ultérieurement:\n${configBox.get('endpoint').first}";
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
"Vous êtes connecté au noeud\n${_sub.getConnectedEndpoint()!.split('//')[1]}";
final snackBar = SnackBar(
padding: const EdgeInsets.all(20),
content: Text(_message, style: const TextStyle(fontSize: 16)),
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
omission: String.fromCharCode(0x2026),
position: TruncatePosition.end) +
truncate(pubkey, 6, omission: "", position: TruncatePosition.start);