Merge branch 'substrate-sdk'

This commit is contained in:
poka 2022-05-23 11:08:24 +02:00
commit 7a6bda3545
101 changed files with 4884 additions and 3086 deletions

View File

@ -45,8 +45,8 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "gecko.axiomteam.fr"
minSdkVersion 16
targetSdkVersion 30
minSdkVersion 19
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true

View File

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gecko">
package="gecko.axiomteam.fr">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View File

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gecko">
package="gecko.axiomteam.fr">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
@ -9,32 +9,34 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application android:requestLegacyExternalStorage="true"
<application
android:requestLegacyExternalStorage="true"
android:name="${applicationName}"
android:label="Ğecko">
android:label="Ğecko"
android:usesCleartextTraffic="true">
<!-- TODO: Remove usesCleartextTraffic for production mode ! kopa -->
<!-- android:icon="@mipmap/ic_launcher"> -->
<activity
android:requestLegacyExternalStorage="true"
android:name=".MainActivity"
android:resource="@style/NormalTheme"
android:icon="@mipmap/ic_launcher"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
<!-- <meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
android:icon="@mipmap/ic_launcher"
/> -->
<!-- Theme to apply as soon as Flutter begins rendering frames -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,4 +1,4 @@
package com.example.gecko
package gecko.axiomteam.fr
import io.flutter.embedding.android.FlutterActivity

View File

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gecko">
package="gecko.axiomteam.fr">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

View File

@ -1,5 +1,3 @@
[
"https://g1.librelois.fr/gva",
"https://duniter-gva.axiom-team.fr/gva",
"https://duniter-g1.p2p.legal/gva"
"https://g1.librelois.fr/gva"
]

View File

