Import mnemonic; can pay;
This commit is contained in:
parent
d2c89b1f14
commit
fa31a2d4d8
|
@ -20,7 +20,7 @@ late Box<WalletData> walletBox;
|
|||
late Box<ChestData> chestBox;
|
||||
late Box configBox;
|
||||
late Box<G1WalletsList> g1WalletsBox;
|
||||
late Box keystoreBox;
|
||||
// late Box keystoreBox;
|
||||
|
||||
String cesiumPod = "https://g1.data.le-sou.org";
|
||||
// String cesiumPod = "https://g1.data.e-is.pro";
|
||||
|
|
|
@ -72,7 +72,7 @@ Future<void> main() async {
|
|||
chestBox = await Hive.openBox<ChestData>("chestBox");
|
||||
configBox = await Hive.openBox("configBox");
|
||||
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
|
||||
keystoreBox = await Hive.openBox("keystoreBox");
|
||||
// keystoreBox = await Hive.openBox("keystoreBox");
|
||||
|
||||
g1WalletsBox.clear();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'dart:async';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:path_provider/path_provider.dart' as pp;
|
||||
|
@ -146,7 +147,7 @@ class HomeProvider with ChangeNotifier {
|
|||
_message =
|
||||
"Aucun noeud Duniter disponible, veuillez réessayer ultérieurement";
|
||||
} else {
|
||||
_message = "Vous êtes connecté au noeud\n${endPointGVA.split('/')[2]}";
|
||||
_message = "Vous êtes connecté au noeud\n${SubstrateSdk().subNode}";
|
||||
}
|
||||
final snackBar = SnackBar(
|
||||
content: Text(_message), duration: const Duration(seconds: 2));
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:fast_base58/fast_base58.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:polkawallet_sdk/api/apiKeyring.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:truncate/truncate.dart';
|
||||
|
||||
class SubstrateSdk with ChangeNotifier {
|
||||
final String subNode = '192.168.1.85:9944';
|
||||
final List subNode = ['127.0.0.1:9944', '192.168.1.85:9944'];
|
||||
final bool isSsl = false;
|
||||
final int ss58 = 42;
|
||||
|
||||
final WalletSDK sdk = WalletSDK();
|
||||
final Keyring keyring = Keyring();
|
||||
|
@ -25,7 +30,8 @@ class SubstrateSdk with ChangeNotifier {
|
|||
|
||||
Future<void> initApi() async {
|
||||
sdkLoading = true;
|
||||
await keyring.init([0, 2]);
|
||||
await keyring.init([ss58]);
|
||||
keyring.setSS58(ss58);
|
||||
|
||||
await sdk.init(keyring);
|
||||
sdkReady = true;
|
||||
|
@ -35,14 +41,18 @@ class SubstrateSdk with ChangeNotifier {
|
|||
|
||||
Future<void> connectNode() async {
|
||||
final String socketKind = isSsl ? 'wss' : 'ws';
|
||||
final node = NetworkParams();
|
||||
node.name = 'pokaniter';
|
||||
node.endpoint = '$socketKind://$subNode';
|
||||
node.ss58 = 42;
|
||||
final res = await sdk.api.connectNode(keyring, [node]).timeout(
|
||||
const Duration(seconds: 10),
|
||||
onTimeout: () => null,
|
||||
);
|
||||
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();
|
||||
|
@ -55,7 +65,17 @@ class SubstrateSdk with ChangeNotifier {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> importFromKeystore() async {
|
||||
Future<bool> importAccount({bool fromMnemonic = false}) async {
|
||||
final KeyType keytype;
|
||||
final String keyToImport;
|
||||
if (fromMnemonic) {
|
||||
keytype = KeyType.mnemonic;
|
||||
keyToImport = generatedMnemonic;
|
||||
} else {
|
||||
keytype = KeyType.keystore;
|
||||
keyToImport = jsonKeystore.text.replaceAll("'", "\\'");
|
||||
}
|
||||
|
||||
importIsLoading = true;
|
||||
notifyListeners();
|
||||
final clipboardData = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
|
@ -63,8 +83,8 @@ class SubstrateSdk with ChangeNotifier {
|
|||
final json = await sdk.api.keyring
|
||||
.importAccount(
|
||||
keyring,
|
||||
keyType: KeyType.keystore,
|
||||
key: jsonKeystore.text.replaceAll("'", "\\'"),
|
||||
keyType: keytype,
|
||||
key: keyToImport,
|
||||
name: 'testKey',
|
||||
password: keystorePassword.text,
|
||||
)
|
||||
|
@ -72,44 +92,119 @@ class SubstrateSdk with ChangeNotifier {
|
|||
importIsLoading = false;
|
||||
notifyListeners();
|
||||
});
|
||||
final acc = await sdk.api.keyring
|
||||
.addAccount(
|
||||
keyring,
|
||||
keyType: KeyType.mnemonic,
|
||||
acc: json!,
|
||||
password: keystorePassword.text,
|
||||
)
|
||||
.catchError((e) {
|
||||
if (json == null) return false;
|
||||
try {
|
||||
final acc = await sdk.api.keyring.addAccount(
|
||||
keyring,
|
||||
keyType: KeyType.mnemonic,
|
||||
acc: json,
|
||||
password: keystorePassword.text,
|
||||
);
|
||||
Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
|
||||
} catch (e) {
|
||||
importIsLoading = false;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
// await keystoreBox.clear();
|
||||
await keystoreBox.add(acc.toJson());
|
||||
Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
|
||||
// await keystoreBox.add(acc.toJson());
|
||||
importIsLoading = false;
|
||||
await Future.delayed(const Duration(milliseconds: 20));
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List getKeyStoreAddress() {
|
||||
List result = [];
|
||||
Future<List<AddressInfo>> getKeyStoreAddress() async {
|
||||
List<AddressInfo> result = [];
|
||||
|
||||
for (var element in keystoreBox.values) {
|
||||
// sdk.api.account.unsubscribeBalance();
|
||||
for (var element in keyring.allAccounts) {
|
||||
// Clipboard.setData(ClipboardData(text: jsonEncode(element)));
|
||||
result.add(element['address']);
|
||||
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();
|
||||
if (nodeConnected) {
|
||||
final brutBalance = await sdk.api.account.queryBalance(element.address);
|
||||
account.balance = int.parse(brutBalance!.freeBalance) / 100;
|
||||
}
|
||||
result.add(account);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<String> generateMnemonic() async {
|
||||
final gen = await sdk.api.keyring.generateMnemonic(42);
|
||||
Future<void> deleteAllAccounts() async {
|
||||
for (var account in keyring.allAccounts) {
|
||||
await sdk.api.keyring.deleteAccount(keyring, account);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> generateMnemonic() async {
|
||||
final gen = await sdk.api.keyring.generateMnemonic(ss58);
|
||||
generatedMnemonic = gen.mnemonic!;
|
||||
notifyListeners();
|
||||
return gen.mnemonic!;
|
||||
|
||||
final res = await importAccount(fromMnemonic: true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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, 'Paiement effectué avec succès !');
|
||||
}
|
||||
},
|
||||
);
|
||||
print(hash.toString());
|
||||
} catch (err) {
|
||||
print(err.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -52,30 +52,50 @@ class SubstrateSandBox extends StatelessWidget {
|
|||
height: 35,
|
||||
),
|
||||
onTap: () async {
|
||||
await keystoreBox.clear();
|
||||
await _sub.deleteAllAccounts();
|
||||
_sub.reload();
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
]),
|
||||
|
||||
Text(keystoreBox.isEmpty
|
||||
? '-'
|
||||
: _sub.getKeyStoreAddress().toString()),
|
||||
// const SizedBox(height: 40),
|
||||
// const Text('Trousseau:'),
|
||||
// TextField(
|
||||
// controller: _sub.jsonKeystore,
|
||||
// onChanged: (_) => _sub.reload(),
|
||||
// minLines: 5,
|
||||
// maxLines: 5,
|
||||
// ),
|
||||
FutureBuilder(
|
||||
future: _sub.getKeyStoreAddress(),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<List<AddressInfo>> _data) {
|
||||
return Column(children: [
|
||||
for (final AddressInfo e in _data.data!)
|
||||
Row(children: [
|
||||
InkWell(
|
||||
onTap: () => _sub.keyring.setCurrent(_sub
|
||||
.keyring.keyPairs
|
||||
.firstWhere((element) =>
|
||||
element.address == e.address!)),
|
||||
child: Text(
|
||||
getShortPubkey(e.address!),
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Monospace'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
InkWell(
|
||||
onTap: () async => await _sub.pay(
|
||||
context,
|
||||
e.address!,
|
||||
10,
|
||||
_sub.keystorePassword.text),
|
||||
child: Text("${e.balance.toString()} ğdev"),
|
||||
)
|
||||
])
|
||||
]);
|
||||
}),
|
||||
const SizedBox(height: 20),
|
||||
const Text('Mot de passe du trousseau:'),
|
||||
TextField(
|
||||
controller: _sub.keystorePassword,
|
||||
obscureText: true,
|
||||
obscuringCharacter: '•',
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
onChanged: (_) => _sub.reload(),
|
||||
),
|
||||
Column(
|
||||
|
@ -89,9 +109,14 @@ class SubstrateSandBox extends StatelessWidget {
|
|||
),
|
||||
onPressed: _sub.keystorePassword.text.isNotEmpty
|
||||
? () async {
|
||||
await _sub.importFromKeystore();
|
||||
final res = await _sub.importAccount();
|
||||
_sub.importIsLoading = false;
|
||||
_sub.reload();
|
||||
snack(
|
||||
context,
|
||||
res
|
||||
? 'Portefeuille importé'
|
||||
: 'Le format de trousseau est invalide');
|
||||
}
|
||||
: null,
|
||||
child: const Text(
|
||||
|
@ -108,10 +133,17 @@ class SubstrateSandBox extends StatelessWidget {
|
|||
onPrimary: Colors.black, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
await _sub.generateMnemonic();
|
||||
final res = await _sub.generateMnemonic();
|
||||
_sub.importIsLoading = false;
|
||||
_sub.reload();
|
||||
snack(
|
||||
context,
|
||||
res
|
||||
? 'Portefeuille importé'
|
||||
: 'Le format de trousseau est invalide');
|
||||
},
|
||||
child: const Text(
|
||||
'Générer un mnemonic',
|
||||
"Générer un mnemonic et l'importer",
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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.4+8
|
||||
version: 0.0.5+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
|
Loading…
Reference in New Issue