Newer
Older
// ignore_for_file: avoid_print
import 'package:crypto/crypto.dart';
import 'package:fast_base58/fast_base58.dart';
import 'package:flutter/material.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';
class SubstrateSdk with ChangeNotifier {
final bool isSsl = false;
final WalletSDK sdk = WalletSDK();
final Keyring keyring = Keyring();
bool sdkReady = false;
bool nodeConnected = false;
int blocNumber = 0;
TextEditingController jsonKeystore = TextEditingController();
TextEditingController keystorePassword = TextEditingController();
Future<void> initApi() async {
await sdk.init(keyring);
sdkReady = true;
notifyListeners();
}
Future<void> connectNode() async {
final String socketKind = isSsl ? 'wss' : 'ws';
List<NetworkParams> node = [];
for (final sn in subNode) {
final n = NetworkParams();
n.name = 'duniter';
n.endpoint = '$socketKind://$sn';
n.ss58 = ss58;
node.add(n);
}
final res = await sdk.api.connectNode(keyring, node).timeout(
const Duration(seconds: 10),
onTimeout: () => null,
);
if (res != null) {
nodeConnected = true;
notifyListeners();
}
// Subscribe bloc number
sdk.api.setting.subscribeBestNumber((res) {
blocNumber = int.parse(res.toString());
notifyListeners();
});
}
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())));
await Future.delayed(const Duration(milliseconds: 20));
final bakedAddress = keyring.allAccounts.last.address;
return bakedAddress!;
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!);
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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;
}
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);
return await sdk.api.keyring.checkPassword(account, pass);
}
int getDerivationNumber(String address) {
final account = getKeypair(address);
final deriveNbr = account.name!.split('/')[1];
return int.parse(deriveNbr);
}
Future<KeyPairData?> changePassword(
String address, String passOld, String? passNew) async {
final account = getKeypair(address);
keyring.setCurrent(account);
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<String> generateMnemonic({String lang = appLang}) async {
final gen = await sdk.api.keyring.generateMnemonic(ss58);
// final res = await importAccount(fromMnemonic: true);
await Clipboard.setData(ClipboardData(text: generatedMnemonic));
return gen.mnemonic!;
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// Future<bool> 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);
keyring.setCurrent(acc);
return acc.address!;
} catch (e) {
return (e.toString());
}
}
KeyPairData getCurrentWallet() {
try {
final acc = keyring.current;
return acc;
} catch (e) {
return KeyPairData();
}
}
Future<String> pay(BuildContext context,
{required String fromAddress,
required String destAddress,
required double amount,
required String password}) async {
setCurrentWallet(fromAddress);
final sender = TxSenderData(
keyring.current.address,
keyring.current.pubKey,
);
final txInfo = TxInfoData('balances', 'transfer', sender);
try {
final hash = await sdk.api.tx.signAndSend(
txInfo,
password,
onStatusChange: (status) {
print('status: ' + status);
if (status == 'Ready') {
return 'confirmed';
} catch (e) {
return e.toString();
BuildContext context, String address, int number, String password) async {
final keypair = getKeypair(address);
final seedMap =
await keyring.store.getDecryptedSeed(keypair.pubKey, password);
print(seedMap);
if (seedMap?['type'] != 'mnemonic') return '';
final List seedList = seedMap!['seed'].split('/');
generatedMnemonic = seedList[0];
int sourceDerivation = -1; // To get derivation number of this account
if (seedList.length > 1) {
sourceDerivation = int.parse(seedMap['seed'].split('/')[1]);
}
print(generatedMnemonic);
print(sourceDerivation);
return await importAccount(fromMnemonic: true, derivePath: '//$number');
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
}
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});
}
String getShortPubkey(String pubkey) {
List<int> pubkeyByte = Base58Decode(pubkey);
Digest pubkeyS256 = sha256.convert(sha256.convert(pubkeyByte).bytes);
String pubkeyCheksum = Base58Encode(pubkeyS256.bytes);
String pubkeyChecksumShort =
truncate(pubkeyCheksum, 3, omission: "", position: TruncatePosition.end);
String pubkeyShort = truncate(pubkey, 5,
omission: String.fromCharCode(0x2026),
position: TruncatePosition.end) +
truncate(pubkey, 4, omission: "", position: TruncatePosition.start) +
':$pubkeyChecksumShort';
return pubkeyShort;