@ -299,7 +299,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.gecko;
PRODUCT_BUNDLE_IDENTIFIER = gecko.axiomteam.fr;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -431,7 +431,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.gecko;
PRODUCT_BUNDLE_IDENTIFIER = gecko.axiomteam.fr;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -458,7 +458,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.gecko;
PRODUCT_BUNDLE_IDENTIFIER = gecko.axiomteam.fr;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -492,4 +492,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -14,14 +14,16 @@ late String appVersion;
late SharedPreferences prefs;
late String endPointGVA;
const int pinLength = 5;
const String appLang = 'french';
const String appLang = 'english';
late Box<WalletData> walletBox;
late Box<ChestData> chestBox;
late Box configBox;
late Box<G1WalletsList> g1WalletsBox;
// late Box keystoreBox;
String cesiumPod = "https://g1.data.le-sou.org";
// String cesiumPod = "https://g1.data.le-sou.org";
String cesiumPod = "https://g1.data.presles.fr";
// String cesiumPod = "https://g1.data.e-is.pro";
// Responsive ratios
@ -36,3 +38,10 @@ Color orangeC = const Color(0xffd07316);
Color yellowC = const Color(0xffFFD68E);
Color floattingYellow = const Color(0xffEFEFBF);
Color backgroundColor = const Color(0xFFF5F5F5);
// Substrate settings
const int ss58 = 42;
String currencyName = 'Ğdev';
// Debug
const debugPin = true;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2020 Axiom-Team.
// Copyright (C) 2022 Axiom-Team.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
@ -20,11 +20,11 @@ import 'dart:io';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/change_pin.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
@ -65,19 +65,23 @@ Future<void> main() async {
Hive.registerAdapter(ChestDataAdapter());
Hive.registerAdapter(G1WalletsListAdapter());
Hive.registerAdapter(IdAdapter());
// Hive.registerAdapter(KeyStoreDataAdapter());
walletBox = await Hive.openBox<WalletData>("walletBox");
chestBox = await Hive.openBox<ChestData>("chestBox");
configBox = await Hive.openBox("configBox");
await Hive.deleteBoxFromDisk('g1WalletsBox');
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
// keystoreBox = await Hive.openBox("keystoreBox");
g1WalletsBox.clear();
// g1WalletsBox.clear();
// final HiveStore _store =
// await HiveStore.open(path: '${appPath.path}/gqlCache');
// Get a valid GVA endpoint
// endPointGVA = 'https://g1.librelois.fr/gva';
endPointGVA = 'https://duniter-g1.p2p.legal/gva';
endPointGVA = 'https://g1.librelois.fr/gva';
// endPointGVA = 'https://duniter-g1.p2p.legal/gva';
// await _homeProvider.getValidEndpoint();
// if (endPointGVA == 'HS') {
@ -152,9 +156,9 @@ class Gecko extends StatelessWidget {
ChangeNotifierProvider(create: (_) => ChestProvider()),
ChangeNotifierProvider(create: (_) => GenerateWalletsProvider()),
ChangeNotifierProvider(create: (_) => WalletOptionsProvider()),
ChangeNotifierProvider(create: (_) => ChangePinProvider()),
ChangeNotifierProvider(create: (_) => SearchProvider()),
ChangeNotifierProvider(create: (_) => CesiumPlusProvider())
ChangeNotifierProvider(create: (_) => CesiumPlusProvider()),
ChangeNotifierProvider(create: (_) => SubstrateSdk())
],
child: GraphQLProvider(
client: _client,
@ -178,8 +182,8 @@ class Gecko extends StatelessWidget {
),
primaryColor: const Color(0xffFFD58D),
textTheme: const TextTheme(
bodyText1: TextStyle(),
bodyText2: TextStyle(),
bodyText1: TextStyle(fontSize: 16),
bodyText2: TextStyle(fontSize: 18),
).apply(
bodyColor: const Color(0xFF000000),
),

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,10 @@ part 'chest_data.g.dart';
@HiveType(typeId: 1)
class ChestData extends HiveObject {
@HiveField(0)
String? dewif;
String? address;
@HiveField(1)
String? rootAddress;
@HiveField(2)
String? name;
@ -25,7 +28,8 @@ class ChestData extends HiveObject {
bool? isCesium;
ChestData({
this.dewif,
this.address,
this.rootAddress,
this.name,
this.defaultWallet,
this.imageName,

View File

@ -17,7 +17,8 @@ class ChestDataAdapter extends TypeAdapter<ChestData> {
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ChestData(
dewif: fields[0] as String?,
address: fields[0] as String?,
rootAddress: fields[1] as String?,
name: fields[2] as String?,
defaultWallet: fields[3] as int?,
imageName: fields[4] as String?,
@ -29,9 +30,11 @@ class ChestDataAdapter extends TypeAdapter<ChestData> {
@override
void write(BinaryWriter writer, ChestData obj) {
writer
..writeByte(6)
..writeByte(7)
..writeByte(0)
..write(obj.dewif)
..write(obj.address)
..writeByte(1)
..write(obj.rootAddress)
..writeByte(2)
..write(obj.name)
..writeByte(3)

View File

@ -11,19 +11,19 @@ class G1WalletsList {
@HiveField(1)
double? balance;
@HiveField(3)
@HiveField(2)
Id? id;
@HiveField(4)
@HiveField(3)
Image? avatar;
@HiveField(5)
@HiveField(4)
String? username;
@HiveField(6)
@HiveField(5)
String? csName;
@HiveField(7)
@HiveField(6)
bool? isMembre;
G1WalletsList({

View File

@ -1,7 +1,5 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_local_variable
part of 'g1_wallets_list.dart';
// **************************************************************************
@ -21,11 +19,11 @@ class G1WalletsListAdapter extends TypeAdapter<G1WalletsList> {
return G1WalletsList(
pubkey: fields[0] as String?,
balance: fields[1] as double?,
id: fields[3] as Id?,
avatar: fields[4] as Image?,
username: fields[5] as String?,
csName: fields[6] as String?,
isMembre: fields[7] as bool?,
id: fields[2] as Id?,
avatar: fields[3] as Image?,
username: fields[4] as String?,
csName: fields[5] as String?,
isMembre: fields[6] as bool?,
);
}
@ -37,15 +35,15 @@ class G1WalletsListAdapter extends TypeAdapter<G1WalletsList> {
..write(obj.pubkey)
..writeByte(1)
..write(obj.balance)
..writeByte(3)
..writeByte(2)
..write(obj.id)
..writeByte(4)
..writeByte(3)
..write(obj.avatar)
..writeByte(5)
..writeByte(4)
..write(obj.username)
..writeByte(6)
..writeByte(5)
..write(obj.csName)
..writeByte(7)
..writeByte(6)
..write(obj.isMembre);
}
@ -66,10 +64,6 @@ class IdAdapter extends TypeAdapter<Id> {
@override
Id read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Id();
}

View File

@ -0,0 +1,28 @@
import 'package:hive_flutter/hive_flutter.dart';
import 'package:polkawallet_sdk/storage/types/keyPairData.dart';
part 'keystore_data.g.dart';
@HiveType(typeId: 4)
class KeyStoreData extends HiveObject {
@HiveField(0)
KeyPairData? keystore;
KeyStoreData({this.keystore});
@override
String toString() {
return keystore!.address!;
}
String name() {
return keystore!.name!;
}
String pubkey() {
return keystore!.pubKey!;
}
Map indexInfo() {
return keystore!.indexInfo!;
}
}

View File

@ -0,0 +1,41 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'keystore_data.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class KeyStoreDataAdapter extends TypeAdapter<KeyStoreData> {
@override
final int typeId = 4;
@override
KeyStoreData read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return KeyStoreData(
keystore: fields[0] as KeyPairData?,
);
}
@override
void write(BinaryWriter writer, KeyStoreData obj) {
writer
..writeByte(1)
..writeByte(0)
..write(obj.keystore);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is KeyStoreDataAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({Key? key, required this.onInit, required this.child})
: super(key: key);
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
widget.onInit();
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View File

@ -1,7 +1,5 @@
import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
part 'wallet_data.g.dart';
@HiveType(typeId: 0)
@ -10,22 +8,26 @@ class WalletData extends HiveObject {
int? chest;
@HiveField(1)
int? number;
String? address;
@HiveField(2)
String? name;
int? number;
@HiveField(3)
int? derivation;
String? name;
@HiveField(4)
String? imageName;
int? derivation;
@HiveField(5)
String? imageName;
@HiveField(6)
File? imageFile;
WalletData(
{this.chest,
this.address,
this.number,
this.name,
this.derivation,
@ -48,3 +50,10 @@ class WalletData extends HiveObject {
return [chest, number];
}
}
class NewWallet {
final String address;
final String password;
NewWallet._(this.address, this.password);
}

View File

@ -18,29 +18,32 @@ class WalletDataAdapter extends TypeAdapter<WalletData> {
};
return WalletData(
chest: fields[0] as int?,
number: fields[1] as int?,
name: fields[2] as String?,
derivation: fields[3] as int?,
imageName: fields[4] as String?,
imageFile: fields[5] as File?,
address: fields[1] as String?,
number: fields[2] as int?,
name: fields[3] as String?,
derivation: fields[4] as int?,
imageName: fields[5] as String?,
imageFile: fields[6] as File?,
);
}
@override
void write(BinaryWriter writer, WalletData obj) {
writer
..writeByte(6)
..writeByte(7)
..writeByte(0)
..write(obj.chest)
..writeByte(1)
..write(obj.number)
..write(obj.address)
..writeByte(2)
..write(obj.name)
..write(obj.number)
..writeByte(3)
..write(obj.derivation)
..write(obj.name)
..writeByte(4)
..write(obj.imageName)
..write(obj.derivation)
..writeByte(5)
..write(obj.imageName)
..writeByte(6)
..write(obj.imageFile);
}

View File

@ -63,7 +63,7 @@ class CesiumPlusProvider with ChangeNotifier {
Future<String> getName(String? _pubkey) async {
String? _name;
if (g1WalletsBox.get(_pubkey)!.csName != null) {
if (g1WalletsBox.get(_pubkey)?.csName != null) {
return g1WalletsBox.get(_pubkey)!.csName!;
}

View File

@ -1,48 +0,0 @@
import 'package:durt/durt.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
class ChangePinProvider with ChangeNotifier {
bool ischangedPin = false;
TextEditingController newPin = TextEditingController();
String? pinToGive;
NewWallet? get badWallet => null;
Future<NewWallet?> changePin(String _oldPin, {String? newCustomPin}) async {
final NewWallet newWalletFile;
try {
final _chest = chestBox.get(configBox.get('currentChest'))!;
if (_chest.isCesium!) {
newWalletFile = await Dewif().changeCesiumPassword(
dewif: _chest.dewif!,
oldPassword: _oldPin.toUpperCase(),
newPassword: newCustomPin);
} else {
newWalletFile = await Dewif().changePassword(
dewif: _chest.dewif!,
oldPassword: _oldPin.toUpperCase(),
newPassword: newCustomPin);
}
newPin.text = pinToGive = newWalletFile.password;
ischangedPin = true;
// notifyListeners();
return newWalletFile;
} catch (e) {
log.e('Impossible de changer le code PIN: $e');
return badWallet;
}
}
void storeNewPinChest(context, NewWallet _newWalletFile) {
// ChestData currentChest = chestBox.getAt(configBox.get('currentChest'));
// currentChest.dewif = _newWalletFile.dewif;
// await chestBox.add(currentChest);
chestBox.get(configBox.get('currentChest'))!.dewif = _newWalletFile.dewif;
Navigator.pop(context, pinToGive);
pinToGive = '';
}
}

View File

@ -1,21 +1,22 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:durt/durt.dart';
import 'package:durt/durt.dart' as durt;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/bip39_words.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
import "package:unorm_dart/unorm_dart.dart" as unorm;
class GenerateWalletsProvider with ChangeNotifier {
GenerateWalletsProvider();
// NewWallet generatedWallet;
NewWallet? actualWallet;
durt.NewWallet? actualWallet;
FocusNode walletNameFocus = FocusNode();
Color? askedWordColor = Colors.black;
@ -37,7 +38,7 @@ class GenerateWalletsProvider with ChangeNotifier {
bool isCesiumIDVisible = false;
bool isCesiumPWDVisible = false;
bool canImport = false;
late CesiumWallet cesiumWallet;
late durt.CesiumWallet cesiumWallet;
// Import Chest
TextEditingController cellController0 = TextEditingController();
@ -55,7 +56,7 @@ class GenerateWalletsProvider with ChangeNotifier {
bool isFirstTimeSentenceComplete = true;
Future storeHDWChest(
NewWallet _wallet, String _name, BuildContext context) async {
String address, String _name, BuildContext context) async {
int chestNumber = 0;
chestBox.toMap().forEach((key, value) {
if (!value.isCesium!) {
@ -70,7 +71,7 @@ class GenerateWalletsProvider with ChangeNotifier {
chestName = 'Coffre à Ğecko ${chestNumber + 1}';
}
ChestData thisChest = ChestData(
dewif: _wallet.dewif,
address: address,
name: chestName,
defaultWallet: 0,
imageName: '${chestNumber % 8}.png',
@ -81,9 +82,10 @@ class GenerateWalletsProvider with ChangeNotifier {
WalletData myWallet = WalletData(
chest: chestKey,
address: address,
number: 0,
name: _name,
derivation: 3,
derivation: 2,
imageName: '0.png');
await walletBox.add(myWallet);
@ -152,64 +154,78 @@ class GenerateWalletsProvider with ChangeNotifier {
notifyListeners();
}
Future<NewWallet?> generateWallet(String generatedMnemonic,
{required bool isImport}) async {
try {
actualWallet = await Dewif().generateDewif(
generatedMnemonic, randomSecretCode(pinLength),
lang: appLang);
} catch (e) {
log.e(e);
}
if (!isImport) {
mnemonicController.text = generatedMnemonic;
pin.text = actualWallet!.password;
}
// notifyListeners();
return actualWallet;
}
String changePinCode({required bool reload}) {
pin.text = randomSecretCode(pinLength);
pin.text = durt.randomSecretCode(pinLength);
if (reload) {
notifyListeners();
}
return pin.text;
}
Future<Uint8List> printWallet(String? _title) async {
Future<Uint8List> printWallet(AsyncSnapshot<List>? mnemoList) async {
final ByteData fontData =
await rootBundle.load("assets/OpenSans-Regular.ttf");
final pw.Font ttf = pw.Font.ttf(fontData.buffer.asByteData());
final pdf = pw.Document();
const imageProvider = AssetImage('assets/icon/gecko_final.png');
final geckoLogo = await flutterImageProvider(imageProvider);
// const imageProvider = AssetImage('assets/icon/gecko_final.png');
// final geckoLogo = await flutterImageProvider(imageProvider);
pw.Widget arrayCell(dataWord) {
return pw.SizedBox(
width: 120,
child: pw.Column(children: <pw.Widget>[
pw.Text(
dataWord.split(':')[0],
style: pw.TextStyle(
fontSize: 15, color: const PdfColor(0.5, 0, 0), font: ttf),
),
pw.Text(
dataWord.split(':')[1],
style: pw.TextStyle(
fontSize: 20, color: const PdfColor(0, 0, 0), font: ttf),
),
pw.SizedBox(height: 10)
]),
);
}
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Column(children: <pw.Widget>[
pw.SizedBox(height: 20),
pw.Text("Phrase de restauration:",
style: pw.TextStyle(fontSize: 20, font: ttf)),
pw.SizedBox(height: 10),
pw.Text(_title!,
style: pw.TextStyle(fontSize: 15, font: ttf),
textAlign: pw.TextAlign.center),
pw.Expanded(
child: pw.Align(
alignment: pw.Alignment.bottomCenter,
child: pw.Text(
"Gardez cette feuille en lieu sûr, à l'abris des regards indiscrets.",
style: pw.TextStyle(fontSize: 10, font: ttf),
))),
pw.SizedBox(height: 15),
pw.Image(geckoLogo, height: 50)
]);
return pw.Column(
// mainAxisAlignment: pw.MainAxisAlignment.center,
// mainAxisSize: pw.MainAxisSize.max,
// crossAxisAlignment: pw.CrossAxisAlignment.center,
children: <pw.Widget>[
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList!.data![0]),
arrayCell(mnemoList.data![1]),
arrayCell(mnemoList.data![2]),
arrayCell(mnemoList.data![3]),
]),
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList.data![4]),
arrayCell(mnemoList.data![5]),
arrayCell(mnemoList.data![6]),
arrayCell(mnemoList.data![7]),
]),
pw.Row(children: <pw.Widget>[
arrayCell(mnemoList.data![8]),
arrayCell(mnemoList.data![9]),
arrayCell(mnemoList.data![10]),
arrayCell(mnemoList.data![11])
]),
pw.Expanded(
child: pw.Align(
alignment: pw.Alignment.bottomCenter,
child: pw.Text(
"Gardez cette feuille préciseusement, à labri des lézards indiscrets.",
style: pw.TextStyle(fontSize: 15, font: ttf),
)))
],
);
},
),
);
@ -219,63 +235,13 @@ class GenerateWalletsProvider with ChangeNotifier {
Future<void> generateCesiumWalletPubkey(
String _cesiumID, String _cesiumPWD) async {
cesiumWallet = CesiumWallet(_cesiumID, _cesiumPWD);
cesiumWallet = durt.CesiumWallet(_cesiumID, _cesiumPWD);
String _walletPubkey = cesiumWallet.pubkey;
cesiumPubkey.text = _walletPubkey;
log.d(_walletPubkey);
}
Future<int?> importCesiumWallet() async {
// String _walletPubkey = await DubpRust.getLegacyPublicKey(
// salt: _cesiumID, password: _cesiumPWD);
// String shortPubkey = truncate(_walletPubkey, 9,
// omission: "...", position: TruncatePosition.end);
// await storeWallet(
// actualWallet, 'Portefeuille Cesium - $shortPubkey', context);
// NewWallet myCesiumWallet = await DubpRust.genWalletFromDeprecatedSaltPassword(salt: _cesiumID, password: _cesiumPWD);
cesiumID.text = '';
cesiumPWD.text = '';
cesiumPubkey.text = '';
canImport = false;
isCesiumIDVisible = false;
isCesiumPWDVisible = false;
int chestNumber = 0;
chestBox.toMap().forEach((key, value) {
if (value.isCesium!) {
chestNumber++;
}
});
String chestName;
if (chestNumber == 0) {
chestName = 'Coffre à Césium';
} else {
chestName = 'Coffre à Césium ${chestNumber + 1}';
}
log.d(pin.text);
NewWallet cesiumDewif =
await Dewif().generateCesiumDewif(cesiumWallet.seed, pin.text);
ChestData cesiumChest = ChestData(
dewif: cesiumDewif.dewif,
name: chestName,
imageName: 'cesium.png',
defaultWallet: 0,
isCesium: true);
await chestBox.add(cesiumChest).then((value) => null);
int? chestKey = await chestBox.toMap().keys.last;
// chestBox.toMap().
await configBox.put('currentChest', chestKey);
pin.text = '';
return chestKey;
}
void cesiumIDisVisible() {
isCesiumIDVisible = !isCesiumIDVisible;
notifyListeners();
@ -293,8 +259,10 @@ class GenerateWalletsProvider with ChangeNotifier {
notifyListeners();
}
List<String> generateWordList() {
generatedMnemonic = generateMnemonic(lang: appLang);
Future<List<String>> generateWordList(BuildContext context) async {
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
generatedMnemonic = await _sub.generateMnemonic(lang: appLang);
List<String> _wordsList = [];
String word;
int _nbr = 1;
@ -313,7 +281,7 @@ class GenerateWalletsProvider with ChangeNotifier {
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
return bip39Words.contains(word);
return bip39Words(appLang).contains(word);
}
bool isBipWordsList(List<String> words) {
@ -322,7 +290,7 @@ class GenerateWalletsProvider with ChangeNotifier {
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
if (!bip39Words.contains(word)) {
if (!bip39Words(appLang).contains(word)) {
isValid = false;
}
}
@ -333,8 +301,8 @@ class GenerateWalletsProvider with ChangeNotifier {
cellController0.text = cellController1.text = cellController2.text =
cellController3.text = cellController4.text = cellController5.text =
cellController6.text = cellController7.text = cellController8.text =
cellController9.text = cellController10.text =
cellController11.text = '';
cellController9.text =
cellController10.text = cellController11.text = '';
isFirstTimeSentenceComplete = true;
notifyListeners();
}
@ -366,22 +334,31 @@ class GenerateWalletsProvider with ChangeNotifier {
}
}
Future<bool> isSentenceValid() async {
String inputMnemonic =
'${cellController0.text} ${cellController1.text} ${cellController2.text} ${cellController3.text} ${cellController4.text} ${cellController5.text} ${cellController6.text} ${cellController7.text} ${cellController8.text} ${cellController9.text} ${cellController10.text} ${cellController11.text}';
Future pasteMnemonic(BuildContext context) async {
final sentence = await Clipboard.getData('text/plain');
int nbr = 0;
// Needed for bad encoding of UTF-8
inputMnemonic = inputMnemonic.replaceAll('é', '');
inputMnemonic = inputMnemonic.replaceAll('è', '');
List cells = [
cellController0,
cellController1,
cellController2,
cellController3,
cellController4,
cellController5,
cellController6,
cellController7,
cellController8,
cellController9,
cellController10,
cellController11
];
for (var word in sentence!.text!.split(' ')) {
bool isValid = isBipWord(word);
NewWallet? generatedWallet =
await generateWallet(inputMnemonic, isImport: true);
if (generatedWallet == null) {
return false;
} else {
generatedMnemonic = inputMnemonic;
return true;
if (isValid) {
cells[nbr].text = word;
}
nbr++;
}
}

View File

@ -139,22 +139,6 @@ class HomeProvider with ChangeNotifier {
notifyListeners();
}
void snackNode(context) {
if (isFirstBuild) {
String _message;
if (endPointGVA == 'HS') {
_message =
"Aucun noeud Duniter disponible, veuillez réessayer ultérieurement";
} else {
_message = "Vous êtes connecté au noeud\n${endPointGVA.split('/')[2]}";
}
final snackBar = SnackBar(
content: Text(_message), duration: const Duration(seconds: 2));
isFirstBuild = false;
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
void rebuildWidget() {
notifyListeners();
}

View File

@ -1,10 +1,11 @@
import 'dart:typed_data';
import 'package:durt/durt.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:provider/provider.dart';
class MyWalletsProvider with ChangeNotifier {
List<WalletData> listWallets = [];
@ -21,25 +22,13 @@ class MyWalletsProvider with ChangeNotifier {
return configBox.get('currentChest');
}
String dewifToMnemonic(context, WalletData _wallet, String _pin) {
String _mnemonic;
try {
String _localDewif = chestBox.get(_wallet.chest)!.dewif!;
_mnemonic = Dewif()
.mnemonicFromDewif(_localDewif, _pin.toUpperCase(), lang: appLang);
} on ChecksumException catch (e) {
log.e(e.cause);
return 'bad';
} catch (e) {
// _homeProvider.playSound('non', 0.6);
log.e('ERROR READING FILE: $e');
return 'bad';
}
return _mnemonic;
}
bool checkIfWalletExist() {
// configBox.delete('endpoint');
if (!configBox.containsKey('endpoint') || configBox.get('endpoint') == '') {
log.d('No endpoint, configure...');
configBox.put('endpoint', 'ws://127.0.0.1:9944');
}
if (chestBox.isEmpty) {
log.i('No wallets detected');
return false;
@ -85,6 +74,7 @@ class MyWalletsProvider with ChangeNotifier {
}
Future<int> deleteAllWallet(context) async {
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
try {
log.w('DELETE ALL WALLETS ?');
@ -93,9 +83,7 @@ class MyWalletsProvider with ChangeNotifier {
await walletBox.clear();
await chestBox.clear();
await configBox.delete('defaultWallet');
// await Future.delayed(const Duration(milliseconds: 50));
// notifyListeners();
await _sub.deleteAllAccounts();
await Navigator.of(context).pushNamedAndRemoveUntil(
'/',
ModalRoute.withName('/'),
@ -113,23 +101,42 @@ class MyWalletsProvider with ChangeNotifier {
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
'Êtes-vous sûr de vouloir supprimer tous vos trousseaux ?'),
content: const SingleChildScrollView(child: Text('')),
backgroundColor: backgroundColor,
content: const Text(
'Êtes-vous sûr de vouloir oublier tous vos coffres ?',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
actions: <Widget>[
TextButton(
child: const Text("Non"),
onPressed: () {
Navigator.pop(context, false);
},
),
TextButton(
key: const Key('confirmDeletingAllWallets'),
child: const Text("Oui"),
onPressed: () {
Navigator.pop(context, true);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: const Key('confirmDeletingAllWallets'),
child: const Text(
"Oui",
style: TextStyle(
fontSize: 20,
color: Color(0xffD80000),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
const SizedBox(width: 20),
TextButton(
child: const Text(
"Non",
style: TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.pop(context, false);
},
),
const SizedBox(height: 120)
],
)
],
);
},
@ -143,15 +150,27 @@ class MyWalletsProvider with ChangeNotifier {
List<WalletData> _walletConfig = readAllWallets(_chest);
if (_walletConfig.isEmpty) {
_newDerivationNbr = 3;
_newDerivationNbr = 2;
_newWalletNbr = 0;
} else {
_newDerivationNbr = _walletConfig.last.derivation! + 3;
_newDerivationNbr = _walletConfig.last.derivation! + 2;
_newWalletNbr = _walletConfig.last.number! + 1;
}
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final int? _currentChestNumber = myWalletProvider.getCurrentChest();
final ChestData _currentChest = chestBox.get(_currentChestNumber)!;
final address = await _sub.derive(
context, _currentChest.address!, _newDerivationNbr, pinCode);
WalletData newWallet = WalletData(
chest: _chest,
address: address,
number: _newWalletNbr,
name: _name,
derivation: _newDerivationNbr,

View File

@ -0,0 +1,371 @@
// ignore_for_file: avoid_print
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:polkawallet_sdk/storage/types/keyPairData.dart';
import 'package:truncate/truncate.dart';
class SubstrateSdk with ChangeNotifier {
final int ss58 = 42;
final WalletSDK sdk = WalletSDK();
final Keyring keyring = Keyring();
String generatedMnemonic = '';
bool sdkReady = false;
bool sdkLoading = false;
bool nodeConnected = false;
bool importIsLoading = false;
int blocNumber = 0;
bool isLoadingEndpoint = false;
TextEditingController jsonKeystore = TextEditingController();
TextEditingController keystorePassword = TextEditingController();
Future<void> initApi() async {
sdkLoading = true;
await keyring.init([ss58]);
keyring.setSS58(ss58);
await sdk.init(keyring);
sdkReady = true;
sdkLoading = false;
notifyListeners();
}
Future<void> connectNode(BuildContext ctx) async {
List<NetworkParams> node = [];
final n = NetworkParams();
n.name = currencyName;
n.endpoint = configBox.get('endpoint');
n.ss58 = ss58;
node.add(n);
if (sdk.api.connectedNode?.endpoint != null) {
await sdk.api.setting.unsubscribeBestNumber();
}
isLoadingEndpoint = true;
notifyListeners();
final res = await sdk.api.connectNode(keyring, node).timeout(
const Duration(seconds: 7),
onTimeout: () => null,
);
isLoadingEndpoint = false;
notifyListeners();
if (res != null) {
nodeConnected = true;
notifyListeners();
snackNode(ctx, true);
} else {
nodeConnected = false;
notifyListeners();
snackNode(ctx, false);
}
// Subscribe bloc number
if (nodeConnected) {
sdk.api.setting.subscribeBestNumber((res) {
blocNumber = int.parse(res.toString());
notifyListeners();
});
}
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("'", "\\'");
}
importIsLoading = true;
notifyListeners();
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();
});
if (json == null) return '';
print(json);
try {
await sdk.api.keyring.addAccount(
keyring,
keyType: keytype,
acc: json,
password: password,
);
// Clipboard.setData(ClipboardData(text: jsonEncode(acc.toJson())));
} catch (e) {
print(e);
importIsLoading = false;
notifyListeners();
}
importIsLoading = false;
await Future.delayed(const Duration(milliseconds: 20));
notifyListeners();
final bakedAddress = keyring.allAccounts.last.address;
return bakedAddress!;
}
void reload() {
notifyListeners();
}
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!);
result.add(account);
}
return result;
}
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);
generatedMnemonic = gen.mnemonic!;
// final res = await importAccount(fromMnemonic: true);
// await Clipboard.setData(ClipboardData(text: generatedMnemonic));
return gen.mnemonic!;
}
// 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,
[destAddress, amount * 100],
password,
onStatusChange: (status) {
print('status: ' + status);
if (status == 'Ready') {
snack(context, 'Transaction terminé');
}
},
);
print(hash.toString());
return 'confirmed';
} catch (e) {
return e.toString();
}
}
Future<String> derive(
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(seedList[1]);
}
print(generatedMnemonic);
print(sourceDerivation);
return await importAccount(fromMnemonic: true, derivePath: '//$number');
}
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);
}
}
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";
} else {
_message =
"Vous êtes connecté au noeud\n${configBox.get('endpoint').split('//')[1]}";
}
final snackBar = SnackBar(
padding: const EdgeInsets.all(20),
content: Text(_message, style: const TextStyle(fontSize: 16)),
duration: const Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
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;
}

View File

@ -1,139 +1,41 @@
import 'dart:io';
import 'package:crypto/crypto.dart';
import 'package:durt/durt.dart';
import 'package:fast_base58/fast_base58.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:truncate/truncate.dart';
class WalletOptionsProvider with ChangeNotifier {
TextEditingController pubkey = TextEditingController();
TextEditingController address = TextEditingController();
final TextEditingController _newWalletName = TextEditingController();
bool isWalletUnlock = false;
bool ischangedPin = false;
TextEditingController newPin = TextEditingController();
bool isEditing = false;
bool isBalanceBlur = true;
bool isBalanceBlur = false;
FocusNode walletNameFocus = FocusNode();
TextEditingController nameController = TextEditingController();
late bool isDefaultWallet;
Future<NewWallet>? get badWallet => null;
String _getPubkeyFromDewif(
String? _dewif, _pin, int _pinLenght, int? derivation) {
RegExp regExp = RegExp(
r'^[A-Z0-9]+$',
caseSensitive: false,
multiLine: false,
);
if (regExp.hasMatch(_pin) == true && _pin.length == _pinLenght) {
} else {
return 'false';
}
if (derivation != -1) {
try {
final _wallet = HdWallet.fromDewif(_dewif!, _pin, lang: appLang);
pubkey.text = _wallet.getPubkey(derivation!);
log.d(pubkey.text);
notifyListeners();
return pubkey.text;
} catch (e) {
log.w('Bad PIN code !\n' + e.toString());
notifyListeners();
return 'false';
}
} else {
try {
pubkey.text = CesiumWallet.fromDewif(_dewif!, _pin).pubkey;
notifyListeners();
return pubkey.text;
} catch (e) {
log.w('Bad PIN code !\n' + e.toString());
notifyListeners();
return 'false';
}
}
}
String? readLocalWallet(
context, WalletData _wallet, String _pin, int _pinLenght,
{String? mnemonic}) {
isWalletUnlock = false;
final String _localPubkey;
try {
String? _localDewif = chestBox.get(_wallet.chest)!.dewif;
if (mnemonic == null) {
_localPubkey = _getPubkeyFromDewif(
_localDewif, _pin.toUpperCase(), _pinLenght, _wallet.derivation);
} else {
final _hdwallet = HdWallet.fromMnemonic(mnemonic);
_localPubkey = _hdwallet.getPubkey(_wallet.derivation!);
}
if (_localPubkey != 'false') {
pubkey.text = _localPubkey;
isWalletUnlock = true;
log.d(pubkey.text);
return _localDewif;
} else {
throw 'Bad pubkey';
}
} on ChecksumException catch (e) {
log.e(e.cause);
return 'bad';
} catch (e) {
// _homeProvider.playSound('non', 0.6);
log.e('ERROR READING FILE: $e');
pubkey.clear();
return 'bad';
}
}
int getPinLenght(_walletNbr) {
// TODOo: Get real Dewif lenght
// String _localDewif;
// if (_walletNbr is int || _walletNbr == null) {
// _localDewif = chestBox.get(configBox.get('currentChest')).dewif;
// } else {
// _localDewif = _walletNbr;
// }
// final int _pinLenght = DubpRust.getDewifSecretCodeLen(
// dewif: _localDewif, secretCodeType: SecretCodeType.letters);
return pinLength;
}
Future<double> getBalance(String pubkey, {bool isUd = false}) async {
final node = Gva(node: endPointGVA);
return await node.balance(pubkey, ud: isUd);
}
void _renameWallet(List<int?> _walletID, _newName,
void _renameWallet(List<int?> _walletID, String _newName,
{required bool isCesium}) async {
if (isCesium) {
ChestData _chestTarget = chestBox.get(_walletID[0])!;
_chestTarget.name = _newName;
await chestBox.put(_chestTarget.key, _chestTarget);
} else {
MyWalletsProvider myWalletClass = MyWalletsProvider();
MyWalletsProvider myWalletClass = MyWalletsProvider();
WalletData _walletTarget = myWalletClass.getWalletData(_walletID)!;
_walletTarget.name = _newName;
await walletBox.put(_walletTarget.key, _walletTarget);
}
WalletData _walletTarget = myWalletClass.getWalletData(_walletID)!;
_walletTarget.name = _newName;
await walletBox.put(_walletTarget.key, _walletTarget);
_newWalletName.text = '';
}
@ -161,12 +63,13 @@ class WalletOptionsProvider with ChangeNotifier {
final bool? _answer = await (_confirmDeletingWallet(context, wallet.name));
if (_answer!) {
walletBox.delete(wallet.key);
await walletBox.delete(wallet.key);
Navigator.popUntil(
context,
ModalRoute.withName('/mywallets'),
);
// Navigator.popUntil(
// context,
// ModalRoute.withName('/mywallets'),
// );
Navigator.pop(context);
}
return 0;
}
@ -205,14 +108,6 @@ class WalletOptionsProvider with ChangeNotifier {
);
}
snackCopyKey(context) {
const snackBar = SnackBar(
content:
Text("Cette clé publique a été copié dans votre presse-papier."),
duration: Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
String getShortPubkey(String pubkey) {
List<int> pubkeyByte = Base58Decode(pubkey);
Digest pubkeyS256 = sha256.convert(sha256.convert(pubkeyByte).bytes);
@ -242,14 +137,59 @@ class WalletOptionsProvider with ChangeNotifier {
if (pickedFile != null) {
_image = File(pickedFile.path);
////TODO: Store image on disk, store path in walletBox.imagePath
log.i(pickedFile.path);
return _image;
} else {
log.w('No image selected.');
return null;
}
}
void reloadBuild() {
notifyListeners();
}
String? getAddress(int chest, int derivation) {
String? _address;
walletBox.toMap().forEach((key, value) {
if (value.chest == chest && value.derivation == derivation) {
_address = value.address!;
return;
}
});
address.text = _address ?? '';
return _address;
}
}
Widget balance(BuildContext context, String address, double size) {
String balanceCache = '';
return Column(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, _sdk, _) {
return FutureBuilder(
future: _sdk.getBalance(address),
builder: (BuildContext context, AsyncSnapshot<num?> _balance) {
if (_balance.connectionState != ConnectionState.done ||
_balance.hasError) {
return Text(balanceCache,
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
));
}
balanceCache = "${_balance.data.toString()} $currencyName";
return Text(
balanceCache,
style: TextStyle(
fontSize: isTall ? size : 18,
),
);
});
}),
]);
}

View File

@ -1,14 +1,10 @@
import 'dart:io';
import 'package:durt/durt.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:jdenticon_dart/jdenticon_dart.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:qrscan/qrscan.dart' as scanner;
import 'dart:math';
import 'package:intl/intl.dart';
@ -59,34 +55,24 @@ class WalletsProfilesProvider with ChangeNotifier {
return barcode;
}
Future<String> pay(BuildContext context, {int? derivation}) async {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
int? currentChest = configBox.get('currentChest');
String result;
// Future<String> pay(BuildContext context, {int? derivation}) async {
// MyWalletsProvider _myWalletProvider =
// Provider.of<MyWalletsProvider>(context, listen: false);
// int? currentChest = configBox.get('currentChest');
// String result;
if (chestBox.get(currentChest)!.isCesium!) {
result = await Gva(node: endPointGVA).pay(
recipient: pubkey!,
amount: double.parse(payAmount.text),
cesiumSeed: _myWalletProvider.cesiumSeed,
comment: payComment.text,
derivation: -1,
lang: appLang);
} else {
derivation ??=
_myWalletProvider.getDefaultWallet(currentChest)!.derivation!;
result = await Gva(node: endPointGVA).pay(
recipient: pubkey!,
amount: double.parse(payAmount.text),
mnemonic: _myWalletProvider.mnemonic,
comment: payComment.text,
derivation: derivation,
lang: appLang);
}
// derivation ??=
// _myWalletProvider.getDefaultWallet(currentChest)!.derivation!;
// result = await Gva(node: endPointGVA).pay(
// recipient: pubkey!,
// amount: double.parse(payAmount.text),
// mnemonic: _myWalletProvider.mnemonic,
// comment: payComment.text,
// derivation: derivation,
// lang: appLang);
return result;
}
// return result;
// }
bool isPubkey(pubkey) {
final RegExp regExp = RegExp(
@ -97,7 +83,7 @@ class WalletsProfilesProvider with ChangeNotifier {
if (regExp.hasMatch(pubkey) == true &&
pubkey.length > 42 &&
pubkey.length < 45) {
pubkey.length < 50) {
log.d("C'est une pubkey !");
this.pubkey = pubkey;
@ -253,25 +239,6 @@ class WalletsProfilesProvider with ChangeNotifier {
return num.parse(result);
}
snackCopyKey(context) {
const snackBar = SnackBar(
padding: EdgeInsets.all(20),
content:
Text("Cette clé publique a été copié dans votre presse-papier."),
duration: Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
void switchProfileView() {
isHistoryScreen = !isHistoryScreen;
if (isHistoryScreen) {
historySwitchButtun = "Payer";
} else {
historySwitchButtun = "Voir l'historique";
}
notifyListeners();
}
String generateIdenticon(String _pubkey) {
return Jdenticon.toSvg(_pubkey);
}
@ -299,3 +266,12 @@ class WalletsProfilesProvider with ChangeNotifier {
return balance;
}
}
snackCopyKey(context) {
const snackBar = SnackBar(
padding: EdgeInsets.all(20),
content: Text("Cette clé publique a été copié dans votre presse-papier.",
style: TextStyle(fontSize: 16)),
duration: Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

View File

@ -1,5 +1,5 @@
import 'package:dots_indicator/dots_indicator.dart';
import 'package:flutter/material.dart';
import 'package:bubble/bubble.dart';
import 'package:gecko/globals.dart';
class CommonElements {
@ -8,95 +8,104 @@ class CommonElements {
return const Text('Coucou');
}
Widget bubbleSpeak(String text,
{double? long, Key? textKey, bool isMaxWidth = true}) {
Widget buildImage(String assetName,
[double boxHeight = 440, double imageWidth = 350]) {
return Container(
padding: const EdgeInsets.all(0),
width: 440,
height: boxHeight,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xffd2d4cf),
Color(0xffeaeae7),
],
),
border: Border.all(color: Colors.grey[900]!)),
child: Image.asset('assets/onBoarding/$assetName', width: imageWidth));
}
Widget buildText(List<TextSpan> text, [double size = 20]) {
return Container(
padding: const EdgeInsets.all(12),
width: 440,
decoration: BoxDecoration(
color: Colors.white, border: Border.all(color: Colors.grey[900]!)),
child: RichText(
textAlign: TextAlign.justify,
text: TextSpan(
style: TextStyle(
fontSize: size, color: Colors.black, letterSpacing: 0.3),
children: text,
),
),
);
}
Widget nextButton(
BuildContext context, String text, nextScreen, bool isFast) {
return SizedBox(
width: isMaxWidth ? double.infinity : 300,
child: Bubble(
padding: long == null
? const BubbleEdges.all(18)
: BubbleEdges.symmetric(horizontal: long, vertical: 30),
elevation: 5,
color: Colors.white,
margin: const BubbleEdges.fromLTRB(10, 0, 20, 10),
// nip: BubbleNip.leftTop,
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context, FaderTransition(page: nextScreen, isFast: isFast));
},
child: Text(
text,
key: textKey,
style: const TextStyle(
color: Colors.black, fontSize: 18, fontWeight: FontWeight.w400),
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
);
}
Widget bubbleSpeakRich(List<TextSpan> text, {Key? textKey}) {
return SizedBox(
width: double.infinity,
child: Bubble(
padding: const BubbleEdges.all(18),
elevation: 5,
color: Colors.white,
margin: const BubbleEdges.fromLTRB(10, 0, 20, 10),
// nip: BubbleNip.leftTop,
child: RichText(
key: textKey,
text: TextSpan(
style: const TextStyle(
fontSize: 18.0,
color: Colors.black,
),
children: text,
),
),
Widget buildProgressBar(double pagePosition) {
return DotsIndicator(
dotsCount: 10,
position: pagePosition,
decorator: DotsDecorator(
spacing: const EdgeInsets.symmetric(horizontal: 10),
color: Colors.grey[300]!, // Inactive color
activeColor: orangeC,
),
);
}
Widget onboardingProgressBar(
BuildContext context, String screenTitle, int progress) {
return Stack(children: [
Container(height: 100),
Positioned(
top: 0, left: 0, right: 0, child: GeckoSpeechAppBar(screenTitle)),
Positioned(
top: 0,
left: 0,
child: GestureDetector(
onTap: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
},
child: Image.asset(
'assets/onBoarding/gecko_bar.png',
),
Widget infoIntro(
BuildContext context,
List<TextSpan> text,
String assetName,
String buttonText,
nextScreen,
double pagePosition, {
bool isFast = false,
double boxHeight = 440,
double imageWidth = 350,
double textSize = 20,
}) {
return Column(children: <Widget>[
SizedBox(height: isTall ? 40 : 20),
buildProgressBar(pagePosition),
SizedBox(height: isTall ? 40 : 20),
buildText(text, textSize),
buildImage(assetName, boxHeight, imageWidth),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: nextButton(context, buttonText, nextScreen, false),
),
),
if (progress != 0)
Positioned(
top: 75,
left: 90,
child: Image.asset(
'assets/onBoarding/progress_bar/total.png',
),
),
if (progress != 0)
Positioned(
top: 75,
left: 90,
child: Image.asset(
'assets/onBoarding/progress_bar/$progress.png',
),
),
if (progress != 0)
Positioned(
top: 70,
right: 90,
child: Text(progress == 12 ? '11/11' : '$progress/11',
style: const TextStyle(fontSize: 12, color: Colors.black)),
),
// const SizedBox(height: 40),
SizedBox(height: isTall ? 40 : 10),
]);
}

View File

@ -33,7 +33,7 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
log.i('Build pubkey : ' + pubkey!);
WidgetsBinding.instance!.addPostFrameCallback((_) {});
// WidgetsBinding.instance.addPostFrameCallback((_) {});
_historyProvider.balance = _historyProvider.transBC = null;
@ -346,7 +346,7 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
],
),
),
trailing: Text("${repository[4]} Ğ1",
trailing: Text("${repository[4]} $currencyName",
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
textAlign: TextAlign.justify),
@ -403,7 +403,7 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(pubkey!),
@ -466,7 +466,7 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
return const Text('...');
}
return Text(
"${_balance.data.toString()} Ğ1",
"${_balance.data.toString()} $currencyName",
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22, fontWeight: FontWeight.w500),

View File

@ -1,9 +1,10 @@
import 'package:bubble/bubble.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/myWallets/restore_chest.dart';
@ -12,6 +13,7 @@ import 'package:gecko/screens/onBoarding/1.dart';
import 'package:gecko/screens/search.dart';
import 'package:gecko/screens/settings.dart';
import 'package:flutter/services.dart';
import 'package:gecko/screens/substrate_sandbox.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatelessWidget {
@ -24,7 +26,7 @@ class HomeScreen extends StatelessWidget {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context);
HomeProvider homeClass = HomeProvider();
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
@ -65,6 +67,20 @@ class HomeScreen extends StatelessWidget {
);
},
),
ListTile(
key: const Key('substrateSandbox'),
title: const Text('Substrate debug'),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const SubstrateSandBox();
}),
);
},
),
// ListTile(
// title: const Text('A propos'),
// onTap: () {
@ -82,8 +98,11 @@ class HomeScreen extends StatelessWidget {
body: Builder(
builder: (ctx) => StatefulWrapper(
onInit: () {
WidgetsBinding.instance!.addPostFrameCallback((_) {
if (isWalletsExists) homeClass.snackNode(ctx);
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (!_sub.sdkReady && !_sub.sdkLoading) await _sub.initApi();
if (_sub.sdkReady && !_sub.nodeConnected) {
await _sub.connectNode(ctx); //kopa
}
});
},
child: isWalletsExists ? geckHome(context) : welcomeHome(context)
@ -176,9 +195,10 @@ Widget geckHome(context) {
),
],
),
)
),
]),
),
const SizedBox(height: 15),
Expanded(
flex: 1,
child: Container(
@ -382,31 +402,30 @@ Widget welcomeHome(context) {
]),
Padding(
padding: EdgeInsets.only(top: 1 * ratio),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text(
"Lapplication de paiement Ğ1\nplus rapide quun reptile du Vietnam",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w700,
shadows: <Shadow>[
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
],
child:
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text(
"Lapplication de paiement $currencyName\nplus rapide quun reptile du Vietnam",
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w700,
shadows: <Shadow>[
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
)
]),
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
],
),
)
]),
),
Expanded(
flex: 1,
@ -464,7 +483,7 @@ Widget welcomeHome(context) {
context,
MaterialPageRoute(
builder: (context) {
return OnboardingStepOne();
return const OnboardingStepOne();
},
),
);
@ -512,28 +531,6 @@ Widget welcomeHome(context) {
);
}
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({Key? key, required this.onInit, required this.child})
: super(key: key);
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
widget.onInit();
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
Widget bubbleSpeak(String text, {double? long, Key? textKey}) {
return Bubble(
padding: long == null

View File

@ -1,410 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/queries.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/history.dart';
import 'package:gecko/screens/myWallets/change_pin.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'package:qr_flutter/qr_flutter.dart';
bool _isNewNameValid = false;
class CesiumWalletOptions extends StatelessWidget {
const CesiumWalletOptions(
{Key? key, Key? keyMyWallets, required this.cesiumWallet})
: super(key: key);
final ChestData cesiumWallet;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
ChestProvider _chestProvider =
Provider.of<ChestProvider>(context, listen: false);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final String shortPubkey =
_walletOptions.getShortPubkey(_walletOptions.pubkey.text);
if (_isNewNameValid == false) {
_walletOptions.nameController.text = cesiumWallet.name!;
} else {
cesiumWallet.name = _walletOptions.nameController.text;
}
return WillPopScope(
onWillPop: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = true;
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
return Future<bool>.value(true);
},
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight: 60 * ratio,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = true;
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
}),
title: SizedBox(
height: 22,
child: Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Text(_walletOptions.nameController.text);
}),
),
),
body: Builder(
builder: (ctx) => SafeArea(
child: Column(children: <Widget>[
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xfffafafa),
],
)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
const Spacer(flex: 1),
InkWell(
onTap: () async {
File newAvatar =
await (_walletOptions.changeAvatar());
cesiumWallet.imageFile = newAvatar;
_walletOptions.reloadBuild();
},
child: cesiumWallet.imageFile == null
? Image.asset(
'assets/chests/${cesiumWallet.imageName}',
width: 110,
)
: Image.file(cesiumWallet.imageFile!, width: 110),
),
InkWell(
onTap: () async {
File newAvatar =
await (_walletOptions.changeAvatar());
cesiumWallet.imageFile = newAvatar;
_walletOptions.reloadBuild();
},
child: Column(children: <Widget>[
Image.asset(
'assets/walletOptions/camera.png',
height: 40,
),
const SizedBox(height: 80)
])),
const Spacer(flex: 1),
Column(children: <Widget>[
SizedBox(
width: 260,
child: TextField(
key: const Key('walletName'),
autofocus: false,
focusNode: _walletOptions.walletNameFocus,
enabled: _walletOptions.isEditing,
controller: _walletOptions.nameController,
minLines: 1,
maxLines: 3,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? 27 : 23,
color: Colors.black,
fontWeight: FontWeight.w400,
)),
),
SizedBox(height: isTall ? 5 : 0),
Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': _walletOptions.pubkey.text,
},
// pollInterval: Duration(seconds: 1),
),
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return const Text('Loading');
}
// List repositories = result.data['viewer']['repositories']['nodes'];
String wBalanceUD;
if (result.data!['balance'] == null) {
wBalanceUD = '0.0';
} else {
int wBalanceG1 =
result.data!['balance']['amount'];
int currentUD =
result.data!['currentUd']['amount'];
double wBalanceUDBrut =
wBalanceG1 / currentUD; // .toString();
wBalanceUD = double.parse(
(wBalanceUDBrut).toStringAsFixed(2))
.toString();
}
return Row(children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: _walletOptions.isBalanceBlur
? 6
: 0.001,
sigmaY: _walletOptions.isBalanceBlur
? 5
: 0.001),
child: Text(wBalanceUD,
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black)),
),
Text(' DU',
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black))
]);
// Text(
// '$wBalanceUD DU',
// style: TextStyle(
// fontSize: 20, color: Colors.black),
// );
},
),
const SizedBox(height: 5),
InkWell(
key: const Key('displayBalance'),
onTap: () {
_walletOptions.bluringBalance();
},
child: Image.asset(
_walletOptions.isBalanceBlur
? 'assets/walletOptions/icon_oeuil.png'
: 'assets/walletOptions/icon_oeuil_close.png',
height: 35,
),
),
]),
Column(children: <Widget>[
InkWell(
key: const Key('renameWallet'),
onTap: () async {
_isNewNameValid = _walletOptions.editWalletName(
[cesiumWallet.key, 0],
isCesium: cesiumWallet.isCesium);
await Future.delayed(
const Duration(milliseconds: 30));
_walletOptions.walletNameFocus.requestFocus();
},
child: ClipRRect(
child: Image.asset(
_walletOptions.isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 20,
height: 20),
)),
const SizedBox(
height: 60,
)
]),
const Spacer(flex: 3),
]),
);
}),
SizedBox(height: 4 * ratio),
QrImageWidget(
data: _walletOptions.pubkey.text,
version: QrVersions.auto,
size: isTall ? 300 : 270,
),
SizedBox(height: 15 * ratio),
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(
ClipboardData(text: _walletOptions.pubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 30),
Image.asset(
'assets/walletOptions/key.png',
height: 45,
),
const SizedBox(width: 20),
Text("${shortPubkey.split(':')[0]}:",
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace',
color: Colors.black)),
Text(shortPubkey.split(':')[1],
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
const SizedBox(width: 15),
SizedBox(
height: 40,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 1,
primary: orangeC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
Clipboard.setData(ClipboardData(
text: _walletOptions.pubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: Row(children: <Widget>[
Image.asset(
'assets/walletOptions/copy-white.png',
height: 25,
),
const SizedBox(width: 7),
Text('Copier',
style: TextStyle(
fontSize: 15, color: Colors.grey[50]))
]))),
]))),
SizedBox(height: 10 * ratio),
InkWell(
key: const Key('displayHistory'),
onTap: () {
_historyProvider.nPage = 1;
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HistoryScreen(
pubkey: _walletOptions.pubkey.text);
}),
);
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 30),
Image.asset(
'assets/walletOptions/clock.png',
height: 45,
),
const SizedBox(width: 22),
const Text('Historique des transactions',
style:
TextStyle(fontSize: 20, color: Colors.black)),
]))),
SizedBox(height: 7 * ratio),
InkWell(
key: const Key('changePin'),
onTap: () async {
// await _chestProvider.changePin(context, cesiumWallet);
String? newPin = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ChangePinScreen(
walletName: cesiumWallet.name,
walletProvider: _myWalletProvider,
);
},
),
);
if (newPin != null) _myWalletProvider.pinCode = newPin;
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 31),
Image.asset(
'assets/chests/secret_code.png',
height: 24,
),
const SizedBox(width: 20),
const Text('Changer mon code secret',
style: TextStyle(fontSize: 20, color: Colors.black)),
]),
),
),
SizedBox(height: 7 * ratio),
InkWell(
key: const Key('deleteWallet'),
onTap: () async {
await _chestProvider.deleteChest(context, cesiumWallet);
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 33),
Image.asset(
'assets/walletOptions/trash.png',
height: 45,
),
const SizedBox(width: 21),
const Text(
'Supprimer ce coffre',
style: TextStyle(
fontSize: 20,
color: Color(0xffD80000),
),
),
]),
),
),
]),
),
),
),
);
}
}

View File

@ -2,9 +2,11 @@ import 'package:flutter/material.dart';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/change_pin.dart';
import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'dart:io';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
@ -18,15 +20,16 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
final MyWalletsProvider walletProvider;
Directory? appPath;
TextEditingController newPin = TextEditingController();
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
ChangePinProvider _changePin = Provider.of<ChangePinProvider>(context);
// _walletOptions.changePin(walletName, oldPin);
// _walletOptions.newPin.text = _tmpPin;
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
return WillPopScope(
onWillPop: () {
_changePin.newPin.text = '';
newPin.text = '';
return Future<bool>.value(true);
},
child: Scaffold(
@ -36,7 +39,7 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
_changePin.newPin.text = '';
newPin.text = '';
Navigator.of(context).pop();
}),
title: SizedBox(
@ -49,7 +52,7 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
child: Column(children: <Widget>[
StatefulWrapper(
onInit: () {
_changePin.newPin.text = randomSecretCode(pinLength);
newPin.text = randomSecretCode(pinLength);
},
child: Container(),
),
@ -68,7 +71,7 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
children: <Widget>[
TextField(
enabled: false,
controller: _changePin.newPin,
controller: newPin,
maxLines: 1,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
@ -80,7 +83,7 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
icon: const Icon(Icons.replay),
color: orangeC,
onPressed: () async {
_changePin.newPin.text = randomSecretCode(pinLength);
newPin.text = randomSecretCode(pinLength);
},
),
],
@ -96,12 +99,12 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
onPrimary: Colors.black, // foreground
),
onPressed: () async {
NewWallet? _newWalletFile = await _changePin.changePin(
walletProvider.pinCode,
newCustomPin: _changePin.newPin.text);
_changePin.newPin.text = '';
_changePin.storeNewPinChest(context, _newWalletFile!);
walletProvider.pinCode = _changePin.newPin.text;
final _chest = chestBox.get(configBox.get('currentChest'));
await _sub.changePassword(
_chest!.address!, walletProvider.pinCode, newPin.text);
walletProvider.pinCode = newPin.text;
newPin.text = '';
Navigator.pop(context);
},
child: const Text(
'Confirmer',
@ -116,25 +119,3 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
);
}
}
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({Key? key, required this.onInit, required this.child})
: super(key: key);
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
widget.onInit();
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View File

@ -24,14 +24,15 @@ class ChestOptions extends StatelessWidget {
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight: 60 * ratio,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName('/mywallets'),
);
}),
// leading: IconButton(
// icon: const Icon(Icons.arrow_back, color: Colors.black),
// onPressed: () {
// // Navigator.popUntil(
// // context,
// // ModalRoute.withName('/mywallets'),
// // );
// Navigator.pop(context);
// }),
title: SizedBox(
height: 22,
child: Text(currentChest.name!),

View File

@ -3,6 +3,7 @@ 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/wallets_profiles.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:provider/provider.dart';
@ -11,17 +12,20 @@ import 'package:provider/provider.dart';
// ignore: must_be_immutable
class ChooseWalletScreen extends StatelessWidget {
ChooseWalletScreen({Key? key}) : super(key: key);
ChooseWalletScreen({Key? key, required this.chest, required this.pin})
: super(key: key);
final int chest;
final String pin;
int? _derivation;
List<int?>? _selectedId;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletsProfilesProvider _walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
WalletsProfilesProvider _walletsProfilesProvider =
Provider.of<WalletsProfilesProvider>(context);
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
@ -31,7 +35,7 @@ class ChooseWalletScreen extends StatelessWidget {
)),
body: SafeArea(
child: Stack(children: [
myWalletsTiles(context),
myWalletsTiles(context, chest),
Positioned.fill(
bottom: 60,
child: Align(
@ -46,8 +50,15 @@ class ChooseWalletScreen extends StatelessWidget {
onPrimary: Colors.white, // foreground
),
onPressed: () async {
final resultPay = await _walletsProfilesProvider
.pay(context, derivation: _derivation);
final acc = _sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: ${_walletViewProvider.outputPubkey.text}, amount: ${double.parse(_walletViewProvider.payAmount.text)}, password: $pin");
final resultPay = await _sub.pay(context,
fromAddress: acc.address!,
destAddress: _walletViewProvider.outputPubkey.text,
amount:
double.parse(_walletViewProvider.payAmount.text),
password: pin);
await paymentsResult(context, resultPay);
},
child: const Text(
@ -64,17 +75,19 @@ class ChooseWalletScreen extends StatelessWidget {
));
}
Widget myWalletsTiles(BuildContext context) {
Widget myWalletsTiles(BuildContext context, int? currentChest) {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
_myWalletProvider.getDefaultWallet(currentChest);
_selectedId ??= defaultWallet!.id();
_derivation ??= defaultWallet!.derivation!;
_myWalletProvider.readAllWallets(configBox.get('currentChest'));
_sub.setCurrentWallet(defaultWallet!.address!);
_myWalletProvider.readAllWallets(currentChest);
if (!isWalletsExists) {
return const Text('');
@ -116,6 +129,7 @@ class ChooseWalletScreen extends StatelessWidget {
onTap: () {
_derivation = _repository.derivation!;
_selectedId = _repository.id();
_sub.setCurrentWallet(_repository.address!);
_myWalletProvider.rebuildWidget();
},
child: ClipOvalShadow(
@ -182,6 +196,7 @@ class ChooseWalletScreen extends StatelessWidget {
onTap: () {
_derivation = _repository.derivation!;
_selectedId = _repository.id();
_sub.setCurrentWallet(_repository.address!);
_myWalletProvider.rebuildWidget();
},
)
@ -195,24 +210,28 @@ class ChooseWalletScreen extends StatelessWidget {
}
Future<bool?> paymentsResult(context, String resultPay) {
if (resultPay != "success") log.e(resultPay);
final bool isValid = resultPay == "confirmed";
if (!isValid) log.e(resultPay);
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text(resultPay == "success"
title: Text(isValid
? 'Paiement effecuté avec succès !'
: "Une erreur s'est produite lors du paiement:\n$resultPay"),
content: const SingleChildScrollView(child: Text('')),
actions: <Widget>[
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
onPressed: () async {
isValid
? await Navigator.of(context).pushNamedAndRemoveUntil(
'/',
ModalRoute.withName('/'),
)
: Navigator.pop(context);
},
),
],

View File

@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart';
@ -32,6 +33,7 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
final int? _currentChest = _myWalletProvider.getCurrentChest();
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
_mnemonicController.text = generatedMnemonic!;
return WillPopScope(
@ -53,7 +55,7 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
}),
title: const SizedBox(
height: 22,
child: Text('Enregistrer ce trousseau'),
child: Text('Enregistrer ce coffre'),
)),
body: Center(
child: Column(children: <Widget>[
@ -134,9 +136,16 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
.isAskedWordValid &&
walletName.text != '')
? () async {
_generateWalletProvider.storeHDWChest(
generatedWallet!,
walletName.text,
final address = await _sub.importAccount(
fromMnemonic: true,
mnemonic: _generateWalletProvider
.generatedMnemonic!,
password:
_generateWalletProvider.pin.text,
derivePath: '//2');
await _generateWalletProvider.storeHDWChest(
address,
'Mon portefeuille courant',
context);
_generateWalletProvider.isAskedWordValid =
false;

View File

@ -1,16 +1,13 @@
import 'package:durt/durt.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/myWallets/confirm_wallet_storage.dart';
import 'package:flutter/material.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
import 'package:super_tooltip/super_tooltip.dart';
// ignore: must_be_immutable
class GenerateFastChestScreen extends StatelessWidget {
SuperTooltip? tooltip;
bool hasError = false;
String validPin = 'NO PIN';
String currentText = "";
@ -25,14 +22,11 @@ class GenerateFastChestScreen extends StatelessWidget {
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
Provider.of<GenerateWalletsProvider>(context, listen: false);
if (_generateWalletProvider.mnemonicController.text == '') {
_generateWalletProvider.generateWordList();
_generateWalletProvider.mnemonicController.text =
_generateWalletProvider.generatedMnemonic!;
_generateWalletProvider.pin.text = randomSecretCode(pinLength);
}
_generateWalletProvider.pin.text = kDebugMode && debugPin
? 'AAAAA'
: _generateWalletProvider.changePinCode(reload: false);
return WillPopScope(
onWillPop: () {
@ -52,7 +46,7 @@ class GenerateFastChestScreen extends StatelessWidget {
}),
title: const SizedBox(
height: 22,
child: Text('Générer un trousseau'),
child: Text('Générer un coffre'),
)),
floatingActionButton: SizedBox(
height: 80.0,
@ -61,9 +55,7 @@ class GenerateFastChestScreen extends StatelessWidget {
child: FloatingActionButton(
heroTag: "buttonGenerateWallet",
onPressed: () {
_generateWalletProvider.generateWordList();
_generateWalletProvider.mnemonicController.text =
_generateWalletProvider.generatedMnemonic!;
_generateWalletProvider.reloadBuild();
},
child: SizedBox(
height: 40.0,
@ -79,18 +71,23 @@ class GenerateFastChestScreen extends StatelessWidget {
const SizedBox(height: 20),
toolTips(_toolTipSentence, 'Phrase de restauration:',
"Notez et gardez cette phrase précieusement sur un papier, elle vous servira à restaurer votre portefeuille sur un autre appareil"),
TextField(
enabled: false,
controller: _generateWalletProvider.mnemonicController,
maxLines: 3,
textAlign: TextAlign.center,
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(15.0),
),
style: const TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.w400)),
Consumer<GenerateWalletsProvider>(builder: (context, _gWP, _) {
return FutureBuilder(
future: _gWP.generateWordList(context),
builder: (BuildContext context, AsyncSnapshot<List> _data) {
if (!_data.hasData) {
return const Text('');
} else {
return Text(_gWP.generatedMnemonic!,
maxLines: 3,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.w400));
}
});
}),
const SizedBox(height: 8),
toolTips(_toolTipSecret, 'Code secret:',
"Retenez bien votre code secret, il vous sera demandé à chaque paiement, ainsi que pour configurer votre portefeuille"),
@ -112,7 +109,7 @@ class GenerateFastChestScreen extends StatelessWidget {
icon: const Icon(Icons.replay),
color: orangeC,
onPressed: () {
_generateWalletProvider.changePinCode(reload: true);
_generateWalletProvider.changePinCode(reload: false);
},
),
],
@ -128,11 +125,6 @@ class GenerateFastChestScreen extends StatelessWidget {
? () async {
_generateWalletProvider.nbrWord =
_generateWalletProvider.getRandomInt();
_generateWalletProvider.actualWallet = await Dewif()
.generateDewif(
_generateWalletProvider.generatedMnemonic!,
_generateWalletProvider.pin.text,
lang: appLang);
await Navigator.push(
context,
MaterialPageRoute(builder: (context) {
@ -145,20 +137,20 @@ class GenerateFastChestScreen extends StatelessWidget {
);
}
: null,
child: const Text('Enregistrer ce trousseau',
child: const Text('Enregistrer ce coffre',
style: TextStyle(fontSize: 20))),
const SizedBox(height: 20),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PrintWallet(
_generateWalletProvider.generatedMnemonic);
}),
);
},
child: const Icon(Icons.print))
// GestureDetector(
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return PrintWallet(
// _generateWalletProvider.generatedMnemonic);
// }),
// );
// },
// child: const Icon(Icons.print))
]),
),
),
@ -201,30 +193,30 @@ class GenerateFastChestScreen extends StatelessWidget {
}
}
// ignore: must_be_immutable
class PrintWallet extends StatelessWidget {
const PrintWallet(this.sentence, {Key? key}) : super(key: key);
// // ignore: must_be_immutable
// class PrintWallet extends StatelessWidget {
// const PrintWallet(this.sentence, {Key? key}) : super(key: key);
final String? sentence;
// final String? sentence;
@override
Widget build(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
Navigator.pop(context);
}),
toolbarHeight: 60 * ratio,
title: const Text('Imprimer ce trousseau')),
body: PdfPreview(
build: (format) => _generateWalletProvider.printWallet(sentence),
),
),
);
}
}
// @override
// Widget build(BuildContext context) {
// GenerateWalletsProvider _generateWalletProvider =
// Provider.of<GenerateWalletsProvider>(context);
// return MaterialApp(
// home: Scaffold(
// appBar: AppBar(
// leading: IconButton(
// icon: const Icon(Icons.arrow_back, color: Colors.white),
// onPressed: () {
// Navigator.pop(context);
// }),
// toolbarHeight: 60 * ratio,
// title: const Text('Imprimer ce coffre')),
// body: PdfPreview(
// build: (format) => _generateWalletProvider.printWallet(sentence),
// ),
// ),
// );
// }
// }

View File

@ -1,244 +0,0 @@
import 'dart:async';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart';
class ImportWalletScreen extends StatelessWidget {
const ImportWalletScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GlobalKey _toolTipSecret = GlobalKey();
Timer? _debounce;
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
_generateWalletProvider.pin.text = randomSecretCode(pinLength);
return WillPopScope(
onWillPop: () {
_generateWalletProvider.resetCesiumImportView();
return Future<bool>.value(true);
},
child: Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
_generateWalletProvider.resetCesiumImportView();
Navigator.of(context).pop();
}),
title: const SizedBox(
height: 22,
child: Text('Importer un portefeuille'),
)),
body: Builder(
builder: (ctx) => SafeArea(
child: Column(children: <Widget>[
const SizedBox(height: 20),
Consumer<GenerateWalletsProvider>(
builder: (context, walletProvider, _) {
return TextFormField(
autofocus: true,
onChanged: (text) {
if (_debounce?.isActive ?? false) {
_debounce!.cancel();
}
_debounce = Timer(const Duration(milliseconds: 600), () {
walletProvider
.generateCesiumWalletPubkey(
text, walletProvider.cesiumPWD.text)
.then((value) {
walletProvider.canImport = true;
walletProvider.reloadBuild();
});
});
},
keyboardType: TextInputType.text,
controller: walletProvider.cesiumID,
obscureText: !walletProvider
.isCesiumIDVisible, //This will obscure text dynamically
decoration: InputDecoration(
hintText: 'Entrez votre identifiant Cesium',
suffixIcon: IconButton(
icon: Icon(
walletProvider.isCesiumIDVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.black,
),
onPressed: () {
walletProvider.cesiumIDisVisible();
},
),
),
);
}),
const SizedBox(height: 15),
Consumer<GenerateWalletsProvider>(
builder: (context, walletProvider, _) {
return TextFormField(
onChanged: (text) {
if (_debounce?.isActive ?? false) {
_debounce!.cancel();
}
_debounce = Timer(const Duration(milliseconds: 600), () {
walletProvider
.generateCesiumWalletPubkey(
walletProvider.cesiumID.text, text)
.then((value) {
walletProvider.canImport = true;
walletProvider.reloadBuild();
});
});
},
keyboardType: TextInputType.text,
controller: walletProvider.cesiumPWD,
obscureText: !walletProvider
.isCesiumPWDVisible, //This will obscure text dynamically
decoration: InputDecoration(
hintText: 'Entrez votre mot de passe Cesium',
suffixIcon: IconButton(
icon: Icon(
walletProvider.isCesiumPWDVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.black,
),
onPressed: () {
walletProvider.cesiumPWDisVisible();
},
),
),
);
}),
const SizedBox(height: 15),
GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(
text: _generateWalletProvider.cesiumPubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: Consumer<GenerateWalletsProvider>(
builder: (context, walletProvider, _) {
return Text(
_generateWalletProvider.cesiumPubkey.text,
style: const TextStyle(
fontSize: 14.0,
color: Colors.black,
fontWeight: FontWeight.bold,
fontFamily: 'Monospace'),
);
}),
),
const SizedBox(height: 20),
toolTips(_toolTipSecret, 'Code secret:',
"Retenez bien votre code secret, il vous sera demandé à chaque paiement, ainsi que pour configurer votre portefeuille"),
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(
enabled: false,
controller: _generateWalletProvider.pin,
maxLines: 1,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
style: const TextStyle(
fontSize: 30.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
IconButton(
icon: const Icon(Icons.replay),
color: orangeC,
onPressed: () {
_generateWalletProvider.changePinCode(reload: true);
},
),
],
),
const SizedBox(height: 30),
Consumer<GenerateWalletsProvider>(
builder: (context, walletProvider, _) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: walletProvider.canImport
? () async {
final chestKey =
await walletProvider.importCesiumWallet();
_myWalletProvider.rebuildWidget();
await Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) {
return UnlockingWallet(
wallet: WalletData(chest: chestKey),
action: "mywallets",
);
}),
ModalRoute.withName('/'),
);
_generateWalletProvider.resetCesiumImportView();
}
: null,
child: const Text(
'Importer ce portefeuille Cesium',
style: TextStyle(fontSize: 20),
),
);
}),
]),
),
),
),
);
}
Widget toolTips(_key, _text, _message) {
return GestureDetector(
onTap: () {
final dynamic _toolTip = _key.currentState;
_toolTip.ensureTooltipVisible();
},
child: Tooltip(
padding: const EdgeInsets.all(10),
key: _key,
showDuration: const Duration(seconds: 5),
message: _message,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(width: 20),
Column(children: <Widget>[
SizedBox(
width: 30,
height: 25,
child:
Icon(Icons.info_outline, size: 22, color: orangeC)),
const SizedBox(height: 1)
]),
Text(
_text,
style: TextStyle(
fontSize: 15.0,
color: Colors.grey[600],
fontWeight: FontWeight.w400),
),
const SizedBox(width: 45)
])));
}
}

View File

@ -3,8 +3,9 @@ import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/11.dart';
import 'package:gecko/screens/onBoarding/9.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
@ -15,14 +16,19 @@ class RestoreChest extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
GenerateWalletsProvider genW =
Provider.of<GenerateWalletsProvider>(context, listen: false);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
generateWalletProvider.actualWallet = null;
genW.actualWallet = null;
if (genW.isSentenceComplete(context)) {
genW.generatedMnemonic =
'${genW.cellController0.text} ${genW.cellController1.text} ${genW.cellController2.text} ${genW.cellController3.text} ${genW.cellController4.text} ${genW.cellController5.text} ${genW.cellController6.text} ${genW.cellController7.text} ${genW.cellController8.text} ${genW.cellController9.text} ${genW.cellController10.text} ${genW.cellController11.text}';
}
return WillPopScope(
onWillPop: () {
generateWalletProvider.resetImportView();
genW.resetImportView();
return Future<bool>.value(true);
},
child: Scaffold(
@ -31,7 +37,7 @@ class RestoreChest extends StatelessWidget {
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
generateWalletProvider.resetImportView();
genW.resetImportView();
Navigator.of(context).pop();
}),
title: const SizedBox(
@ -48,32 +54,32 @@ class RestoreChest extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController0),
arrayCell(context, generateWalletProvider.cellController1),
arrayCell(context, generateWalletProvider.cellController2),
arrayCell(context, generateWalletProvider.cellController3),
arrayCell(context, genW.cellController0),
arrayCell(context, genW.cellController1),
arrayCell(context, genW.cellController2),
arrayCell(context, genW.cellController3),
]),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController4),
arrayCell(context, generateWalletProvider.cellController5),
arrayCell(context, generateWalletProvider.cellController6),
arrayCell(context, generateWalletProvider.cellController7),
arrayCell(context, genW.cellController4),
arrayCell(context, genW.cellController5),
arrayCell(context, genW.cellController6),
arrayCell(context, genW.cellController7),
]),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController8),
arrayCell(context, generateWalletProvider.cellController9),
arrayCell(context, generateWalletProvider.cellController10),
arrayCell(context, generateWalletProvider.cellController11),
arrayCell(context, genW.cellController8),
arrayCell(context, genW.cellController9),
arrayCell(context, genW.cellController10),
arrayCell(context, genW.cellController11),
]),
]),
// const Spacer(),
if (generateWalletProvider.isSentenceComplete(context))
if (genW.isSentenceComplete(context))
Expanded(
child: Align(
alignment: Alignment.center,
@ -87,12 +93,13 @@ class RestoreChest extends StatelessWidget {
onPrimary: Colors.white, // foreground
),
onPressed: () async {
if (await generateWalletProvider.isSentenceValid()) {
generateWalletProvider.resetImportView();
if (await _sub.isMnemonicValid(genW.generatedMnemonic!)) {
genW.resetImportView();
await Navigator.push(
context,
FaderTransition(
page: const OnboardingStepThirteen(), isFast: true),
page: const OnboardingStepThirteen(),
isFast: true),
);
} else {
await badMnemonicPopup(context);
@ -107,6 +114,30 @@ class RestoreChest extends StatelessWidget {
),
// SizedBox(height: isTall ? 80 : 80),
))
else
Column(children: [
const SizedBox(height: 20),
SizedBox(
width: 150,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
genW.pasteMnemonic(context);
},
child: const Text(
'Coller depuis le\npresse-papier',
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.w400),
),
),
)
])
]),
),
),
@ -168,7 +199,7 @@ class RestoreChest extends StatelessWidget {
return AlertDialog(
title: const Text('Phrase incorrecte'),
content: const Text(
'Votre phrase de restauration semble incorrecte, veuillez la corriger.'),
'Votre phrase de restauration semble incorrecte, les mots ne sont pas dans le bon ordre.\nVeuillez la corriger.'),
actions: <Widget>[
TextButton(
child: const Text("OK"),

View File

@ -1,13 +1,13 @@
// ignore_for_file: avoid_print
import 'dart:async';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/cesium_wallet_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/screens/myWallets/choose_wallet.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
@ -21,6 +21,8 @@ class UnlockingWallet extends StatelessWidget {
{Key? keyUnlockWallet, required this.wallet, required this.action})
: super(key: keyUnlockWallet);
WalletData? wallet;
late int currentChestNumber;
late ChestData currentChest;
String action;
// ignore: close_sinks
@ -34,17 +36,11 @@ class UnlockingWallet extends StatelessWidget {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context);
final double statusBarHeight = MediaQuery.of(context).padding.top;
// final double statusBarHeight = MediaQuery.of(context).padding.top;
int _pinLenght;
ChestData currentChest = chestBox.get(configBox.get('currentChest'))!;
if (currentChest.isCesium!) {
_pinLenght = _walletOptions.getPinLenght(currentChest.dewif);
wallet = WalletData(derivation: -1, chest: currentChest.key);
} else {
_pinLenght = _walletOptions.getPinLenght(wallet!.number);
}
currentChestNumber = configBox.get('currentChest');
currentChest = chestBox.get(currentChestNumber)!;
int _pinLenght = _walletOptions.getPinLenght(wallet!.number);
errorController = StreamController<ErrorAnimationType>();
return Scaffold(
@ -55,7 +51,7 @@ class UnlockingWallet extends StatelessWidget {
children: <Widget>[
Stack(children: <Widget>[
Positioned(
top: statusBarHeight + 10,
top: 10, //statusBarHeight + 10,
left: 15,
child: Builder(
builder: (context) => IconButton(
@ -63,7 +59,7 @@ class UnlockingWallet extends StatelessWidget {
icon: const Icon(
Icons.arrow_back,
color: Colors.black,
size: 25,
size: 30,
),
onPressed: () => Navigator.pop(context),
),
@ -106,7 +102,7 @@ class UnlockingWallet extends StatelessWidget {
fontWeight: FontWeight.w400),
)),
SizedBox(height: 40 * ratio),
pinForm(context, _pinLenght, currentChest),
pinForm(context, _pinLenght),
SizedBox(height: 3 * ratio),
InkWell(
key: const Key('chooseChest'),
@ -137,7 +133,7 @@ class UnlockingWallet extends StatelessWidget {
));
}
Widget pinForm(context, _pinLenght, ChestData currentChest) {
Widget pinForm(context, _pinLenght) {
// var _walletPin = '';
// ignore: close_sinks
StreamController<ErrorAnimationType> errorController =
@ -147,8 +143,8 @@ class UnlockingWallet extends StatelessWidget {
Provider.of<WalletOptionsProvider>(context);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
FocusNode pinFocus = FocusNode();
@ -201,30 +197,12 @@ class UnlockingWallet extends StatelessWidget {
],
onCompleted: (_pin) async {
log.d("Completed");
_myWalletProvider.pinCode = _pin;
_myWalletProvider.pinCode = _pin.toUpperCase();
if (currentChest.isCesium!) {
try {
String _localDewif = chestBox.get(wallet!.chest)!.dewif!;
final cesiumWallet =
CesiumWallet.fromDewif(_localDewif, _pin.toUpperCase());
_walletOptions.pubkey.text = cesiumWallet.pubkey;
_myWalletProvider.cesiumSeed = cesiumWallet.seed;
_myWalletProvider.mnemonic = 'cesium';
} catch (e) {
log.e(e);
_myWalletProvider.mnemonic = 'bad';
}
} else {
_myWalletProvider.mnemonic = _myWalletProvider.dewifToMnemonic(
context, wallet!, _pin.toUpperCase());
}
// final String? resultWallet = _walletOptions.readLocalWallet(
// context, wallet!, _pin.toUpperCase(), _pinLenght);
// _myWalletProvider.pinCode = _pin.toUpperCase();
_myWalletProvider.pinLenght = _pinLenght;
final isValid = await _sub.checkPassword(
currentChest.address!, _pin.toUpperCase());
if (_myWalletProvider.mnemonic == 'bad') {
if (!isValid) {
await Future.delayed(const Duration(milliseconds: 50));
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
@ -235,32 +213,20 @@ class UnlockingWallet extends StatelessWidget {
} else {
pinColor = Colors.green[400];
if (action == "mywallets") {
currentChest.isCesium!
? Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return CesiumWalletOptions(
cesiumWallet: currentChest);
}),
).then((value) => _myWalletProvider.mnemonic = '')
: Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
).then((value) => _myWalletProvider.cesiumSeed.clear());
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
);
} else if (action == "pay") {
if (currentChest.isCesium!) {
final resultPay = await _historyProvider.pay(context);
await paymentsResult(context, resultPay);
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChooseWalletScreen();
}),
);
}
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChooseWalletScreen(
chest: currentChestNumber, pin: _pin.toUpperCase());
}),
);
}
}
},

View File

@ -1,6 +1,4 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/my_wallets.dart';
@ -27,16 +25,18 @@ class WalletOptions extends StatelessWidget {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
log.d(_walletOptions.pubkey.text);
log.d(_walletOptions.address.text);
final int _currentChest = _myWalletProvider.getCurrentChest()!;
log.d("Wallet options: $_currentChest:${wallet.number}");
// final currentWallet = _myWalletProvider.getDefaultWallet(_currentChest);
// log.d(_walletOptions.getAddress(_currentChest, 3));
log.d("Wallet options: $_currentChest:${wallet.derivation}");
return WillPopScope(
onWillPop: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = true;
_walletOptions.isBalanceBlur = false;
Navigator.pop(context);
return Future<bool>.value(true);
},
@ -49,7 +49,7 @@ class WalletOptions extends StatelessWidget {
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = true;
_walletOptions.isBalanceBlur = false;
Navigator.pop(context);
}),
title: SizedBox(
@ -89,15 +89,15 @@ class WalletOptions extends StatelessWidget {
Column(children: <Widget>[
walletName(walletProvider, _walletOptions),
SizedBox(height: isTall ? 5 : 0),
balance(walletProvider),
balance(context, walletProvider.address.text, 20),
]),
const Spacer(flex: 3),
]),
);
}),
SizedBox(height: 4 * ratio),
SizedBox(height: 10 * ratio),
QrImageWidget(
data: _walletOptions.pubkey.text,
data: _walletOptions.address.text,
version: QrVersions.auto,
size: isTall ? 300 : 270,
),
@ -129,8 +129,10 @@ class WalletOptions extends StatelessWidget {
children: <Widget>[
InkWell(
onTap: () async {
File newAvatar = await (walletProvider.changeAvatar());
wallet.imageFile = newAvatar;
wallet.imageFile = await (walletProvider.changeAvatar());
if (wallet.imageFile != null) {
walletBox.put(wallet.key, wallet);
}
walletProvider.reloadBuild();
},
child: wallet.imageFile == null
@ -148,8 +150,7 @@ class WalletOptions extends StatelessWidget {
top: 0,
child: InkWell(
onTap: () async {
File newAvatar = await (walletProvider.changeAvatar());
wallet.imageFile = newAvatar;
wallet.imageFile = await (walletProvider.changeAvatar());
walletProvider.reloadBuild();
},
child: Image.asset(
@ -220,54 +221,14 @@ class WalletOptions extends StatelessWidget {
);
}
Widget balance(WalletOptionsProvider walletProvider) {
return Column(children: <Widget>[
FutureBuilder(
future: walletProvider.getBalance(walletProvider.pubkey.text),
builder: (BuildContext context, AsyncSnapshot<num?> _balance) {
if (_balance.connectionState != ConnectionState.done ||
_balance.hasError) {
return Text('',
style: TextStyle(
fontSize: isTall ? 20 : 18,
));
}
return ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: walletProvider.isBalanceBlur ? 6 : 0,
sigmaY: walletProvider.isBalanceBlur ? 5 : 0),
child: Text(
_balance.data.toString() + ' Ğ1',
style: TextStyle(
fontSize: isTall ? 20 : 18,
),
),
);
}),
const SizedBox(height: 5),
InkWell(
key: const Key('displayBalance'),
onTap: () {
walletProvider.bluringBalance();
},
child: Image.asset(
walletProvider.isBalanceBlur
? 'assets/walletOptions/icon_oeuil.png'
: 'assets/walletOptions/icon_oeuil_close.png',
height: 35,
),
),
]);
}
Widget pubkeyWidget(WalletOptionsProvider walletProvider, BuildContext ctx) {
final String shortPubkey =
walletProvider.getShortPubkey(walletProvider.pubkey.text);
walletProvider.getShortPubkey(walletProvider.address.text);
return GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(text: walletProvider.pubkey.text));
walletProvider.snackCopyKey(ctx);
Clipboard.setData(ClipboardData(text: walletProvider.address.text));
snackCopyKey(ctx);
},
child: SizedBox(
height: 50,
@ -303,8 +264,8 @@ class WalletOptions extends StatelessWidget {
),
onPressed: () {
Clipboard.setData(
ClipboardData(text: walletProvider.pubkey.text));
walletProvider.snackCopyKey(ctx);
ClipboardData(text: walletProvider.address.text));
snackCopyKey(ctx);
},
child: Row(children: <Widget>[
Image.asset(
@ -336,7 +297,7 @@ class WalletOptions extends StatelessWidget {
context,
MaterialPageRoute(builder: (context) {
return HistoryScreen(
pubkey: walletProvider.pubkey.text,
pubkey: walletProvider.address.text,
avatar: wallet.imageFile == null
? Image.asset(
'assets/avatars/${wallet.imageName}',
@ -422,7 +383,7 @@ class WalletOptions extends StatelessWidget {
onTap: !walletProvider.isDefaultWallet
? () async {
await walletProvider.deleteWallet(context, wallet);
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_myWalletProvider.listWallets =
_myWalletProvider.readAllWallets(_currentChest);
_myWalletProvider.rebuildWidget();

View File

@ -1,4 +1,3 @@
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
@ -55,7 +54,7 @@ class WalletsHome extends StatelessWidget {
backgroundColor: const Color(0xffFFD58D),
),
body: SafeArea(
child: myWalletsTiles(context),
child: myWalletsTiles(context, _currentChestNumber!),
),
),
);
@ -132,7 +131,7 @@ class WalletsHome extends StatelessWidget {
]);
}
Widget myWalletsTiles(BuildContext context) {
Widget myWalletsTiles(BuildContext context, int _currentChestNumber) {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
WalletOptionsProvider _walletOptions =
@ -182,9 +181,8 @@ class WalletsHome extends StatelessWidget {
onTap: () {
// _walletOptions.readLocalWallet(context, _repository,
// _myWalletProvider.pinCode, pinLength);
_walletOptions.pubkey.text =
HdWallet.fromMnemonic(_myWalletProvider.mnemonic)
.getPubkey(_repository.derivation!);
_walletOptions.getAddress(
_currentChestNumber, _repository.derivation!);
Navigator.push(
context,
SmoothTransition(
@ -275,10 +273,8 @@ class WalletsHome extends StatelessWidget {
// _repository,
// _myWalletProvider.pinCode,
// pinLength);
_walletOptions.pubkey.text =
HdWallet.fromMnemonic(
_myWalletProvider.mnemonic)
.getPubkey(_repository.derivation!);
_walletOptions.getAddress(
_currentChestNumber, _repository.derivation!);
Navigator.push(
context,
SmoothTransition(

View File

@ -1,112 +0,0 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
import 'package:gecko/screens/onBoarding/1.dart';
class NoKeyChainScreen extends StatelessWidget {
const NoKeyChainScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
// backgroundColor: Colors.white,
// appBar: GeckoSpeechAppBar('Mes portefeuilles'),
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(context, 'Mes portefeuilles', 0),
common.bubbleSpeak(
"Je ne connais pour linstant aucun de vos portefeuilles.\n\nVous pouvez en créer un nouveau, ou bien importer un portefeuille Cesium existant.",
textKey: const Key('textOnboarding')),
const SizedBox(height: 90),
Container(
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
key: const Key('goStep1'),
splashColor: orangeC, // inkwell color
child: const Padding(
padding: EdgeInsets.all(8),
child: Image(
image: AssetImage('assets/onBoarding/wallet.png'),
height: 90)),
onTap: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepOne(), isFast: true));
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(2.0, 2.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 15),
const Text(
"Créer un nouveau\nportefeuille",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w500),
),
const SizedBox(height: 70),
Container(
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
splashColor: orangeC, // inkwell color
child: Padding(
padding: const EdgeInsets.all(12),
child:
// Image(
// image: AssetImage('assets/cesium_bw3.png'),
// height: 60),
SvgPicture.asset('assets/cesium_small.svg',
semanticsLabel: 'Cesium Logo', height: 48),
),
onTap: () {
Navigator.push(context,
SlideLeftRoute(page: const ImportWalletScreen()));
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(2.0, 2.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 10),
const Text(
"Importer un\nportefeuille Cesium",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black, fontSize: 13),
)
]),
));
}
}

View File

@ -1,63 +1,47 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/2.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepOne extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 1;
OnboardingStepOne({Key? key}) : super(key: key);
const OnboardingStepOne({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Nouveau portefeuilles', progress),
common.bubbleSpeak(
"Il semblerait que vous nayez pas encore de trousseau.\n\nUn trousseau vous permet de gérer un ou plusieurs portefeuilles.",
textKey: const Key('step1')),
const SizedBox(height: 90),
Image.asset(
'assets/onBoarding/keys-and-wallets-horizontal.png',
height: 200,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep2'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepTwo(), isFast: true));
},
child: const Text('Créer mon trousseau',
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 80),
]),
));
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Nouveau portefeuille',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(
text: 'Gecko fabrique votre portefeuille à partir dune '),
const TextSpan(
text: 'phrase de restauration',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text:
'. Elle est un peu comme le plan qui permet de construire votre portefeuille.'),
],
'fabrication-de-portefeuille.png',
'>',
const OnboardingStepTwo(),
0),
),
);
}
}

View File

@ -1,64 +1,167 @@
// ignore_for_file: file_names
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.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/common_elements.dart';
import 'package:gecko/screens/onBoarding/11.dart';
import 'package:gecko/screens/onBoarding/11_congratulations.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepTwelve extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 9;
class OnboardingStepFourteen extends StatelessWidget {
OnboardingStepFourteen({
Key? validationKey,
}) : super(key: validationKey);
OnboardingStepTwelve({Key? key}) : super(key: key);
final formKey = GlobalKey<FormState>();
Color? pinColor = const Color(0xFFA4B600);
bool hasError = false;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context);
CommonElements common = CommonElements();
final int _pinLenght = _generateWalletProvider.pin.text.length;
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Mon code secret',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Si un jour vous changez de téléphone, votre code secret sera différent, mais il vous suffira de me redonner votre phrase de restauration pour recréer votre trousseau.",
textKey: const Key('step10'),
),
const SizedBox(height: 10),
Image.asset(
'assets/onBoarding/plusieurs-codes-secrets-un-trousseau.png',
height: isTall ? 410 : 380,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep11'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: const OnboardingStepThirteen(),
isFast: true),
);
},
child: const Text("Générer le code secret",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 80),
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(9),
SizedBox(height: isTall ? 40 : 20),
common.buildText(<TextSpan>[
TextSpan(
text:
"Gecko va vérifier avec vous si vous avez bien mémorisé votre code secret.\n\nTapez votre code secret dans le champ ci-dessous pour vérifier que vous lavez bien noté.",
style: TextStyle(fontSize: 16 * ratio))
]),
SizedBox(height: isTall ? 80 : 20),
pinForm(context, _walletOptions, _pinLenght, 1, 2)
]),
));
}
Widget pinForm(context, WalletOptionsProvider _walletOptions, _pinLenght,
int _walletNbr, int _derivation) {
// var _walletPin = '';
// ignore: close_sinks
StreamController<ErrorAnimationType> errorController =
StreamController<ErrorAnimationType>();
TextEditingController _enterPin = TextEditingController();
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final int? _currentChest = _myWalletProvider.getCurrentChest();
return Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
child: PinCodeTextField(
key: const Key('formKey2'),
autoFocus: true,
appContext: context,
pastedTextStyle: TextStyle(
color: Colors.green.shade600,
fontWeight: FontWeight.bold,
),
length: _pinLenght,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
validator: (v) {
if (v!.length < _pinLenght) {
return "Votre code PIN fait $_pinLenght caractères";
} else {
return null;
}
},
pinTheme: PinTheme(
activeColor: pinColor,
borderWidth: 4,
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5),
fieldHeight: 60,
fieldWidth: 50,
activeFillColor: hasError ? Colors.blueAccent : Colors.black,
),
cursorColor: Colors.black,
animationDuration: const Duration(milliseconds: 300),
textStyle: const TextStyle(fontSize: 20, height: 1.6),
backgroundColor: const Color(0xffF9F9F1),
enableActiveFill: false,
errorAnimationController: errorController,
controller: _enterPin,
keyboardType: TextInputType.text,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),
color: Colors.black12,
blurRadius: 10,
)
],
onCompleted: (_pin) async {
_myWalletProvider.pinCode = _pin.toUpperCase();
_myWalletProvider.pinLenght = _pinLenght;
log.d(_pin + ' || ' + _generateWalletProvider.pin.text);
if (_pin.toUpperCase() == _generateWalletProvider.pin.text) {
pinColor = Colors.green[500];
final address = await _sub.importAccount(
fromMnemonic: true,
mnemonic: _generateWalletProvider.generatedMnemonic!,
derivePath: '//2',
password: _generateWalletProvider.pin.text);
await _generateWalletProvider.storeHDWChest(
address, 'Mon portefeuille courant', context);
_myWalletProvider.readAllWallets(_currentChest);
// scheduleMicrotask(() {
// _walletOptions.reloadBuild();
_myWalletProvider.rebuildWidget();
// });
_generateWalletProvider.generatedMnemonic = '';
Navigator.push(
context,
FaderTransition(
page: const OnboardingStepFiveteen(), isFast: false),
);
} else {
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
hasError = true;
pinColor = Colors.red[600];
_walletOptions.reloadBuild();
}
},
onChanged: (value) {
if (pinColor != const Color(0xFFA4B600)) {
pinColor = const Color(0xFFA4B600);
}
},
)),
);
}
}

View File

@ -1,118 +0,0 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/12.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepThirteen extends StatelessWidget {
final int progress = 10;
const OnboardingStepThirteen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
// MyWalletsProvider myWalletProvider =
// Provider.of<MyWalletsProvider>(context);
CommonElements common = CommonElements();
_generateWalletProvider.pin.text =
_generateWalletProvider.changePinCode(reload: false);
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeakRich(
<TextSpan>[
const TextSpan(
text:
"Et voilà votre code secret !\n\nMémorisez-le ou notez-le, car il vous sera demandé "),
const TextSpan(
text: 'à chaque fois',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text:
" que vous voudrez effectuer un paiement sur cet appareil."),
],
textKey: const Key('step11'),
),
const SizedBox(height: 100),
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(
key: const Key('generatedPin'),
enabled: false,
controller: _generateWalletProvider.pin,
maxLines: 1,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
style: const TextStyle(
letterSpacing: 5,
fontSize: 35.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
IconButton(
icon: const Icon(Icons.replay),
color: orangeC,
onPressed: () {
_generateWalletProvider.changePinCode(reload: true);
},
),
],
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('changeSecretCode'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: const Color(0xffFFD58D),
onPrimary: Colors.black, // foreground
),
onPressed: () {
_generateWalletProvider.changePinCode(reload: true);
},
child: const Text("Choisir un autre code secret",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 25),
SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep12'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () async {
_generateWalletProvider.isAskedWordValid = false;
_generateWalletProvider.askedWordColor = Colors.black;
Navigator.push(
context,
FaderTransition(
page: OnboardingStepFourteen(), isFast: true),
);
},
child: const Text("J'ai noté mon code secret",
style: TextStyle(fontSize: 20))),
),
const SizedBox(height: 80),
]),
));
}
}

View File

@ -0,0 +1,78 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
// ignore: must_be_immutable
class OnboardingStepFiveteen extends StatelessWidget {
const OnboardingStepFiveteen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Cest tout bon !',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
const SizedBox(height: 40),
common.buildText(<TextSpan>[
const TextSpan(
text:
"Top !\n\nVotre coffre votre premier portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
)
]),
SizedBox(height: isTall ? 20 : 10),
Image.asset(
'assets/onBoarding/gecko-clin.gif',
height: isTall ? 400 : 300,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: finishButton(context)),
),
const SizedBox(height: 40),
]),
));
}
}
Widget finishButton(BuildContext context) {
return SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
key: const Key('goWalletHome'),
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
ModalRoute.withName('/'),
);
},
child: const Text("Accéder à mon coffre",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600))),
);
}

View File

@ -1,153 +0,0 @@
// ignore_for_file: file_names
import 'dart:async';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/13_congratulations.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepFourteen extends StatelessWidget {
OnboardingStepFourteen({
Key? validationKey,
}) : super(key: validationKey);
final int progress = 11;
final formKey = GlobalKey<FormState>();
Color? pinColor = const Color(0xFFA4B600);
bool hasError = false;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context);
CommonElements common = CommonElements();
final int _pinLenght = _generateWalletProvider.pin.text.length;
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Avez-vous bien mémorisé votre code secret ?\n\nVérifions ça ensemble !\n\nTapez votre code secret dans le champ ci-dessous (après cest fini, promis-juré-gecko).",
textKey: const Key('step12'),
),
SizedBox(height: isTall ? 80 : 10),
pinForm(context, _walletOptions, _pinLenght, 1, 3)
]),
));
}
Widget pinForm(context, WalletOptionsProvider _walletOptions, _pinLenght,
int _walletNbr, int _derivation) {
// var _walletPin = '';
// ignore: close_sinks
StreamController<ErrorAnimationType> errorController =
StreamController<ErrorAnimationType>();
TextEditingController _enterPin = TextEditingController();
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
final int? _currentChest = _myWalletProvider.getCurrentChest();
return Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
child: PinCodeTextField(
key: const Key('formKey2'),
autoFocus: true,
appContext: context,
pastedTextStyle: TextStyle(
color: Colors.green.shade600,
fontWeight: FontWeight.bold,
),
length: _pinLenght,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
validator: (v) {
if (v!.length < _pinLenght) {
return "Votre code PIN fait $_pinLenght caractères";
} else {
return null;
}
},
pinTheme: PinTheme(
activeColor: pinColor,
borderWidth: 4,
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5),
fieldHeight: 60,
fieldWidth: 50,
activeFillColor: hasError ? Colors.blueAccent : Colors.black,
),
cursorColor: Colors.black,
animationDuration: const Duration(milliseconds: 300),
textStyle: const TextStyle(fontSize: 20, height: 1.6),
backgroundColor: const Color(0xffF9F9F1),
enableActiveFill: false,
errorAnimationController: errorController,
controller: _enterPin,
keyboardType: TextInputType.text,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),
color: Colors.black12,
blurRadius: 10,
)
],
onCompleted: (_pin) async {
_myWalletProvider.pinCode = _pin.toUpperCase();
_myWalletProvider.pinLenght = _pinLenght;
log.d(_pin + ' || ' + _generateWalletProvider.pin.text);
if (_pin.toUpperCase() == _generateWalletProvider.pin.text) {
pinColor = Colors.green[500];
NewWallet generatedWallet = await Dewif().generateDewif(
_generateWalletProvider.generatedMnemonic!,
_generateWalletProvider.pin.text,
lang: appLang);
await _generateWalletProvider.storeHDWChest(
generatedWallet, 'Mon portefeuille courant', context);
_myWalletProvider.readAllWallets(_currentChest);
// scheduleMicrotask(() {
// _walletOptions.reloadBuild();
_myWalletProvider.rebuildWidget();
// });
_generateWalletProvider.generatedMnemonic = '';
Navigator.push(
context,
FaderTransition(
page: OnboardingStepFiveteen(), isFast: false),
);
} else {
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
hasError = true;
pinColor = Colors.red[600];
_walletOptions.reloadBuild();
}
},
onChanged: (value) {
if (pinColor != const Color(0xFFA4B600)) {
pinColor = const Color(0xFFA4B600);
}
},
)),
);
}
}

View File

@ -1,67 +0,0 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
// ignore: must_be_immutable
class OnboardingStepFiveteen extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 12;
OnboardingStepFiveteen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Top !\n\nVotre trousseau de clef et votre portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
textKey: const Key('step13'),
),
SizedBox(height: isTall ? 20 : 10),
Image.asset(
'assets/onBoarding/gecko-clin.gif',
height: isTall ? 400 : 300,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goWalletHome'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
ModalRoute.withName('/'),
);
},
child: const Text("Accéder à mes portefeuilles",
style: TextStyle(fontSize: 20))),
),
),
),
const SizedBox(height: 80),
]),
));
}
}

View File

@ -5,16 +5,9 @@ import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/3.dart';
// import 'package:gecko/screens/commonElements.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepTwo extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 2;
OnboardingStepTwo({Key? key}) : super(key: key);
const OnboardingStepTwo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -22,44 +15,30 @@ class OnboardingStepTwo extends StatelessWidget {
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Nouveau portefeuilles', progress),
common.bubbleSpeak(
"Un trousseau est créé à partir dune phrase de restauration.",
textKey: const Key('step2'),
),
const SizedBox(height: 70),
Image.asset(
'assets/onBoarding/keys-and-wallets-horizontal-plus-phrase.png'),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep3'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepFor(), isFast: true),
);
},
child: const Text("D'accord",
style: TextStyle(fontSize: 20)),
),
))),
const SizedBox(height: 80),
]),
));
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Votre phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(
text:
'Conservez cette phrase précieusement, car sans elle Gecko ne pourra pas reconstruire vos portefeuilles le jour où vous changez de téléphone.'),
],
'fabrication-de-portefeuille-impossible-sans-phrase.png',
'>',
const OnboardingStepThree(),
1),
),
);
}
}

View File

@ -6,12 +6,8 @@ import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/4.dart';
// ignore: must_be_immutable
class OnboardingStepFor extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 3;
OnboardingStepFor({Key? key}) : super(key: key);
class OnboardingStepThree extends StatelessWidget {
const OnboardingStepThree({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -19,50 +15,28 @@ class OnboardingStepFor extends StatelessWidget {
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Si un jour vous changez de téléphone, il vous suffira de me redonner votre phrase de restauration pour recréer votre trousseau.",
textKey: const Key('step3'),
),
SizedBox(height: isTall ? 15 : 0),
// Row(children: <Widget>[
// Align(
// alignment: Alignment.centerRight,
// child:
Image.asset(
'assets/onBoarding/plusieurs-appareils-un-trousseau.png',
height: 400 * ratio,
),
// ]),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep4'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepFive(), isFast: true),
);
},
child: const Text("J'ai compris",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 80),
]),
));
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Votre phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(text: 'Dans une blockchain, pas de procédure de récupération par mail. Seule votre phrase de restauration peut vous permettre de récupérer vos Ğ1 à tout moment.'),
],
'mot-de-passe-oublie.png',
'>',
const OnboardingStepFor(),
2),
),
);
}
}

View File

@ -6,12 +6,8 @@ import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/5.dart';
// ignore: must_be_immutable
class OnboardingStepFive extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 4;
OnboardingStepFive({Key? key}) : super(key: key);
class OnboardingStepFor extends StatelessWidget {
const OnboardingStepFor({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -19,45 +15,33 @@ class OnboardingStepFive extends StatelessWidget {
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Par contre, attention :\n\nDans une blockchain, il ny a pas de procédure de récupération de trousseau.\n\nSi vous perdez votre phrase de restauration, je ne pourrai pas vous la communiquer, et vous ne pourrez donc plus jamais accéder à votre compte.",
textKey: const Key('step4'),
),
SizedBox(height: isTall ? 30 : 10),
Image.asset(
'assets/onBoarding/maison-qui-brule.png',
width: 320 * ratio,
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep5'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepSeven(), isFast: true),
);
},
child: const Text("J'ai compris",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 80),
]),
));
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Votre phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(text: 'Il est temps de vous munir d'),
const TextSpan(
text: 'un dun papier et dun crayon',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text: ' afin de pouvoir noter votre phrase de restauration.'),
],
'gecko-oublie-aussi.png',
'>',
const OnboardingStepFive(),
3),
),
);
}
}

View File

@ -3,78 +3,243 @@
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/6.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepSeven extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 5;
AsyncSnapshot<List>? mnemoList;
OnboardingStepSeven({Key? key}) : super(key: key);
class OnboardingStepFive extends StatelessWidget {
const OnboardingStepFive({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
CommonElements common = CommonElements();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeakRich(
<TextSpan>[
const TextSpan(text: "Munissez-vous d'"),
const TextSpan(
text: 'un papier et dun crayon\n',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text:
"afin de pouvoir noter votre phrase de restauration."),
],
textKey: const Key('step5'),
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Votre phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: [
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(4),
SizedBox(height: isTall ? 40 : 20),
common.buildText(
<TextSpan>[
const TextSpan(
text:
'Gecko a généré votre phrase de restauration ! Tâchez de la garder bien secrète, car elle permet à quiconque la connaît daccéder à tous vos portefeuilles.'),
],
),
const SizedBox(height: 40),
sentanceArray(context),
const SizedBox(height: 20),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PrintWallet(_generateWalletProvider.generatedMnemonic);
}),
);
},
child: Image.asset(
'assets/printer.png',
height: 45,
),
Expanded(
child: Align(
),
const SizedBox(height: 40),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 90),
child: common.bubbleSpeak(
"Moi, jai déjà essayé de\nmémoriser une phrase de\nrestauration, mais je nai\npas une mémoire\ndéléphant.",
isMaxWidth: false),
),
Image.asset(
'assets/onBoarding/chopp-gecko.png',
height: 200,
),
]),
)),
SizedBox(height: isTall ? 120 : 50),
SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep6'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepEight(), isFast: true),
);
},
child: const Text("J'ai de quoi noter",
style: TextStyle(fontSize: 20))),
child: SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
key: const Key('generateMnemonic'),
style: ElevatedButton.styleFrom(
elevation: 4,
primary: const Color(0xffFFD58D),
onPrimary: Colors.black, // foreground
),
onPressed: () {
_generateWalletProvider.reloadBuild();
// setState(() {});
},
child: const Text("Choisir une autre phrase",
style: TextStyle(
fontSize: 24, fontWeight: FontWeight.w600))),
),
),
const SizedBox(height: 80),
]),
));
),
const SizedBox(height: 25),
nextButton(context, "J'ai noté ma phrase", false),
const SizedBox(height: 40),
]),
),
);
}
}
Widget sentanceArray(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),
child: Container(
constraints: const BoxConstraints(maxWidth: 450),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: const Color(0xffeeeedd),
borderRadius: const BorderRadius.all(
Radius.circular(10),
)),
padding: const EdgeInsets.all(20),
child: FutureBuilder(
future: _generateWalletProvider.generateWordList(context),
builder: (BuildContext context, AsyncSnapshot<List> _data) {
if (!_data.hasData) {
return const Text('');
} else {
mnemoList = _data;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(children: <Widget>[
arrayCell(_data.data![0]),
arrayCell(_data.data![1]),
arrayCell(_data.data![2]),
arrayCell(_data.data![3]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(_data.data![4]),
arrayCell(_data.data![5]),
arrayCell(_data.data![6]),
arrayCell(_data.data![7]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(_data.data![8]),
arrayCell(_data.data![9]),
arrayCell(_data.data![10]),
arrayCell(_data.data![11]),
]),
]);
}
}),
),
);
}
Widget arrayCell(dataWord) {
return SizedBox(
width: 100,
child: Column(children: <Widget>[
Text(
dataWord.split(':')[0],
style: const TextStyle(fontSize: 15, color: Color(0xff6b6b52)),
),
Text(
dataWord.split(':')[1],
key: Key('word${dataWord.split(':')[0]}'),
style: const TextStyle(fontSize: 20, color: Colors.black),
),
]),
);
}
// ignore: must_be_immutable
class PrintWallet extends StatelessWidget {
const PrintWallet(this.sentence, {Key? key}) : super(key: key);
final String? sentence;
@override
Widget build(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
Navigator.pop(context);
}),
backgroundColor: yellowC,
foregroundColor: Colors.black,
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Imprimer ma phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
body: PdfPreview(
canDebug: false,
canChangeOrientation: false,
build: (format) => _generateWalletProvider.printWallet(mnemoList),
),
),
);
}
}
Widget nextButton(BuildContext context, String text, bool isFast) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
return SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
_generateWalletProvider.nbrWord =
_generateWalletProvider.getRandomInt();
_generateWalletProvider.nbrWordAlpha = _generateWalletProvider
.intToString(_generateWalletProvider.nbrWord + 1);
_myWalletProvider.mnemonic = _generateWalletProvider.generatedMnemonic!;
Navigator.push(
context,
FaderTransition(
page: OnboardingStepSix(
generatedMnemonic: _generateWalletProvider.generatedMnemonic),
isFast: true),
);
},
child: Text(
text,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
);
}

View File

@ -1,124 +1,238 @@
// ignore_for_file: file_names
import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/7.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepEight extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 6;
class OnboardingStepSix extends StatelessWidget {
OnboardingStepSix({Key? key, required this.generatedMnemonic})
: super(key: key);
OnboardingStepEight({Key? key}) : super(key: key);
String? generatedMnemonic;
TextEditingController wordController = TextEditingController();
final TextEditingController _mnemonicController = TextEditingController();
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: true);
return Scaffold(
CommonElements common = CommonElements();
_mnemonicController.text = generatedMnemonic!;
return WillPopScope(
onWillPop: () {
_generateWalletProvider.isAskedWordValid = false;
_generateWalletProvider.askedWordColor = Colors.black;
return Future<bool>.value(true);
},
child: Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"Jai généré votre phrase de restauration !\nTâchez de la garder bien secrète, car elle permet à quiconque la connaît daccéder à tous vos portefeuilles.",
textKey: const Key('step6'),
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Votre phrase de restauration',
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: isTall ? 70 : 40),
// SizedBox(height: 30),
sentanceArray(context),
// ),
Expanded(
child: Align(
),
),
body: SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Column(children: [
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(5),
SizedBox(height: isTall ? 40 : 20),
common.buildText(
<TextSpan>[
TextSpan(
text:
"Avez-vous bien noté votre phrase de restauration ?\n\nPour en être sûr, veuillez taper dans le champ ci-dessous le ",
style: TextStyle(fontSize: 16 * ratio)),
TextSpan(
text: '${_generateWalletProvider.nbrWord + 1}ème mot',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16 * ratio)),
TextSpan(
text: " de votre phrase de restauration :",
style: TextStyle(fontSize: 16 * ratio)),
],
),
SizedBox(height: isTall ? 70 : 20),
Text('${_generateWalletProvider.nbrWord + 1}',
key: const Key('askedWord'),
style: TextStyle(
fontSize: isTall ? 17 : 15,
color: orangeC,
fontWeight: FontWeight.w400)),
const SizedBox(height: 10),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
border: Border.all(
color: Colors.grey[600]!,
width: 3,
)),
width: 430,
child: TextFormField(
key: const Key('inputWord'),
autofocus: true,
enabled: !_generateWalletProvider.isAskedWordValid,
controller: wordController,
textInputAction: TextInputAction.next,
onChanged: (value) {
_generateWalletProvider.checkAskedWord(
value, _mnemonicController.text);
},
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
labelStyle: TextStyle(
fontSize: 22.0,
color: Colors.grey[500],
fontWeight: FontWeight.w500),
labelText: _generateWalletProvider.isAskedWordValid
? "C'est le bon mot !"
: "${_generateWalletProvider.nbrWordAlpha} mot de votre phrase de restauration",
fillColor: const Color(0xffeeeedd),
filled: true,
contentPadding: const EdgeInsets.all(12),
),
style: TextStyle(
fontSize: 40.0,
color: _generateWalletProvider.askedWordColor,
fontWeight: FontWeight.w500))),
Visibility(
visible: _generateWalletProvider.isAskedWordValid,
child: Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep7'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepNine(), isFast: false),
);
},
child: const Text("Afficher ma phrase",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 80),
]),
));
child: nextButton(context, 'Continuer',
const OnboardingStepSeven(), false),
),
),
),
// Visibility(
// visible: !_generateWalletProvider.isAskedWordValid,
// child: const Expanded(
// child: Align(
// alignment: Alignment.bottomCenter,
// child: Text(''),
// ),
// ),
// ),
const SizedBox(height: 40),
]),
),
),
),
);
}
}
Widget sentanceArray(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Container(
constraints: const BoxConstraints(maxWidth: 450),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[300],
borderRadius: const BorderRadius.all(
Radius.circular(10),
)),
// color: Colors.grey[300],
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(children: <Widget>[
arrayCell("1:exquis"),
arrayCell("2:favori"),
arrayCell("3:curseur"),
arrayCell("4:relatif"),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell("5:embellir"),
arrayCell("6:cultiver"),
arrayCell("7:bureau"),
arrayCell("8:ossature"),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell("9:labial"),
arrayCell("10:science"),
arrayCell("11:théorie"),
arrayCell("12:Monnaie"),
]),
])));
padding: const EdgeInsets.symmetric(horizontal: 3),
child: Container(
constraints: const BoxConstraints(maxWidth: 450),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: const Color(0xffeeeedd),
borderRadius: const BorderRadius.all(
Radius.circular(10),
)),
padding: const EdgeInsets.all(20),
child: FutureBuilder(
future: _generateWalletProvider.generateWordList(context),
builder: (BuildContext context, AsyncSnapshot<List> _data) {
if (!_data.hasData) {
return const Text('');
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(children: <Widget>[
arrayCell(_data.data![0]),
arrayCell(_data.data![1]),
arrayCell(_data.data![2]),
arrayCell(_data.data![3]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(_data.data![4]),
arrayCell(_data.data![5]),
arrayCell(_data.data![6]),
arrayCell(_data.data![7]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(_data.data![8]),
arrayCell(_data.data![9]),
arrayCell(_data.data![10]),
arrayCell(_data.data![11]),
]),
]);
}
}),
),
);
}
Widget arrayCell(dataWord) {
return SizedBox(
width: 102,
child: Column(
children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 1, sigmaY: 1),
child: Text(dataWord.split(':')[0],
style: const TextStyle(fontSize: 14, color: Colors.black)),
),
const SizedBox(height: 2),
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 4, sigmaY: 4),
child: Text(dataWord.split(':')[1],
style: const TextStyle(fontSize: 19, color: Colors.black)),
)
],
));
width: 100,
child: Column(children: <Widget>[
Text(
dataWord.split(':')[0],
style: const TextStyle(fontSize: 15, color: Color(0xff6b6b52)),
),
Text(
dataWord.split(':')[1],
key: Key('word${dataWord.split(':')[0]}'),
style: const TextStyle(fontSize: 20, color: Colors.black),
),
]),
);
}
Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
_generateWalletProvider.isAskedWordValid = false;
_generateWalletProvider.askedWordColor = Colors.black;
return SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context, FaderTransition(page: nextScreen, isFast: isFast));
},
child: Text(
text,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
);
}

View File

@ -1,209 +1,43 @@
// ignore_for_file: file_names
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/8.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepNine extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 6;
OnboardingStepNine({Key? key}) : super(key: key);
class OnboardingStepSeven extends StatelessWidget {
const OnboardingStepSeven({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
CommonElements common = CommonElements();
// _generateWalletProvider.generateMnemonic();
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeak(
"C'est le moment de noter votre phrase !",
textKey: const Key('step7'),
long: 60,
),
SizedBox(height: isTall ? 100 : 70),
sentanceArray(context),
SizedBox(height: isTall ? 20 : 15),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PrintWallet(
_generateWalletProvider.generatedMnemonic);
}),
);
},
child: Image.asset(
'assets/printer.png',
height: 35,
),
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('generateMnemonic'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: const Color(0xffFFD58D),
onPrimary: Colors.black, // foreground
),
onPressed: () {
_generateWalletProvider.reloadBuild();
},
child: const Text("Choisir une autre phrase",
style: TextStyle(fontSize: 20))),
))),
const SizedBox(height: 25),
SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep8'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
_generateWalletProvider.nbrWord =
_generateWalletProvider.getRandomInt();
_generateWalletProvider.nbrWordAlpha =
_generateWalletProvider
.intToString(_generateWalletProvider.nbrWord + 1);
_myWalletProvider.mnemonic =
_generateWalletProvider.generatedMnemonic!;
Navigator.push(
context,
FaderTransition(
page: OnboardingStepTen(
generatedMnemonic:
_generateWalletProvider.generatedMnemonic),
isFast: true),
);
},
child: const Text("J'ai noté ma phrase",
style: TextStyle(fontSize: 20))),
),
const SizedBox(height: 80),
]),
));
}
}
Widget sentanceArray(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
List formatedArray = _generateWalletProvider.generateWordList();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Container(
constraints: const BoxConstraints(maxWidth: 450),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[300],
borderRadius: const BorderRadius.all(
Radius.circular(10),
)),
// color: Colors.grey[300],
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(children: <Widget>[
arrayCell(formatedArray[0]),
arrayCell(formatedArray[1]),
arrayCell(formatedArray[2]),
arrayCell(formatedArray[3]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(formatedArray[4]),
arrayCell(formatedArray[5]),
arrayCell(formatedArray[6]),
arrayCell(formatedArray[7]),
]),
const SizedBox(height: 15),
Row(children: <Widget>[
arrayCell(formatedArray[8]),
arrayCell(formatedArray[9]),
arrayCell(formatedArray[10]),
arrayCell(formatedArray[11]),
]),
]),
),
);
}
Widget arrayCell(dataWord) {
return SizedBox(
width: 102,
child: Column(children: <Widget>[
Text(
dataWord.split(':')[0],
style: const TextStyle(fontSize: 14),
),
const SizedBox(height: 2),
Text(
dataWord.split(':')[1],
key: Key('word${dataWord.split(':')[0]}'),
style: const TextStyle(fontSize: 19, color: Colors.black),
),
]),
);
}
// ignore: must_be_immutable
class PrintWallet extends StatelessWidget {
const PrintWallet(this.sentence, {Key? key}) : super(key: key);
final String? sentence;
@override
Widget build(BuildContext context) {
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
Navigator.pop(context);
}),
toolbarHeight: 60 * ratio,
title: const Text('Imprimer ce trousseau')),
body: PdfPreview(
build: (format) => _generateWalletProvider.printWallet(sentence),
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Mon code secret',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(
text:
'Gecko va maintenant générer pour vous un code secret court qui vous permettra daccéder rapidement à vos portefeuilles, sans avoir à taper votre phrase de restauration à chaque fois.'),
],
'coffre-fort-code-secret-dans-telephone.png',
'>',
const OnboardingStepEight(),
6,
boxHeight: 400),
),
);
}
}

View File

@ -2,134 +2,47 @@
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/9.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepTen extends StatelessWidget {
OnboardingStepTen({
Key? validationKey,
required this.generatedMnemonic,
}) : super(key: validationKey);
String? generatedMnemonic;
TextEditingController tplController = TextEditingController();
TextEditingController wordController = TextEditingController();
final TextEditingController _mnemonicController = TextEditingController();
final int progress = 7;
class OnboardingStepEight extends StatelessWidget {
const OnboardingStepEight({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
CommonElements common = CommonElements();
_mnemonicController.text = generatedMnemonic!;
return WillPopScope(
onWillPop: () {
_generateWalletProvider.isAskedWordValid = false;
_generateWalletProvider.askedWordColor = Colors.black;
return Future<bool>.value(true);
},
child: Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Valider ma phrase de restauration', progress),
common.bubbleSpeakRich(
<TextSpan>[
TextSpan(
text:
"Avez-vous bien noté votre phrase de restauration ?\n\nPour en être sûr, veuillez taper dans le champ ci-dessous le ",
style: TextStyle(fontSize: 16 * ratio)),
TextSpan(
text: '${_generateWalletProvider.nbrWord + 1}ème mot',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16 * ratio)),
TextSpan(
text: " de votre phrase de restauration :",
style: TextStyle(fontSize: 16 * ratio)),
],
textKey: const Key('step8'),
),
SizedBox(height: isTall ? 70 : 10),
Text('${_generateWalletProvider.nbrWord + 1}',
key: const Key('askedWord'),
style: TextStyle(
fontSize: isTall ? 17 : 10,
color: orangeC,
fontWeight: FontWeight.w400)),
SizedBox(height: isTall ? 10 : 0),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
border: Border.all(
color: Colors.grey[600]!,
width: 3,
)),
width: 430,
child: TextFormField(
key: const Key('inputWord'),
autofocus: true,
enabled: !_generateWalletProvider.isAskedWordValid,
controller: wordController,
textInputAction: TextInputAction.next,
onChanged: (value) {
_generateWalletProvider.checkAskedWord(
value, _mnemonicController.text);
},
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
labelStyle: TextStyle(
fontSize: 22.0,
color: Colors.grey[500],
fontWeight: FontWeight.w500),
labelText: _generateWalletProvider.isAskedWordValid
? "C'est le bon mot !"
: "${_generateWalletProvider.nbrWordAlpha} mot de votre phrase de restauration",
fillColor: Colors.grey[300],
filled: true,
contentPadding: const EdgeInsets.all(12),
),
style: TextStyle(
fontSize: 40.0,
color: _generateWalletProvider.askedWordColor,
fontWeight: FontWeight.w500))),
Visibility(
visible: _generateWalletProvider.isAskedWordValid,
child: Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
child: ElevatedButton(
key: const Key('goStep9'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepEleven(),
isFast: true),
);
},
child: const Text("Continuer",
style: TextStyle(fontSize: 20))),
)))),
const SizedBox(height: 80),
]),
)));
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Mon code secret',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: common.infoIntro(
context,
<TextSpan>[
const TextSpan(
text:
'Ce code secret protège vos portefeuilles dans un coffre-fort '),
const TextSpan(
text: 'dont vous seul possédez le code',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text:
', de sorte que vos portefeuilles seront inutilisables par dautres.'),
],
'coffre-fort-protege-les-portefeuilles.png',
'>',
const OnboardingStepThirteen(),
7),
),
);
}
}

View File

@ -1,71 +1,109 @@
// ignore_for_file: file_names
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/10.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class OnboardingStepEleven extends StatelessWidget {
TextEditingController tplController = TextEditingController();
final int progress = 8;
OnboardingStepEleven({Key? key}) : super(key: key);
class OnboardingStepThirteen extends StatelessWidget {
const OnboardingStepThirteen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider _generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
// MyWalletsProvider myWalletProvider =
// Provider.of<MyWalletsProvider>(context);
CommonElements common = CommonElements();
_generateWalletProvider.pin.text = kDebugMode && debugPin
? 'AAAAA'
: _generateWalletProvider.changePinCode(reload: false);
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text(
'Mon code secret',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: Column(children: <Widget>[
common.onboardingProgressBar(
context, 'Ma phrase de restauration', progress),
common.bubbleSpeakRich(
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(8),
SizedBox(height: isTall ? 40 : 20),
common.buildText(
<TextSpan>[
const TextSpan(
text: "Super !\n\nJe vais maintenant créer votre "),
text:
"Et voilà votre code secret !\n\nMémorisez-le ou notez-le, car il vous sera demandé "),
const TextSpan(
text: 'code secret.',
text: 'à chaque fois',
style: TextStyle(fontWeight: FontWeight.bold)),
const TextSpan(
text:
" \n\nVotre code secret chiffre votre trousseau de clefs, ce qui le rend inutilisable par dautres, par exemple si vous perdez votre téléphone ou si on vous le vole."),
" que vous voudrez effectuer un paiement sur cet appareil."),
],
textKey: const Key('step9'),
),
SizedBox(height: isTall ? 50 : 10),
Image.asset(
'assets/onBoarding/treasure-chest-gecko-souligne.png',
height: 280 * ratio, //5": 400
const SizedBox(height: 100),
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(
key: const Key('generatedPin'),
enabled: false,
controller: _generateWalletProvider.pin,
maxLines: 1,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
style: const TextStyle(
letterSpacing: 5,
fontSize: 35.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
IconButton(
icon: const Icon(Icons.replay),
color: orangeC,
onPressed: () {
_generateWalletProvider.changePinCode(reload: true);
},
),
],
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 400,
height: 62,
width: 410,
height: 70,
child: ElevatedButton(
key: const Key('goStep10'),
key: const Key('changeSecretCode'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: orangeC,
onPrimary: Colors.white, // foreground
elevation: 4,
primary: const Color(0xffFFD58D),
onPrimary: Colors.black, // foreground
),
onPressed: () {
Navigator.push(
context,
FaderTransition(
page: OnboardingStepTwelve(), isFast: true),
);
_generateWalletProvider.changePinCode(reload: true);
},
child: const Text("J'ai compris",
style: TextStyle(fontSize: 20))),
child: const Text("Choisir un autre code secret",
style: TextStyle(
fontSize: 24, fontWeight: FontWeight.w600))),
))),
const SizedBox(height: 80),
const SizedBox(height: 25),
common.nextButton(context, "J'ai noté mon code secret",
OnboardingStepFourteen(), false),
const SizedBox(height: 40),
]),
));
}

View File

@ -3,6 +3,7 @@ import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/search.dart';
import 'package:gecko/screens/wallet_view.dart';
@ -57,9 +58,9 @@ class SearchResultScreen extends StatelessWidget {
),
),
const SizedBox(height: 40),
const Text(
'Dans la blockchain Ğ1',
style: TextStyle(fontSize: 20),
Text(
'Dans la blockchain $currencyName',
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
FutureBuilder(
@ -107,9 +108,11 @@ class SearchResultScreen extends StatelessWidget {
]);
}
if (_avatar.hasData) {
g1WalletsBox
.get(g1Wallet.pubkey)!
.avatar = _avatar.data;
final _w =
g1WalletsBox.get(g1Wallet.pubkey);
if (_w != null) {
_w.avatar = _avatar.data;
}
return ClipOval(child: _avatar.data);
} else {
g1WalletsBox
@ -131,6 +134,11 @@ class SearchResultScreen extends StatelessWidget {
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
balance(context, g1Wallet.pubkey!, 16)
]),
subtitle: Row(children: <Widget>[
Text(g1Wallet.id?.username ?? '',
style: const TextStyle(

View File

@ -2,11 +2,13 @@ import 'package:flutter/material.dart';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/myWallets/generate_wallets.dart';
import 'dart:io';
import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
// import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/myWallets/restore_chest.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class SettingsScreen extends StatelessWidget {
@ -29,105 +31,121 @@ class SettingsScreen extends StatelessWidget {
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
const double buttonHigh = 50;
const double buttonWidth = 240;
const double fontSize = 16;
TextEditingController _endpointController =
TextEditingController(text: configBox.get('endpoint'));
// getAppDirectory();
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Paramètres'),
)),
body: Column(children: <Widget>[
const SizedBox(height: 40),
SizedBox(
height: 70,
width: 500,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Paramètres'),
)),
body: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 60),
Row(children: [
Text(' Noeud $currencyName :'),
const SizedBox(width: 20),
SizedBox(
width: 200,
height: 50,
child: TextField(
controller: _endpointController,
autocorrect: false,
),
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ImportWalletScreen();
}),
).then((value) => {
if (value == true) {Navigator.pop(context)}
const Spacer(),
Consumer<SubstrateSdk>(builder: (context, _sub, _) {
return _sub.isLoadingEndpoint
? CircularProgressIndicator(color: orangeC)
: IconButton(
icon: Icon(
Icons.send,
color: orangeC,
size: 40,
),
onPressed: () async {
configBox.put('endpoint', _endpointController.text);
await _sub.connectNode(context);
});
}),
const Spacer(),
]),
SizedBox(height: isTall ? 50 : 20),
SizedBox(
height: buttonHigh,
width: buttonWidth,
child: ElevatedButton(
key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return GenerateFastChestScreen();
}),
child: const Text(
"Importer un portefeuille Cesium",
style: TextStyle(fontSize: 16),
),
child: const Text(
"Générer un coffre",
style: TextStyle(fontSize: fontSize),
),
),
),
),
const SizedBox(height: 30),
SizedBox(
height: 70,
width: 500,
child: ElevatedButton(
key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return GenerateFastChestScreen();
}),
),
child: const Text(
"Générer un nouveau trousseau",
style: TextStyle(fontSize: 16),
const SizedBox(height: 20),
SizedBox(
height: buttonHigh,
width: buttonWidth,
child: ElevatedButton(
key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const RestoreChest();
}),
),
child: const Text(
"Restaurer un coffre",
style: TextStyle(fontSize: fontSize),
),
),
),
),
const SizedBox(height: 30),
SizedBox(
height: 70,
width: 500,
child: ElevatedButton(
key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const RestoreChest();
}),
),
child: const Text(
"Restaurer un coffre",
style: TextStyle(fontSize: 16),
const SizedBox(height: 25),
SizedBox(
height: buttonHigh,
width: buttonWidth,
child: Center(
child: InkWell(
key: const Key('deleteChest'),
onTap: () async {
log.i('Oublier tous mes coffres');
await _myWallets.deleteAllWallet(context);
},
child: const Text(
'Oublier tous mes coffres',
style: TextStyle(
fontSize: fontSize + 3,
color: Color(0xffD80000),
fontWeight: FontWeight.w500,
),
),
),
),
),
),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 100,
width: 500,
child: ElevatedButton(
key: const Key('deleteAllWallets'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: Colors.redAccent, // background
onPrimary: Colors.black, // foreground
),
onPressed: () async => {
log.i('Suppression de tous les wallets'),
await _myWallets.deleteAllWallet(context)
},
child: const Text("EFFACER TOUS MES PORTEFEUILLES",
style: TextStyle(fontSize: 20)))))),
const SizedBox(height: 50),
]));
]),
);
}
}

View File

@ -0,0 +1,172 @@
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:provider/provider.dart';
class SubstrateSandBox extends StatelessWidget {
const SubstrateSandBox({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
return StatefulWrapper(
onInit: () async {
// if (!_sub.sdkReady && !_sub.sdkLoading) await _sub.initApi();
// if (_sub.sdkReady && !_sub.nodeConnected) await _sub.connectNode();
},
child: Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Substrate Sandbox'),
),
),
body: SafeArea(
child: Consumer<SubstrateSdk>(builder: (context, _sub, _) {
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('js-api chargé ?: ${_sub.sdkReady}'),
InkWell(
onTap: () async {
await _sub.connectNode(context);
},
child: Text(
'Noeud connecté ?: ${_sub.nodeConnected} (${configBox.get('endpoint')})')),
if (_sub.nodeConnected)
Text('Noeud "$currencyName", bloc N°${_sub.blocNumber}'),
const SizedBox(height: 20),
Row(children: [
const Text('Liste des coffres:'),
const Spacer(),
InkWell(
child: Image.asset(
'assets/walletOptions/trash.png',
height: 35,
),
onTap: () async {
await _sub.deleteAllAccounts();
_sub.reload();
},
),
const SizedBox(width: 10),
]),
FutureBuilder(
future: _sub.getKeyStoreAddress(),
builder: (BuildContext context,
AsyncSnapshot<List<AddressInfo>> _data) {
return Column(children: [
if (_data.data != null)
for (final AddressInfo addressInfo in _data.data!)
Row(children: [
InkWell(
onTap: () => _sub.keyring.setCurrent(_sub
.keyring.keyPairs
.firstWhere((element) =>
element.address ==
addressInfo.address!)),
child: Text(
getShortPubkey(addressInfo.address!),
style: const TextStyle(
fontFamily: 'Monospace'),
),
),
const SizedBox(width: 20),
// InkWell(
// onTap: () async => await _sub.pay(
// context,
// addressInfo.address!,
// 10,
// _sub.keystorePassword.text),
// child:
Text(
"${addressInfo.balance.toString()} $currencyName"),
// ),
const SizedBox(width: 20),
InkWell(
onTap: () async => await _sub.derive(
context,
addressInfo.address!,
2,
_sub.keystorePassword.text),
child: const Text("Dériver"),
)
])
]);
}),
const SizedBox(height: 20),
const Text('Mot de passe du coffre:'),
TextField(
controller: _sub.keystorePassword,
obscureText: true,
obscuringCharacter: '',
enableSuggestions: false,
autocorrect: false,
onChanged: (_) => _sub.reload(),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 20, width: double.infinity),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: _sub.keystorePassword.text.isNotEmpty
? () async {
final res = await _sub.importAccount();
_sub.importIsLoading = false;
_sub.reload();
snack(
context,
res != ''
? 'Portefeuille importé'
: 'Le format de coffre est invalide');
}
: null,
child: const Text(
'Importer depuis le presse-papier',
style: TextStyle(fontSize: 20),
),
),
if (_sub.importIsLoading)
const CircularProgressIndicator(),
const SizedBox(height: 20),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () async {
await _sub.generateMnemonic();
_sub.importIsLoading = false;
_sub.reload();
snack(context, 'Le mnemonic a été copié');
},
child: const Text(
"Générer un mnemonic et le copier",
style: TextStyle(fontSize: 20),
),
),
const SizedBox(height: 10),
SizedBox(
width: 400,
child: Text(
_sub.generatedMnemonic,
textAlign: TextAlign.center,
),
)
])
]),
);
}),
),
),
);
}
}

View File

@ -2,15 +2,12 @@ import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/models/queries.dart';
import 'package:gecko/screens/avatar_fullscreen.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/history.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
class WalletViewScreen extends StatelessWidget {
@ -53,7 +50,8 @@ class WalletViewScreen extends StatelessWidget {
height: buttonSize,
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
color: Colors
.grey[300], //const Color(0xffFFD58D), // button color
child: InkWell(
key: const Key('viewHistory'),
splashColor: orangeC, // inkwell color
@ -64,19 +62,20 @@ class WalletViewScreen extends StatelessWidget {
'assets/walletOptions/clock.png'),
height: 90)),
onTap: () {
_historyProvider.nPage = 1;
Navigator.push(
context,
FaderTransition(
page: HistoryScreen(
pubkey: pubkey,
username: username ??
g1WalletsBox.get(pubkey)?.username,
avatar: avatar ??
g1WalletsBox.get(pubkey)?.avatar,
),
isFast: false),
);
////TODO: wait for subsquid indexer
// _historyProvider.nPage = 1;
// Navigator.push(
// context,
// FaderTransition(
// page: HistoryScreen(
// pubkey: pubkey,
// username: username ??
// g1WalletsBox.get(pubkey)?.username,
// avatar: avatar ??
// g1WalletsBox.get(pubkey)?.avatar,
// ),
// isFast: false),
// );
}),
),
),
@ -105,7 +104,7 @@ class WalletViewScreen extends StatelessWidget {
height: 90)),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
snackCopyKey(context);
}),
),
),
@ -191,6 +190,7 @@ class WalletViewScreen extends StatelessWidget {
Provider.of<MyWalletsProvider>(context, listen: false);
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
_walletViewProvider.outputPubkey.text = pubkey!;
showModalBottomSheet<void>(
shape: const RoundedRectangleBorder(
@ -254,7 +254,7 @@ class WalletViewScreen extends StatelessWidget {
// onChanged: (v) => _searchProvider.rebuildWidget(),
decoration: InputDecoration(
hintText: '0.00',
suffix: const Text('Ğ1'),
suffix: Text(currencyName),
filled: true,
fillColor: Colors.transparent,
// border: OutlineInputBorder(
@ -285,21 +285,21 @@ class WalletViewScreen extends StatelessWidget {
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed:
_walletViewProvider.payAmount.text != ''
? () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet,
action: "pay");
},
),
);
}
: null,
onPressed: _walletViewProvider.payAmount.text !=
''
? () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet,
action: "pay");
},
),
);
}
: null,
child: const Text(
'Effectuer le virement',
style: TextStyle(
@ -351,7 +351,7 @@ class WalletViewScreen extends StatelessWidget {
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(pubkey!),
@ -362,40 +362,45 @@ class WalletViewScreen extends StatelessWidget {
),
),
]),
const SizedBox(height: 10),
if (username == null &&
g1WalletsBox.get(pubkey)?.username == null)
Query(
options: QueryOptions(
document: gql(getId),
variables: {
'pubkey': pubkey,
},
),
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.isLoading || result.hasException) {
return const Text('...');
} else if (result.data!['idty'] == null ||
result.data!['idty']['username'] == null) {
g1WalletsBox.get(pubkey)?.username = '';
return const Text('');
} else {
g1WalletsBox.get(pubkey)?.username =
result.data!['idty']['username'] ?? '';
return SizedBox(
width: 230,
child: Text(
result.data!['idty']['username'] ?? '',
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
);
}
},
),
const SizedBox(height: 25),
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return balance(context, pubkey!, 20);
}),
////
// if (username == null &&
// g1WalletsBox.get(pubkey)?.username == null)
// Query(
// options: QueryOptions(
// document: gql(getId),
// variables: {
// 'pubkey': pubkey,
// },
// ),
// builder: (QueryResult result,
// {VoidCallback? refetch, FetchMore? fetchMore}) {
// if (result.isLoading || result.hasException) {
// return const Text('...');
// } else if (result.data!['idty'] == null ||
// result.data!['idty']['username'] == null) {
// g1WalletsBox.get(pubkey)?.username = '';
// return const Text('');
// } else {
// g1WalletsBox.get(pubkey)?.username =
// result.data!['idty']['username'] ?? '';
// return SizedBox(
// width: 230,
// child: Text(
// result.data!['idty']['username'] ?? '',
// style: const TextStyle(
// fontSize: 27,
// color: Color(0xff814C00),
// ),
// ),
// );
// }
// },
// ),
if (username == null &&
g1WalletsBox.get(pubkey)?.username != null)
SizedBox(
@ -420,19 +425,20 @@ class WalletViewScreen extends StatelessWidget {
),
),
const SizedBox(height: 25),
FutureBuilder(
future: _cesiumPlusProvider.getName(pubkey),
initialData: '...',
builder: (context, snapshot) {
return SizedBox(
width: 230,
child: Text(
snapshot.data.toString(),
style: const TextStyle(
fontSize: 18, color: Colors.black),
),
);
}),
//// To get Cs+ name
// FutureBuilder(
// future: _cesiumPlusProvider.getName(pubkey),
// initialData: '...',
// builder: (context, snapshot) {
// return SizedBox(
// width: 230,
// child: Text(
// snapshot.data.toString(),
// style: const TextStyle(
// fontSize: 18, color: Colors.black),
// ),
// );
// }),
const SizedBox(height: 30),
]),
const Spacer(),

View File

@ -6,19 +6,21 @@ import FlutterMacOS
import Foundation
import connectivity_plus_macos
import package_info
import desktop_window
import package_info_plus_macos
import path_provider_macos
import printing
import sentry_flutter
import shared_preferences_macos
import window_size
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
DesktopWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWindowPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
}

View File

@ -8,7 +8,7 @@
PRODUCT_NAME = gecko
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.example.gecko
PRODUCT_BUNDLE_IDENTIFIER = gecko.axiomteam.fr
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved.
PRODUCT_COPYRIGHT = Copyright © 2021 gecko.axiomteam.fr. All rights reserved.

File diff suppressed because it is too large Load Diff

View File

@ -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+3
environment:
sdk: '>=2.12.0 <3.0.0'
@ -17,7 +17,7 @@ dependencies:
sdk: flutter
window_size:
git:
url: git://github.com/google/flutter-desktop-embedding.git
url: https://github.com/google/flutter-desktop-embedding.git
path: plugins/window_size
assorted_layout_widgets: ^5.2.1
bubble: ^1.2.1
@ -25,11 +25,14 @@ dependencies:
confirm_dialog: ^1.0.0
crypto: ^3.0.1
fast_base58: ^0.2.0
flutter_launcher_icons: ^0.9.2
flutter_lints: ^1.0.4
flutter_logs: ^2.1.4
flutter_svg: ^0.22.0
graphql_flutter: ^5.0.0
graphql_flutter: #^5.1.0
git:
url: https://github.com/Quantit-Github/graphql-flutter.git
path: packages/graphql_flutter
ref: f1ccb2d # commit hash
hive: ^2.0.4
hive_flutter: ^1.1.0
http: ^0.13.4
@ -43,25 +46,25 @@ dependencies:
pdf: ^3.7.1
permission_handler: ^8.3.0
pin_code_fields: ^7.3.0
printing: ^5.7.2
printing: #^5.8.0
git:
url: https://github.com/DavBfr/dart_pdf.git
path: printing
provider: ^6.0.1
# qrscan: ^0.3.2
qrscan:
qrscan: #^0.3.2
git:
url: git://github.com/leyan95/qrcode_scanner.git
url: https://github.com/leyan95/qrcode_scanner.git
ref: master # branch name
# qr_code_scanner: ^0.6.1
# qr_flutter: ^4.0.0
qr_flutter:
qr_flutter: #^4.0.0
git:
url: git://github.com/insinfo/qr.flutter.git
url: https://github.com/insinfo/qr.flutter.git
ref: master # branch name
responsive_builder: ^0.4.1
responsive_framework: ^0.1.4
sentry: ^6.0.0
sentry_flutter: ^6.0.0
sentry: ^6.5.1
sentry_flutter: ^6.5.1
shared_preferences: ^2.0.7
super_tooltip: ^1.0.1
sync_http: ^0.3.0
test: ^1.17.10
truncate: ^3.0.1
@ -71,15 +74,17 @@ dependencies:
dio: ^4.0.4
desktop_window: ^0.4.0
durt: ^0.1.6
package_info_plus: ^1.3.0
flutter_icons:
android: "ic_launcher"
ios: true
image_path: "assets/icon/gecko_flat.png"
cupertino_icons: ^1.0.0
package_info_plus: ^1.4.2
polkawallet_sdk: #^0.4.5
git:
url: https://github.com/poka-IT/sdk.git
ref: fixAndroidActivityVersion
dots_indicator: ^2.1.0
dev_dependencies:
# flutter_launcher_icons: ^0.9.2
# flutter_launcher_icons_maker: ^^0.10.2
icons_launcher: ^1.1.8
build_runner: ^2.1.2
flutter_test:
sdk: flutter
@ -87,6 +92,14 @@ dev_dependencies:
integration_test:
sdk: flutter
flutter_icons:
android: true
ios: true
image_path: "assets/icon/gecko_flat.png"
remove_alpha_ios: true
uses-material-design: true
# The following section is specific to Flutter.
flutter:
uses-material-design: true

View File

@ -19,7 +19,7 @@ cargo make
# Build APK
echo "Build APK..."
flutter clean
#flutter clean
flutter build apk --release --build-name $VERSION --build-number $BUILD
# Create artifacts folder

View File

@ -22,7 +22,9 @@ else
# flutter build apk --release --build-name $VERSION --build-number $BUILD
fi
if [[ -d $HOME/Téléchargements ]]; then
if [[ -d $HOME/Nextcloud/Gecko-APK ]]; then
DL="$HOME/Nextcloud/Gecko-APK"
elif [[ -d $HOME/Téléchargements ]]; then
DL="$HOME/Téléchargements"
elif [[ -d $HOME/Downloads ]]; then
DL="$HOME/Downloads"

View File

@ -1,5 +1,5 @@
#!/bin/bash
flutter pub run flutter_launcher_icons:main
flutter pub run icons_launcher:main
exit 0

View File

@ -216,7 +216,7 @@ void main() {
test('OnBoarding - Generate secret code and confirm it', (
{timeout = Timeout.none}) async {
expect(await getText('step9'),
"Super !\n\nJe vais maintenant créer votre code secret. \n\nVotre code secret chiffre votre trousseau de clefs, ce qui le rend inutilisable par dautres, par exemple si vous perdez votre téléphone ou si on vous le vole.");
"Super !\n\nJe vais maintenant créer votre code secret. \n\nVotre code secret chiffre votre coffre de clefs, ce qui le rend inutilisable par dautres, par exemple si vous perdez votre téléphone ou si on vous le vole.");
await sleep(800);
await tapOn('goStep10');
await sleep(50);
@ -248,7 +248,7 @@ void main() {
await driver!.enterText(pinCode!);
expect(await getText('step13'),
"Top !\n\nVotre trousseau de clef et votre portefeuille ont été créés avec un immense succès.\n\nFélicitations !");
"Top !\n\nVotre coffre et votre portefeuille ont été créés avec un immense succès.\n\nFélicitations !");
});
test('My wallets - Rename first derivation', (

View File

@ -10,6 +10,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
window_size
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
@ -18,3 +21,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)

Some files were not shown because too many files have changed in this diff Show More