Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-166-cake-pay-accepts-tip-filtering

This commit is contained in:
Godwin Asuquo 2022-11-08 20:03:40 +02:00
commit 8506fdf5b9
561 changed files with 8253 additions and 6516 deletions

View file

@ -1,51 +1,73 @@
include: package:lints/recommended.yaml
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**]
exclude: [
build/**,
lib/**.g.dart,
cw_core/lib/**.g.dart,
cw_haven/lib/**.g.dart,
cw_monero/lib/**.g.dart,
lib/generated/*.dart,
cw_monero/ios/External/**,
cw_shared_external/**,
shared_external/**]
language:
strict-casts: true
strict-raw-types: true
linter:
rules:
- always_declare_return_types
- annotate_overrides
- avoid_empty_else
- avoid_init_to_null
- avoid_return_types_on_setters
- await_only_futures
- camel_case_types
- cancel_subscriptions
- close_sinks
- comment_references
- constant_identifier_names
- control_flow_in_finally
- empty_catches
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- invariant_booleans
- iterable_contains_unrelated_type
- library_names
- library_prefixes
- list_remove_unrelated_type
- literal_only_boolean_expressions
- non_constant_identifier_names
- one_member_abstracts
- only_throw_errors
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- parameter_assignments
- prefer_final_fields
- prefer_final_locals
- prefer_is_not_empty
- slash_for_doc_comments
- sort_constructors_first
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- type_init_formals
- unawaited_futures
- unnecessary_getters_setters
- unrelated_type_equality_checks
- valid_regexps
# analyzer:
# strong-mode:
# implicit-casts: false
# implicit-dynamic: false
# exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**]
# linter:
# rules:
# - always_declare_return_types
# - annotate_overrides
# - avoid_empty_else
# - avoid_init_to_null
# - avoid_return_types_on_setters
# - await_only_futures
# - camel_case_types
# - cancel_subscriptions
# - close_sinks
# - comment_references
# - constant_identifier_names
# - control_flow_in_finally
# - empty_catches
# - empty_constructor_bodies
# - empty_statements
# - hash_and_equals
# - invariant_booleans
# - iterable_contains_unrelated_type
# - library_names
# - library_prefixes
# - list_remove_unrelated_type
# - literal_only_boolean_expressions
# - non_constant_identifier_names
# - one_member_abstracts
# - only_throw_errors
# - overridden_fields
# - package_api_docs
# - package_names
# - package_prefixed_library_names
# - parameter_assignments
# - prefer_final_fields
# - prefer_final_locals
# - prefer_is_not_empty
# - slash_for_doc_comments
# - sort_constructors_first
# - sort_unnamed_constructors_first
# - test_types_in_equals
# - throw_in_finally
# - type_init_formals
# - unawaited_futures
# - unnecessary_getters_setters
# - unrelated_type_equality_checks
# - valid_regexps

View file

@ -37,7 +37,7 @@ if (appPropertiesFile.exists()) {
}
android {
compileSdkVersion 29
compileSdkVersion 33
lintOptions {
disable 'InvalidPackage'
@ -80,6 +80,8 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
ndkVersion "25.1.8937393"
}
flutter {

View file

@ -1,4 +1,5 @@
buildscript {
ext.kotlin_version = '1.5.10'
repositories {
google()
jcenter()
@ -7,6 +8,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.google.gms:google-services:4.3.8'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View file

@ -5,31 +5,31 @@
},
{
"question" : "Comment envoyer des Monero vers une plateforme d'échange qui nécessite un ID de paiement ?",
"answer" : "Appuyez sur le bouton envoyer de l'écran du Wallet. Ensuite, copiez l'adresse de dépôt de la plateforme d'échange et collez là dans le champ adresse. Puis, copiez l'ID de paiement fourni par la plateforme d'échange et copiez le dans le champ ID de paiement. Enfin, entrez le montant que vous souhaitez envoyer et vous êtes fin prêt !\n"
"answer" : "Appuyez sur le bouton envoyer de l'écran du Portefeuille (Wallet). Ensuite, copiez l'adresse de dépôt de la plateforme d'échange et collez là dans le champ adresse. Puis, copiez l'ID de paiement fourni par la plateforme d'échange et copiez le dans le champ ID de paiement. Enfin, entrez le montant que vous souhaitez envoyer et vous êtes fin prêt !\n"
},
{
"question" : "Que faire si j'oublie d'entrer l'ID de paiement quand j'envoie des Monero vers une plateforme d'échange ?",
"answer" : "Bien que notre service de support ne puisse pas vous aider directement pour ce type de souci, c'est un problème très courant que la plupart des plateformes d'échange ont l'habitude de gérer. Contactez simplement le support de la plateforme d'échange, expliquez que vous avez oublié d'inclure l'ID de paiement et envoyez leur l'ID de transaction comme preuve. Vous pouvez visualiser l'ID de transaction en tapant sur transaction sur l'écran de votre wallet.\n"
"answer" : "Bien que notre service de support ne puisse pas vous aider directement pour ce type de souci, c'est un problème très courant que la plupart des plateformes d'échange ont l'habitude de gérer. Contactez simplement le support de la plateforme d'échange, expliquez que vous avez oublié d'inclure l'ID de paiement et envoyez leur l'ID de transaction comme preuve. Vous pouvez visualiser l'ID de transaction en tapant sur transaction sur l'écran de votre portefeuille (wallet).\n"
},
{
"question" : "Que signifient \"seed\" et \"clefs\" ?",
"answer" : "Vos clefs encodent l'information privée de votre wallet, ce sont elles qui permettent de dépenser vos fonds et de visualiser les transactions entrantes.\nVotre seed est simplement une version de votre clef privée sous une forme plus simple à recopier. Votre seed et vos clefs sont la même chose, juste sous des formes différentes !\nNE DONNEZ JAMAIS votre seed ou vos clefs à quiconque. Vos fonds seront dérobés si vous donner votre seed ou vos clefs. Merci d'écrire cependant votre seed et de le stocker en lieu sûr (afin de vous permettre de restaurer votre wallet si vous perdez votre téléphone.)\n"
"question" : "Que signifient \"phrase secrète (seed)\" et \"clefs\" ?",
"answer" : "Vos clefs encodent l'information privée de votre portefeuille (wallet), ce sont elles qui permettent de dépenser vos fonds et de visualiser les transactions entrantes.\nVotre phrase secrète (seed) est simplement une version de votre clef privée sous une forme plus simple à recopier. Votre phrase secrète et vos clefs sont la même chose, juste sous des formes différentes !\nNE DONNEZ JAMAIS votre phrase secrète ou vos clefs à quiconque. Vos fonds seront dérobés si vous donnez votre phrase secrète ou vos clefs. Merci d'écrire cependant votre phrase secrète et de la stocker en lieu sûr (afin de vous permettre de restaurer votre portefeuille si vous perdez votre téléphone.)\n"
},
{
"question" : "Combien de wallets puis-je créer ?",
"answer" : "Il n'y a pas de limite ! Vous pouvez créer autant de wallets que vous le souhaitez.\n"
"question" : "Combien de portefeuilles (wallets) puis-je créer ?",
"answer" : "Il n'y a pas de limite ! Vous pouvez créer autant de portefeuilles (wallets) que vous le souhaitez.\n"
},
{
"question" : "Commen puis-je restarurer mon wallet ?",
"answer" : "Appuyez sur le menu •••, sélectionnez Wallets, puis choisissez Restaurer un Wallet. Entrez alors votre seed (ou vos clefs), et de façon optionnelle une date antérieure à la première transaction de votre wallet (cela permettra d'accélérer le processus de synchronisation). Vous pourrez avoir besoin de maintenir l'application ouverte pendant 15 à 30 minutes afin de restaurer complètement votre wallet.\n"
"question" : "Commen puis-je restarurer mon portefeuille (wallet) ?",
"answer" : "Appuyez sur le menu •••, sélectionnez Portefeuilles (Wallets), puis choisissez Restaurer un Portefeuille. Entrez alors votre phrase secrète (seed) (ou vos clefs), et de façon optionnelle une date antérieure à la première transaction de votre portefeuille (cela permettra d'accélérer le processus de synchronisation). Vous pourrez avoir besoin de maintenir l'application ouverte pendant 15 à 30 minutes afin de restaurer complètement votre portefeuille.\n"
},
{
"question" : "Que puis-je faire si je perds mon seed ?",
"answer" : "Si vous oubliez votre seed, il y a des chances que vous l'ayez inscrit quelque part. Vérifiez vos notes et regardez sur votre ordinateur. Si vous ne parvenez pas à le retrouver, il est possible que vous ayez effectué une sauvegarde de Cake Wallet (dans ce cas vous pourrez restaurer d'après cette sauvegarde). Si aucune des ces options ne convient, malheureusement il n'y a plus rien à faire, vos fonds sont définitivement perdus.\n"
"question" : "Que puis-je faire si je perds ma phrase secrète (seed) ?",
"answer" : "Si vous oubliez votre phrase secrète (seed), il y a des chances que vous l'ayez inscrite quelque part. Vérifiez vos notes et regardez sur votre ordinateur. Si vous ne parvenez pas à la retrouver, il est possible que vous ayez effectué une sauvegarde de Cake Wallet (dans ce cas vous pourrez restaurer d'après cette sauvegarde). Si aucune des ces options ne convient, malheureusement il n'y a plus rien à faire, vos fonds sont définitivement perdus.\n"
},
{
"question" : "Collectez vous des informations à propos de mon wallet ?",
"answer" : "Cake Wallet NE COLLECTE PAS d'informations à propos de votre wallet. Nous sommes respectueux de votre intimité.\n"
"question" : "Collectez vous des informations à propos de mon portefeuille (wallet) ?",
"answer" : "Cake Wallet NE COLLECTE PAS d'informations à propos de votre portefeuille (wallet). Nous sommes respectueux de votre intimité.\n"
},
{
"question" : "Est il possible d'annuler une transaction ?",
@ -37,11 +37,11 @@
},
{
"question" : "Que sont les sous-adresses, et comment s'en servir ?",
"answer" : "Une sous-adresse est une adresse unique que vous pouvez générer à tout moment. Les montants envoyés vers cette adresse arrivent toujours dans votre wallet principal, mais la personne qui vous envoie les fonds ne peut pas déterminer votre adresse principale. Les sous-adresses commencent par un 8.\nVous pouvez créer une nouvelle sous-adresse dans l'écran Réception en appuyant sur le + à côté du bouton Sous-Adresses. Entrez un nom pour la sous-adresse et appuyez sur Ajouter. Ensuite appuyez sur le nom de la sous-adresse quand vous souhaitez l'utiliser !\nSi vous êtres paranoïaque, vous devriez créer une nouvelle sous-adresse à chaque fois que vous voulez recevoir des Monero.\n"
"answer" : "Une sous-adresse est une adresse unique que vous pouvez générer à tout moment. Les montants envoyés vers cette adresse arrivent toujours dans votre portefeuille (wallet) principal, mais la personne qui vous envoie les fonds ne peut pas déterminer votre adresse principale. Les sous-adresses commencent par un 8.\nVous pouvez créer une nouvelle sous-adresse dans l'écran Réception en appuyant sur le + à côté du bouton Sous-Adresses. Entrez un nom pour la sous-adresse et appuyez sur Ajouter. Ensuite appuyez sur le nom de la sous-adresse quand vous souhaitez l'utiliser !\nSi vous êtres paranoïaque, vous devriez créer une nouvelle sous-adresse à chaque fois que vous voulez recevoir des Monero.\n"
},
{
"question" : "Qu'est-ce que l'ID de transaction ?",
"answer" : "Une empreinte (hash) de transaction, ou ID de transaction, est un moyen unique d'identifier une transaction. Chaque transaction a sa propre empreinte. Si vous deve fournir une empreinte de transaction à quelque'un, allez simplement sur l'écran principal du Wallet, appuyez sur la transaction puis appuyez longuement sur la section du haut et sélectionnez Copier.\n"
"answer" : "Une empreinte (hash) de transaction, ou ID de transaction, est un moyen unique d'identifier une transaction. Chaque transaction a sa propre empreinte. Si vous deve fournir une empreinte de transaction à quelque'un, allez simplement sur l'écran principal du Portefeuille (Wallet), appuyez sur la transaction puis appuyez longuement sur la section du haut et sélectionnez Copier.\n"
},
{
"question" : "Je n'ai pas reçu mes XMR ! Que puis-je faire ?",

BIN
assets/images/ape_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
assets/images/btt_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
assets/images/dcr_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

BIN
assets/images/doge_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
assets/images/firo_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
assets/images/hbar_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
assets/images/husd_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
assets/images/kmd_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
assets/images/mana_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
assets/images/mkr_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
assets/images/nano_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/images/near_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
assets/images/oxt_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
assets/images/paxg_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
assets/images/pivx_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
assets/images/rune_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
assets/images/rvn_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

BIN
assets/images/sc_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/images/scrt_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
assets/images/sol_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
assets/images/stx_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
assets/images/uni_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
assets/images/usdc_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
assets/images/xvg_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 6 KiB

BIN
assets/images/zen_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -8,7 +8,7 @@ String addressFromOutput(Uint8List script, bitcoin.NetworkType networkType) {
data: PaymentData(output: script),
network: networkType)
.data
.address;
.address!;
} catch (_) {}
try {
@ -16,8 +16,8 @@ String addressFromOutput(Uint8List script, bitcoin.NetworkType networkType) {
data: PaymentData(output: script),
network: networkType)
.data
.address;
.address!;
} catch(_) {}
return null;
return '';
}

View file

@ -2,7 +2,7 @@ import 'dart:convert';
class BitcoinAddressRecord {
BitcoinAddressRecord(this.address,
{this.index, this.isHidden = false, bool isUsed = false})
{required this.index, this.isHidden = false, bool isUsed = false})
: _isUsed = isUsed;
factory BitcoinAddressRecord.fromJSON(String jsonSource) {
@ -11,8 +11,8 @@ class BitcoinAddressRecord {
return BitcoinAddressRecord(
decoded['address'] as String,
index: decoded['index'] as int,
isHidden: decoded['isHidden'] as bool ?? false,
isUsed: decoded['isUsed'] as bool ?? false);
isHidden: decoded['isHidden'] as bool? ?? false,
isUsed: decoded['isUsed'] as bool? ?? false);
}
@override

View file

@ -7,10 +7,10 @@ final bitcoinAmountFormat = NumberFormat()
..maximumFractionDigits = bitcoinAmountLength
..minimumFractionDigits = 1;
String bitcoinAmountToString({int amount}) => bitcoinAmountFormat.format(
String bitcoinAmountToString({required int amount}) => bitcoinAmountFormat.format(
cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider));
double bitcoinAmountToDouble({int amount}) =>
double bitcoinAmountToDouble({required int amount}) =>
cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider);
int stringDoubleToBitcoinAmount(String amount) {

View file

@ -106,15 +106,18 @@ Future<String> generateMnemonic(
return result;
}
Uint8List mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) {
Future<Uint8List> mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async {
final pbkdf2 = cryptography.Pbkdf2(
macAlgorithm: cryptography.Hmac(cryptography.sha512),
macAlgorithm: cryptography.Hmac.sha512(),
iterations: 2048,
bits: 512);
final text = normalizeText(mnemonic);
return pbkdf2.deriveBitsSync(text.codeUnits,
nonce: cryptography.Nonce('electrum'.codeUnits));
// pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce)
final key = await pbkdf2.deriveKey(
secretKey: cryptography.SecretKey(text.codeUnits),
nonce: 'electrum'.codeUnits);
final bytes = await key.extractBytes();
return Uint8List.fromList(bytes);
}
bool matchesAnyPrefix(String mnemonic) =>

View file

@ -2,9 +2,9 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/output_info.dart';
class BitcoinTransactionCredentials {
BitcoinTransactionCredentials(this.outputs, {this.priority, this.feeRate});
BitcoinTransactionCredentials(this.outputs, {required this.priority, this.feeRate});
final List<OutputInfo> outputs;
final BitcoinTransactionPriority priority;
final int feeRate;
final BitcoinTransactionPriority? priority;
final int? feeRate;
}

View file

@ -2,7 +2,7 @@ import 'package:cw_core/transaction_priority.dart';
//import 'package:cake_wallet/generated/i18n.dart';
class BitcoinTransactionPriority extends TransactionPriority {
const BitcoinTransactionPriority({String title, int raw})
const BitcoinTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw);
static const List<BitcoinTransactionPriority> all = [fast, medium, slow];
@ -13,7 +13,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
static const BitcoinTransactionPriority fast =
BitcoinTransactionPriority(title: 'Fast', raw: 2);
static BitcoinTransactionPriority deserialize({int raw}) {
static BitcoinTransactionPriority deserialize({required int raw}) {
switch (raw) {
case 0:
return slow;
@ -22,7 +22,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
case 2:
return fast;
default:
return null;
throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize');
}
}
@ -53,7 +53,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
}
class LitecoinTransactionPriority extends BitcoinTransactionPriority {
const LitecoinTransactionPriority({String title, int raw})
const LitecoinTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw);
static const List<LitecoinTransactionPriority> all = [fast, medium, slow];
@ -64,7 +64,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
static const LitecoinTransactionPriority fast =
LitecoinTransactionPriority(title: 'Fast', raw: 2);
static LitecoinTransactionPriority deserialize({int raw}) {
static LitecoinTransactionPriority deserialize({required int raw}) {
switch (raw) {
case 0:
return slow;
@ -73,7 +73,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
case 2:
return fast;
default:
return null;
throw Exception('Unexpected token: $raw for LitecoinTransactionPriority deserialize');
}
}

View file

@ -1,4 +1,5 @@
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
@ -17,12 +18,13 @@ class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
abstract class BitcoinWalletBase extends ElectrumWallet with Store {
BitcoinWalletBase(
{@required String mnemonic,
@required String password,
@required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord> initialAddresses,
ElectrumBalance initialBalance,
{required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required Uint8List seedBytes,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0})
: super(
@ -32,7 +34,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo,
networkType: bitcoin.bitcoin,
initialAddresses: initialAddresses,
initialBalance: initialBalance) {
initialBalance: initialBalance,
seedBytes: seedBytes,
currency: CryptoCurrency.btc) {
walletAddresses = BitcoinWalletAddresses(
walletInfo,
electrumClient: electrumClient,
@ -40,20 +44,40 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd,
sideHd: bitcoin.HDWallet.fromSeed(
mnemonicToSeedBytes(mnemonic), network: networkType)
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
.derivePath("m/0'/1"),
networkType: networkType);
}
static Future<BitcoinWallet> open({
@required String name,
@required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo,
@required String password,
static Future<BitcoinWallet> create({
required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0
}) async {
final snp = ElectrumWallletSnapshot(name, walletInfo.type, password);
await snp.load();
return BitcoinWallet(
mnemonic: mnemonic,
password: password,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: initialAddresses,
initialBalance: initialBalance,
seedBytes: await mnemonicToSeedBytes(mnemonic),
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex);
}
static Future<BitcoinWallet> open({
required String name,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password,
}) async {
final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password);
return BitcoinWallet(
mnemonic: snp.mnemonic,
password: password,
@ -61,6 +85,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: snp.addresses,
initialBalance: snp.balance,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex);
}

View file

@ -16,13 +16,13 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses
with Store {
BitcoinWalletAddressesBase(
WalletInfo walletInfo,
{@required List<BitcoinAddressRecord> initialAddresses,
{required bitcoin.HDWallet mainHd,
required bitcoin.HDWallet sideHd,
required bitcoin.NetworkType networkType,
required ElectrumClient electrumClient,
List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0,
ElectrumClient electrumClient,
@required bitcoin.HDWallet mainHd,
@required bitcoin.HDWallet sideHd,
@required bitcoin.NetworkType networkType})
int initialChangeAddressIndex = 0})
: super(
walletInfo,
initialAddresses: initialAddresses,
@ -34,6 +34,6 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses
networkType: networkType);
@override
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
String getAddress({required int index, required bitcoin.HDWallet hd}) =>
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
}

View file

@ -2,13 +2,13 @@ import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
class BitcoinNewWalletCredentials extends WalletCredentials {
BitcoinNewWalletCredentials({String name, WalletInfo walletInfo})
BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo})
: super(name: name, walletInfo: walletInfo);
}
class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
BitcoinRestoreWalletFromSeedCredentials(
{String name, String password, this.mnemonic, WalletInfo walletInfo})
{required String name, required String password, required this.mnemonic, WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
final String mnemonic;
@ -16,7 +16,7 @@ class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
BitcoinRestoreWalletFromWIFCredentials(
{String name, String password, this.wif, WalletInfo walletInfo})
{required String name, required String password, required this.wif, WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
final String wif;

View file

@ -1,7 +1,5 @@
import 'package:flutter/foundation.dart';
class BitcoinWalletKeys {
const BitcoinWalletKeys({@required this.wif, @required this.privateKey, @required this.publicKey});
const BitcoinWalletKeys({required this.wif, required this.privateKey, required this.publicKey});
final String wif;
final String privateKey;

View file

@ -10,6 +10,7 @@ import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:collection/collection.dart';
class BitcoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
@ -25,10 +26,10 @@ class BitcoinWalletService extends WalletService<
@override
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
final wallet = BitcoinWallet(
final wallet = await BitcoinWalletBase.create(
mnemonic: await generateMnemonic(),
password: credentials.password,
walletInfo: credentials.walletInfo,
password: credentials.password!,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save();
await wallet.init();
@ -41,9 +42,8 @@ class BitcoinWalletService extends WalletService<
@override
Future<BitcoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, getType()),
orElse: () => null);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await BitcoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource);
@ -68,10 +68,10 @@ class BitcoinWalletService extends WalletService<
throw BitcoinMnemonicIsIncorrectException();
}
final wallet = BitcoinWallet(
password: credentials.password,
final wallet = await BitcoinWalletBase.create(
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save();
await wallet.init();

View file

@ -7,6 +7,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/script_hash.dart';
import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart';
import 'package:collection/collection.dart';
String jsonrpcparams(List<Object> params) {
final _params = params?.map((val) => '"${val.toString()}"')?.join(',');
@ -14,14 +15,20 @@ String jsonrpcparams(List<Object> params) {
}
String jsonrpc(
{String method, List<Object> params, int id, double version = 2.0}) =>
{required String method,
required List<Object> params,
required int id,
double version = 2.0}) =>
'{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n';
class SocketTask {
SocketTask({this.completer, this.isSubscription, this.subject});
SocketTask({
required this.isSubscription,
this.completer,
this.subject});
final Completer completer;
final BehaviorSubject subject;
final Completer<dynamic>? completer;
final BehaviorSubject<dynamic>? subject;
final bool isSubscription;
}
@ -36,18 +43,18 @@ class ElectrumClient {
static const aliveTimerDuration = Duration(seconds: 2);
bool get isConnected => _isConnected;
Socket socket;
void Function(bool) onConnectionStatusChange;
Socket? socket;
void Function(bool)? onConnectionStatusChange;
int _id;
final Map<String, SocketTask> _tasks;
bool _isConnected;
Timer _aliveTimer;
Timer? _aliveTimer;
String unterminatedString;
Future<void> connectToUri(Uri uri) async =>
await connect(host: uri.host, port: uri.port);
Future<void> connect({@required String host, @required int port}) async {
Future<void> connect({required String host, required int port}) async {
try {
await socket?.close();
} catch (_) {}
@ -56,10 +63,11 @@ class ElectrumClient {
timeout: connectionTimeout, onBadCertificate: (_) => true);
_setIsConnected(true);
socket.listen((Uint8List event) {
socket!.listen((Uint8List event) {
try {
final msg = utf8.decode(event.toList());
final response =
json.decode(utf8.decode(event.toList())) as Map<String, Object>;
json.decode(msg) as Map<String, dynamic>;
_handleResponse(response);
} on FormatException catch (e) {
final msg = e.message.toLowerCase();
@ -75,12 +83,12 @@ class ElectrumClient {
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, Object>;
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>')) {
if (!e.toString().contains('Map<String, Object>') || !e.toString().contains('Map<String, dynamic>')) {
return;
}
@ -89,9 +97,10 @@ class ElectrumClient {
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, Object>;
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = null;
// unterminatedString = null;
unterminatedString = '';
}
} catch (e) {
print(e.toString());
@ -128,14 +137,14 @@ class ElectrumClient {
return [];
});
Future<Map<String, Object>> getBalance(String scriptHash) =>
Future<Map<String, dynamic>> getBalance(String scriptHash) =>
call(method: 'blockchain.scripthash.get_balance', params: [scriptHash])
.then((dynamic result) {
if (result is Map<String, Object>) {
if (result is Map<String, dynamic>) {
return result;
}
return <String, Object>{};
return <String, dynamic>{};
});
Future<List<Map<String, dynamic>>> getHistory(String scriptHash) =>
@ -143,11 +152,11 @@ class ElectrumClient {
.then((dynamic result) {
if (result is List) {
return result.map((dynamic val) {
if (val is Map<String, Object>) {
if (val is Map<String, dynamic>) {
return val;
}
return <String, Object>{};
return <String, dynamic>{};
}).toList();
}
@ -162,12 +171,12 @@ class ElectrumClient {
.then((dynamic result) {
if (result is List) {
return result.map((dynamic val) {
if (val is Map<String, Object>) {
if (val is Map<String, dynamic>) {
val['address'] = address;
return val;
}
return <String, Object>{};
return <String, dynamic>{};
}).toList();
}
@ -179,11 +188,11 @@ class ElectrumClient {
.then((dynamic result) {
if (result is List) {
return result.map((dynamic val) {
if (val is Map<String, Object>) {
if (val is Map<String, dynamic>) {
return val;
}
return <String, Object>{};
return <String, dynamic>{};
}).toList();
}
@ -195,30 +204,30 @@ class ElectrumClient {
.then((dynamic result) {
if (result is List) {
return result.map((dynamic val) {
if (val is Map<String, Object>) {
if (val is Map<String, dynamic>) {
return val;
}
return <String, Object>{};
return <String, dynamic>{};
}).toList();
}
return [];
});
Future<Map<String, Object>> getTransactionRaw(
{@required String hash}) async =>
Future<Map<String, dynamic>> getTransactionRaw(
{required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, true])
.then((dynamic result) {
if (result is Map<String, Object>) {
if (result is Map<String, dynamic>) {
return result;
}
return <String, Object>{};
return <String, dynamic>{};
});
Future<String> getTransactionHex(
{@required String hash}) async =>
{required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, false])
.then((dynamic result) {
if (result is String) {
@ -229,7 +238,7 @@ class ElectrumClient {
});
Future<String> broadcastTransaction(
{@required String transactionRaw}) async =>
{required String transactionRaw}) async =>
call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) {
if (result is String) {
@ -240,16 +249,16 @@ class ElectrumClient {
});
Future<Map<String, dynamic>> getMerkle(
{@required String hash, @required int height}) async =>
{required String hash, required int height}) async =>
await call(
method: 'blockchain.transaction.get_merkle',
params: [hash, height]) as Map<String, dynamic>;
Future<Map<String, dynamic>> getHeader({@required int height}) async =>
Future<Map<String, dynamic>> getHeader({required int height}) async =>
await call(method: 'blockchain.block.get_header', params: [height])
as Map<String, dynamic>;
Future<double> estimatefee({@required int p}) =>
Future<double> estimatefee({required int p}) =>
call(method: 'blockchain.estimatefee', params: [p])
.then((dynamic result) {
if (result is double) {
@ -266,13 +275,26 @@ class ElectrumClient {
Future<List<List<int>>> feeHistogram() =>
call(method: 'mempool.get_fee_histogram').then((dynamic result) {
if (result is List) {
return result.map((dynamic e) {
if (e is List) {
return e.map((dynamic ee) => ee is int ? ee : null).toList();
}
// return result.map((dynamic e) {
// if (e is List) {
// return e.map((dynamic ee) => ee is int ? ee : null).toList();
// }
return null;
}).toList();
// return null;
// }).toList();
final histogram = <List<int>>[];
for (final e in result) {
if (e is List) {
final eee = <int>[];
for (final ee in e) {
if (ee is int) {
eee.add(ee);
}
}
histogram.add(eee);
}
}
return histogram;
}
return [];
@ -299,7 +321,7 @@ class ElectrumClient {
}
}
BehaviorSubject<Object> scripthashUpdate(String scripthash) {
BehaviorSubject<Object>? scripthashUpdate(String scripthash) {
_id += 1;
return subscribe<Object>(
id: 'blockchain.scripthash.subscribe:$scripthash',
@ -307,14 +329,14 @@ class ElectrumClient {
params: [scripthash]);
}
BehaviorSubject<T> subscribe<T>(
{@required String id,
@required String method,
BehaviorSubject<T>? subscribe<T>(
{required String id,
required String method,
List<Object> params = const []}) {
try {
final subscription = BehaviorSubject<T>();
_regisrySubscription(id, subscription);
socket.write(jsonrpc(method: method, id: _id, params: params));
socket!.write(jsonrpc(method: method, id: _id, params: params));
return subscription;
} catch(e) {
@ -323,18 +345,18 @@ class ElectrumClient {
}
}
Future<dynamic> call({String method, List<Object> params = const []}) async {
Future<dynamic> call({required String method, List<Object> params = const []}) async {
final completer = Completer<dynamic>();
_id += 1;
final id = _id;
_registryTask(id, completer);
socket.write(jsonrpc(method: method, id: id, params: params));
socket!.write(jsonrpc(method: method, id: id, params: params));
return completer.future;
}
Future<dynamic> callWithTimeout(
{String method,
{required String method,
List<Object> params = const [],
int timeout = 2000}) async {
try {
@ -342,7 +364,7 @@ class ElectrumClient {
_id += 1;
final id = _id;
_registryTask(id, completer);
socket.write(jsonrpc(method: method, id: id, params: params));
socket!.write(jsonrpc(method: method, id: id, params: params));
Timer(Duration(milliseconds: timeout), () {
if (!completer.isCompleted) {
completer.completeError(RequestFailedTimeoutException(method, id));
@ -356,35 +378,35 @@ class ElectrumClient {
}
Future<void> close() async {
_aliveTimer.cancel();
await socket.close();
_aliveTimer?.cancel();
await socket?.close();
onConnectionStatusChange = null;
}
void _registryTask(int id, Completer completer) => _tasks[id.toString()] =
void _registryTask(int id, Completer<dynamic> completer) => _tasks[id.toString()] =
SocketTask(completer: completer, isSubscription: false);
void _regisrySubscription(String id, BehaviorSubject subject) =>
void _regisrySubscription(String id, BehaviorSubject<dynamic> subject) =>
_tasks[id] = SocketTask(subject: subject, isSubscription: true);
void _finish(String id, Object data) {
void _finish(String id, Object? data) {
if (_tasks[id] == null) {
return;
}
if (!(_tasks[id]?.completer?.isCompleted ?? false)) {
_tasks[id]?.completer?.complete(data);
_tasks[id]?.completer!.complete(data);
}
if (!(_tasks[id]?.isSubscription ?? false)) {
_tasks[id] = null;
_tasks.remove(id);
} else {
_tasks[id].subject.add(data);
_tasks[id]?.subject?.add(data);
}
}
void _methodHandler(
{@required String method, @required Map<String, Object> request}) {
{required String method, required Map<String, dynamic> request}) {
switch (method) {
case 'blockchain.scripthash.subscribe':
final params = request['params'] as List<dynamic>;
@ -406,7 +428,7 @@ class ElectrumClient {
_isConnected = isConnected;
}
void _handleResponse(Map<String, Object> response) {
void _handleResponse(Map<String, dynamic> response) {
final method = response['method'];
final id = response['id'] as String;
final result = response['result'];

View file

@ -4,10 +4,10 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_core/balance.dart';
class ElectrumBalance extends Balance {
const ElectrumBalance({@required this.confirmed, @required this.unconfirmed})
const ElectrumBalance({required this.confirmed, required this.unconfirmed})
: super(confirmed, unconfirmed);
factory ElectrumBalance.fromJSON(String jsonSource) {
static ElectrumBalance? fromJSON(String? jsonSource) {
if (jsonSource == null) {
return null;
}
@ -15,8 +15,8 @@ class ElectrumBalance extends Balance {
final decoded = json.decode(jsonSource) as Map;
return ElectrumBalance(
confirmed: decoded['confirmed'] as int ?? 0,
unconfirmed: decoded['unconfirmed'] as int ?? 0);
confirmed: decoded['confirmed'] as int? ?? 0,
unconfirmed: decoded['unconfirmed'] as int? ?? 0);
}
final int confirmed;

View file

@ -17,7 +17,7 @@ class ElectrumTransactionHistory = ElectrumTransactionHistoryBase
abstract class ElectrumTransactionHistoryBase
extends TransactionHistoryBase<ElectrumTransactionInfo> with Store {
ElectrumTransactionHistoryBase(
{@required this.walletInfo, @required String password})
{required this.walletInfo, required String password})
: _password = password,
_height = 0 {
transactions = ObservableMap<String, ElectrumTransactionInfo>();
@ -56,18 +56,18 @@ abstract class ElectrumTransactionHistoryBase
await save();
}
Future<Map<String, Object>> _read() async {
Future<Map<String, dynamic>> _read() async {
final dirPath =
await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
final path = '$dirPath/$_transactionsHistoryFileName';
final content = await read(path: path, password: _password);
return json.decode(content) as Map<String, Object>;
return json.decode(content) as Map<String, dynamic>;
}
Future<void> _load() async {
try {
final content = await _read();
final txs = content['transactions'] as Map<String, Object> ?? {};
final txs = content['transactions'] as Map<String, dynamic> ?? {};
txs.entries.forEach((entry) {
final val = entry.value;
@ -93,11 +93,11 @@ abstract class ElectrumTransactionHistoryBase
transactions[transaction.id] = transaction;
} else {
final originalTx = transactions[transaction.id];
originalTx.confirmations = transaction.confirmations;
originalTx.amount = transaction.amount;
originalTx.height = transaction.height;
originalTx.date ??= transaction.date;
originalTx.isPending = transaction.isPending;
originalTx?.confirmations = transaction.confirmations;
originalTx?.amount = transaction.amount;
originalTx?.height = transaction.height;
originalTx?.date ??= transaction.date;
originalTx?.isPending = transaction.isPending;
}
}
}

View file

@ -10,23 +10,26 @@ import 'package:cw_core/format_amount.dart';
import 'package:cw_core/wallet_type.dart';
class ElectrumTransactionBundle {
ElectrumTransactionBundle(this.originalTransaction, {this.ins, this.time, this.confirmations});
ElectrumTransactionBundle(this.originalTransaction,
{required this.ins,
required this.confirmations,
this.time});
final bitcoin.Transaction originalTransaction;
final List<bitcoin.Transaction> ins;
final int time;
final int? time;
final int confirmations;
}
class ElectrumTransactionInfo extends TransactionInfo {
ElectrumTransactionInfo(this.type,
{@required String id,
@required int height,
@required int amount,
@required int fee,
@required TransactionDirection direction,
@required bool isPending,
@required DateTime date,
@required int confirmations}) {
{required String id,
required int height,
required int amount,
int? fee,
required TransactionDirection direction,
required bool isPending,
required DateTime date,
required int confirmations}) {
this.id = id;
this.height = height;
this.amount = amount;
@ -39,15 +42,15 @@ class ElectrumTransactionInfo extends TransactionInfo {
factory ElectrumTransactionInfo.fromElectrumVerbose(
Map<String, Object> obj, WalletType type,
{@required List<BitcoinAddressRecord> addresses, @required int height}) {
{required List<BitcoinAddressRecord> addresses, required int height}) {
final addressesSet = addresses.map((addr) => addr.address).toSet();
final id = obj['txid'] as String;
final vins = obj['vin'] as List<Object> ?? [];
final vout = (obj['vout'] as List<Object> ?? []);
final vins = obj['vin'] as List<Object>? ?? [];
final vout = (obj['vout'] as List<Object>? ?? []);
final date = obj['time'] is int
? DateTime.fromMillisecondsSinceEpoch((obj['time'] as int) * 1000)
: DateTime.now();
final confirmations = obj['confirmations'] as int ?? 0;
final confirmations = obj['confirmations'] as int? ?? 0;
var direction = TransactionDirection.incoming;
var inputsAmount = 0;
var amount = 0;
@ -57,21 +60,21 @@ class ElectrumTransactionInfo extends TransactionInfo {
final vout = vin['vout'] as int;
final out = vin['tx']['vout'][vout] as Map;
final outAddresses =
(out['scriptPubKey']['addresses'] as List<Object>)?.toSet();
(out['scriptPubKey']['addresses'] as List<Object>?)?.toSet();
inputsAmount +=
stringDoubleToBitcoinAmount((out['value'] as double ?? 0).toString());
stringDoubleToBitcoinAmount((out['value'] as double? ?? 0).toString());
if (outAddresses?.intersection(addressesSet)?.isNotEmpty ?? false) {
if (outAddresses?.intersection(addressesSet).isNotEmpty ?? false) {
direction = TransactionDirection.outgoing;
}
}
for (dynamic out in vout) {
final outAddresses =
out['scriptPubKey']['addresses'] as List<Object> ?? [];
out['scriptPubKey']['addresses'] as List<Object>? ?? [];
final ntrs = outAddresses.toSet().intersection(addressesSet);
final value = stringDoubleToBitcoinAmount(
(out['value'] as double ?? 0.0).toString());
(out['value'] as double? ?? 0.0).toString());
totalOutAmount += value;
if ((direction == TransactionDirection.incoming && ntrs.isNotEmpty) ||
@ -97,10 +100,10 @@ class ElectrumTransactionInfo extends TransactionInfo {
ElectrumTransactionBundle bundle,
WalletType type,
bitcoin.NetworkType networkType,
{@required Set<String> addresses,
int height}) {
{required Set<String> addresses,
required int height}) {
final date = bundle.time != null
? DateTime.fromMillisecondsSinceEpoch(bundle.time * 1000)
? DateTime.fromMillisecondsSinceEpoch(bundle.time! * 1000)
: DateTime.now();
var direction = TransactionDirection.incoming;
var amount = 0;
@ -111,21 +114,21 @@ class ElectrumTransactionInfo extends TransactionInfo {
final input = bundle.originalTransaction.ins[i];
final inputTransaction = bundle.ins[i];
final vout = input.index;
final outTransaction = inputTransaction.outs[vout];
final address = addressFromOutput(outTransaction.script, networkType);
inputAmount += outTransaction.value;
final outTransaction = inputTransaction.outs[vout!];
final address = addressFromOutput(outTransaction.script!, networkType);
inputAmount += outTransaction.value!;
if (addresses.contains(address)) {
direction = TransactionDirection.outgoing;
}
}
for (final out in bundle.originalTransaction.outs) {
totalOutAmount += out.value;
final address = addressFromOutput(out.script, networkType);
totalOutAmount += out.value!;
final address = addressFromOutput(out.script!, networkType);
final addressExists = addresses.contains(address);
if ((direction == TransactionDirection.incoming && addressExists) ||
(direction == TransactionDirection.outgoing && !addressExists)) {
amount += out.value;
amount += out.value!;
}
}
@ -142,7 +145,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
}
factory ElectrumTransactionInfo.fromHexAndHeader(WalletType type, String hex,
{List<String> addresses, int height, int timestamp, int confirmations}) {
{List<String>? addresses, required int height, int? timestamp, required int confirmations}) {
final tx = bitcoin.Transaction.fromHex(hex);
var exist = false;
var amount = 0;
@ -155,7 +158,7 @@ class ElectrumTransactionInfo extends TransactionInfo {
exist = addresses.contains(p2pkh.data.address);
if (exist) {
amount += out.value;
amount += out.value!;
}
} catch (_) {}
});
@ -191,15 +194,15 @@ class ElectrumTransactionInfo extends TransactionInfo {
final WalletType type;
String _fiatAmount;
String? _fiatAmount;
@override
String amountFormatted() =>
'${formatAmount(bitcoinAmountToString(amount: amount))} ${walletTypeToCryptoCurrency(type).title}';
@override
String feeFormatted() => fee != null
? '${formatAmount(bitcoinAmountToString(amount: fee))} ${walletTypeToCryptoCurrency(type).title}'
String? feeFormatted() => fee != null
? '${formatAmount(bitcoinAmountToString(amount: fee!))} ${walletTypeToCryptoCurrency(type).title}'
: '';
@override
@ -225,7 +228,9 @@ class ElectrumTransactionInfo extends TransactionInfo {
m['id'] = id;
m['height'] = height;
m['amount'] = amount;
m['direction'] = direction.index;
// FIX-ME: Hardcoded value
// m['direction'] = direction.index;
m['direction'] = 0;
m['date'] = date.millisecondsSinceEpoch;
m['isPending'] = isPending;
m['confirmations'] = confirmations;

View file

@ -34,6 +34,7 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_bitcoin/electrum.dart';
import 'package:hex/hex.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:collection/collection.dart';
part 'electrum_wallet.g.dart';
@ -42,31 +43,34 @@ class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
ElectrumTransactionHistory, ElectrumTransactionInfo> with Store {
ElectrumWalletBase(
{@required String password,
@required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo,
@required List<BitcoinAddressRecord> initialAddresses,
@required this.networkType,
@required this.mnemonic,
ElectrumClient electrumClient,
ElectrumBalance initialBalance})
: hd = bitcoin.HDWallet.fromSeed(mnemonicToSeedBytes(mnemonic),
network: networkType)
{required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required this.networkType,
required this.mnemonic,
required Uint8List seedBytes,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumClient? electrumClient,
ElectrumBalance? initialBalance,
CryptoCurrency? currency})
: hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
.derivePath("m/0'/0"),
syncStatus = NotConnectedSyncStatus(),
_password = password,
_feeRates = <int>[],
_isTransactionUpdating = false,
unspentCoins = [],
_scripthashesUpdateSubject = {},
balance = ObservableMap<CryptoCurrency, ElectrumBalance>.of(
currency != null
? {currency: initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0)}
: {}),
this.unspentCoinsInfo = unspentCoinsInfo,
super(walletInfo) {
balance = ObservableMap<CryptoCurrency, ElectrumBalance>.of({
currency: initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0)});
this.electrumClient = electrumClient ?? ElectrumClient();
this.walletInfo = walletInfo;
this.unspentCoinsInfo = unspentCoinsInfo;
transactionHistory =
ElectrumTransactionHistory(walletInfo: walletInfo, password: password);
unspentCoins = [];
_scripthashesUpdateSubject = {};
}
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
@ -75,15 +79,15 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
final bitcoin.HDWallet hd;
final String mnemonic;
ElectrumClient electrumClient;
late ElectrumClient electrumClient;
Box<UnspentCoinsInfo> unspentCoinsInfo;
@override
ElectrumWalletAddresses walletAddresses;
late ElectrumWalletAddresses walletAddresses;
@override
@observable
ObservableMap<CryptoCurrency, ElectrumBalance> balance;
late ObservableMap<CryptoCurrency, ElectrumBalance> balance;
@override
@observable
@ -98,7 +102,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
.map((addr) => scriptHash(addr.address, networkType: networkType))
.toList();
String get xpub => hd.base58;
String get xpub => hd.base58!;
@override
String get seed => mnemonic;
@ -107,12 +111,12 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
@override
BitcoinWalletKeys get keys => BitcoinWalletKeys(
wif: hd.wif, privateKey: hd.privKey, publicKey: hd.pubKey);
wif: hd.wif!, privateKey: hd.privKey!, publicKey: hd.pubKey!);
String _password;
List<BitcoinUnspent> unspentCoins;
List<int> _feeRates;
Map<String, BehaviorSubject<Object>> _scripthashesUpdateSubject;
Map<String, BehaviorSubject<Object>?> _scripthashesUpdateSubject;
bool _isTransactionUpdating;
Future<void> init() async {
@ -137,7 +141,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
(timer) async => _feeRates = await electrumClient.feeRates());
syncStatus = SyncedSyncStatus();
} catch (e) {
} catch (e, stacktrace) {
print(stacktrace);
print(e.toString());
syncStatus = FailedSyncStatus();
}
@ -145,7 +150,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
@action
@override
Future<void> connectToNode({@required Node node}) async {
Future<void> connectToNode({required Node node}) async {
try {
syncStatus = ConnectingSyncStatus();
await electrumClient.connectToUri(node.uri);
@ -187,7 +192,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
}
final allAmountFee = feeAmountForPriority(
transactionCredentials.priority, inputs.length, outputs.length);
transactionCredentials.priority!, inputs.length, outputs.length);
final allAmount = allInputsAmount - allAmountFee;
var credentialsAmount = 0;
@ -196,12 +201,12 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
if (hasMultiDestination) {
if (outputs.any((item) => item.sendAll
|| item.formattedCryptoAmount <= 0)) {
|| item.formattedCryptoAmount! <= 0)) {
throw BitcoinTransactionWrongBalanceException(currency);
}
credentialsAmount = outputs.fold(0, (acc, value) =>
acc + value.formattedCryptoAmount);
acc + value.formattedCryptoAmount!);
if (allAmount - credentialsAmount < minAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
@ -210,7 +215,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
amount = credentialsAmount;
if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate, amount,
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount,
outputsCount: outputs.length + 1);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount,
@ -219,7 +224,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
} else {
final output = outputs.first;
credentialsAmount = !output.sendAll
? output.formattedCryptoAmount
? output.formattedCryptoAmount!
: 0;
if (credentialsAmount > allAmount) {
@ -233,7 +238,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
if (output.sendAll || amount == allAmount) {
fee = allAmountFee;
} else if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate, amount);
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount);
}
@ -245,7 +250,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
final totalAmount = amount + fee;
if (totalAmount > balance[currency].confirmed || totalAmount > allInputsAmount) {
if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
}
@ -298,11 +303,11 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
? item.formattedCryptoAmount
: amount;
final outputAddress = item.isParsedAddress
? item.extractedAddress
? item.extractedAddress!
: item.address;
txb.addOutput(
addressToOutputScript(outputAddress, networkType),
outputAmount);
outputAmount!);
});
final estimatedSize =
@ -310,9 +315,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
var feeAmount = 0;
if (transactionCredentials.feeRate != null) {
feeAmount = transactionCredentials.feeRate * estimatedSize;
feeAmount = transactionCredentials.feeRate! * estimatedSize;
} else {
feeAmount = feeRate(transactionCredentials.priority) * estimatedSize;
feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize;
}
final changeValue = totalInputAmount - amount - feeAmount;
@ -369,8 +374,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
feeRate * estimatedTransactionSize(inputsCount, outputsCount);
@override
int calculateEstimatedFee(TransactionPriority priority, int amount,
{int outputsCount}) {
int calculateEstimatedFee(TransactionPriority? priority, int? amount,
{int? outputsCount}) {
if (priority is BitcoinTransactionPriority) {
return calculateEstimatedFeeWithFeeRate(
feeRate(priority),
@ -381,8 +386,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
return 0;
}
int calculateEstimatedFeeWithFeeRate(int feeRate, int amount,
{int outputsCount}) {
int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount,
{int? outputsCount}) {
int inputsCount = 0;
if (amount != null) {
@ -429,16 +434,16 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
await transactionHistory.changePassword(password);
}
bitcoin.ECPair keyPairFor({@required int index}) =>
bitcoin.ECPair keyPairFor({required int index}) =>
generateKeyPair(hd: hd, index: index, network: networkType);
@override
Future<void> rescan({int height}) async => throw UnimplementedError();
Future<void> rescan({required int height}) async => throw UnimplementedError();
@override
Future<void> close() async {
try {
await electrumClient?.close();
await electrumClient.close();
} catch (_) {}
}
@ -450,7 +455,13 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
.addresses.map((address) => electrumClient
.getListUnspentWithAddress(address.address, networkType)
.then((unspent) => unspent
.map((unspent) => BitcoinUnspent.fromJSON(address, unspent)))));
.map((unspent) {
try {
return BitcoinUnspent.fromJSON(address, unspent);
} catch(_) {
return null;
}
}).whereNotNull())));
unspentCoins = unspent.expand((e) => e).toList();
if (unspentCoinsInfo.isEmpty) {
@ -484,7 +495,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
hash: coin.hash,
isFrozen: coin.isFrozen,
isSending: coin.isSending,
note: coin.note
noteRaw: coin.note
);
await unspentCoinsInfo.add(newInfo);
@ -498,10 +509,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
if (currentWalletUnspentCoins.isNotEmpty) {
currentWalletUnspentCoins.forEach((element) {
final existUnspentCoins = unspentCoins
?.where((coin) => element.hash.contains(coin?.hash));
final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash));
if (existUnspentCoins?.isEmpty ?? true) {
if (existUnspentCoins.isEmpty) {
keys.add(element.key);
}
});
@ -516,7 +526,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
}
Future<ElectrumTransactionBundle> getTransactionExpanded(
{@required String hash, @required int height}) async {
{required String hash, required int height}) async {
final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash);
final transactionHex = verboseTransaction['hex'] as String;
final original = bitcoin.Transaction.fromHex(transactionHex);
@ -525,7 +535,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
final confirmations = verboseTransaction['confirmations'] as int ?? 0;
for (final vin in original.ins) {
final id = HEX.encode(vin.hash.reversed.toList());
final id = HEX.encode(vin.hash!.reversed.toList());
final txHex = await electrumClient.getTransactionHex(hash: id);
final tx = bitcoin.Transaction.fromHex(txHex);
ins.add(tx);
@ -538,8 +548,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
confirmations: confirmations);
}
Future<ElectrumTransactionInfo> fetchTransactionInfo(
{@required String hash, @required int height}) async {
Future<ElectrumTransactionInfo?> fetchTransactionInfo(
{required String hash, required int height}) async {
try {
final tx = await getTransactionExpanded(hash: hash, height: height);
final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet();
return ElectrumTransactionInfo.fromElectrumBundle(
@ -548,6 +559,9 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
networkType,
addresses: addresses,
height: height);
} catch(_) {
return null;
}
}
@override
@ -567,19 +581,27 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
history.entries.forEach((historyItem) {
if (historyItem.value.isNotEmpty) {
final address = addressHashes[historyItem.key];
address.setAsUsed();
address?.setAsUsed();
normalizedHistories.addAll(historyItem.value);
}
});
});
final historiesWithDetails = await Future.wait(
normalizedHistories
.map((transaction) => fetchTransactionInfo(
hash: transaction['tx_hash'] as String,
height: transaction['height'] as int)));
.map((transaction) {
try {
return fetchTransactionInfo(
hash: transaction['tx_hash'] as String,
height: transaction['height'] as int);
} catch(_) {
return Future.value(null);
}
}));
return historiesWithDetails.fold<Map<String, ElectrumTransactionInfo>>(
<String, ElectrumTransactionInfo>{}, (acc, tx) {
if (tx == null) {
return acc;
}
acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx;
return acc;
});
@ -597,7 +619,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
walletAddresses.updateReceiveAddresses();
await transactionHistory.save();
_isTransactionUpdating = false;
} catch (e) {
} catch (e, stacktrace) {
print(stacktrace);
print(e);
_isTransactionUpdating = false;
}
@ -637,8 +660,8 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
for (var i = 0; i < balances.length; i++) {
final addressRecord = addresses[i];
final balance = balances[i];
final confirmed = balance['confirmed'] as int ?? 0;
final unconfirmed = balance['unconfirmed'] as int ?? 0;
final confirmed = balance['confirmed'] as int? ?? 0;
final unconfirmed = balance['unconfirmed'] as int? ?? 0;
totalConfirmed += confirmed;
totalUnconfirmed += unconfirmed;

View file

@ -4,7 +4,6 @@ import 'package:cw_bitcoin/electrum.dart';
import 'package:cw_bitcoin/script_hash.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
part 'electrum_wallet_addresses.g.dart';
@ -14,13 +13,13 @@ class ElectrumWalletAddresses = ElectrumWalletAddressesBase
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
ElectrumWalletAddressesBase(WalletInfo walletInfo,
{@required List<BitcoinAddressRecord> initialAddresses,
{required this.mainHd,
required this.sideHd,
required this.electrumClient,
required this.networkType,
List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0,
this.mainHd,
this.sideHd,
this.electrumClient,
this.networkType})
int initialChangeAddressIndex = 0})
: addresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? []).toSet()),
receiveAddresses = ObservableList<BitcoinAddressRecord>.of(
@ -31,10 +30,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
(initialAddresses ?? [])
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed)
.toSet()),
super(walletInfo) {
currentReceiveAddressIndex = initialRegularAddressIndex;
currentChangeAddressIndex = initialChangeAddressIndex;
}
currentReceiveAddressIndex = initialRegularAddressIndex,
currentChangeAddressIndex = initialChangeAddressIndex,
super(walletInfo);
static const defaultReceiveAddressesCount = 22;
static const defaultChangeAddressesCount = 17;
@ -124,17 +122,18 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
Future<BitcoinAddressRecord> generateNewAddress(
{bool isHidden = false, bitcoin.HDWallet hd}) async {
{bitcoin.HDWallet? hd, bool isHidden = false}) async {
currentReceiveAddressIndex += 1;
// FIX-ME: Check logic for whichi HD should be used here ???
final address = BitcoinAddressRecord(
getAddress(index: currentReceiveAddressIndex, hd: hd),
getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd),
index: currentReceiveAddressIndex,
isHidden: isHidden);
addresses.add(address);
return address;
}
String getAddress({@required int index, @required bitcoin.HDWallet hd}) => '';
String getAddress({required int index, required bitcoin.HDWallet hd}) => '';
@override
Future<void> updateAddressesInBox() async {
@ -239,7 +238,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
{int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async {
{required bitcoin.HDWallet hd, int startIndex = 0, bool isHidden = false}) async {
final list = <BitcoinAddressRecord>[];
for (var i = startIndex; i < count + startIndex; i++) {

View file

@ -6,7 +6,15 @@ import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_type.dart';
class ElectrumWallletSnapshot {
ElectrumWallletSnapshot(this.name, this.type, this.password);
ElectrumWallletSnapshot({
required this.name,
required this.type,
required this.password,
required this.mnemonic,
required this.addresses,
required this.balance,
required this.regularAddressIndex,
required this.changeAddressIndex});
final String name;
final String password;
@ -18,28 +26,34 @@ class ElectrumWallletSnapshot {
int regularAddressIndex;
int changeAddressIndex;
Future<void> load() async {
try {
final path = await pathForWallet(name: name, type: type);
final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map;
final addressesTmp = data['addresses'] as List ?? <Object>[];
mnemonic = data['mnemonic'] as String;
addresses = addressesTmp
.whereType<String>()
.map((addr) => BitcoinAddressRecord.fromJSON(addr))
.toList();
balance = ElectrumBalance.fromJSON(data['balance'] as String) ??
ElectrumBalance(confirmed: 0, unconfirmed: 0);
regularAddressIndex = 0;
changeAddressIndex = 0;
static Future<ElectrumWallletSnapshot> load(String name, WalletType type, String password) async {
final path = await pathForWallet(name: name, type: type);
final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map;
final addressesTmp = data['addresses'] as List? ?? <Object>[];
final mnemonic = data['mnemonic'] as String;
final addresses = addressesTmp
.whereType<String>()
.map((addr) => BitcoinAddressRecord.fromJSON(addr))
.toList();
final balance = ElectrumBalance.fromJSON(data['balance'] as String) ??
ElectrumBalance(confirmed: 0, unconfirmed: 0);
var regularAddressIndex = 0;
var changeAddressIndex = 0;
try {
regularAddressIndex = int.parse(data['account_index'] as String);
changeAddressIndex = int.parse(data['change_address_index'] as String);
} catch (_) {}
} catch (e) {
print(e);
}
try {
regularAddressIndex = int.parse(data['account_index'] as String? ?? '0');
changeAddressIndex = int.parse(data['change_address_index'] as String? ?? '0');
} catch (_) {}
return ElectrumWallletSnapshot(
name: name,
type: type,
password: password,
mnemonic: mnemonic,
addresses: addresses,
balance: balance,
regularAddressIndex: regularAddressIndex,
changeAddressIndex: changeAddressIndex);
}
}

View file

@ -1,12 +1,11 @@
import 'dart:io';
import 'package:cw_core/key.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
Future<void> write(
{@required String path,
@required String password,
@required String data}) async {
{required String path,
required String password,
required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);
@ -16,9 +15,9 @@ Future<void> write(
}
Future<void> writeData(
{@required String path,
@required String password,
@required String data}) async {
{required String path,
required String password,
required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);
@ -27,7 +26,7 @@ Future<void> writeData(
f.writeAsStringSync(encrypted);
}
Future<String> read({@required String path, @required String password}) async {
Future<String> read({required String path, required String password}) async {
final file = File(path);
if (!file.existsSync()) {

View file

@ -1,5 +1,6 @@
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
import 'package:cw_core/transaction_priority.dart';
@ -20,12 +21,13 @@ class LitecoinWallet = LitecoinWalletBase with _$LitecoinWallet;
abstract class LitecoinWalletBase extends ElectrumWallet with Store {
LitecoinWalletBase(
{@required String mnemonic,
@required String password,
@required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord> initialAddresses,
ElectrumBalance initialBalance,
{required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required Uint8List seedBytes,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0})
: super(
@ -35,7 +37,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo,
networkType: litecoinNetwork,
initialAddresses: initialAddresses,
initialBalance: initialBalance) {
initialBalance: initialBalance,
seedBytes: seedBytes,
currency: CryptoCurrency.ltc) {
walletAddresses = LitecoinWalletAddresses(
walletInfo,
electrumClient: electrumClient,
@ -44,19 +48,40 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd,
sideHd: bitcoin.HDWallet
.fromSeed(mnemonicToSeedBytes(mnemonic), network: networkType)
.fromSeed(seedBytes, network: networkType)
.derivePath("m/0'/1"),
networkType: networkType,);
}
static Future<LitecoinWallet> open({
@required String name,
@required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo,
@required String password,
static Future<LitecoinWallet> create({
required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0
}) async {
final snp = ElectrumWallletSnapshot(name, walletInfo.type, password);
await snp.load();
return LitecoinWallet(
mnemonic: mnemonic,
password: password,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: initialAddresses,
initialBalance: initialBalance,
seedBytes: await mnemonicToSeedBytes(mnemonic),
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex);
}
static Future<LitecoinWallet> open({
required String name,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password,
}) async {
final snp = await ElectrumWallletSnapshot.load (name, walletInfo.type, password);
return LitecoinWallet(
mnemonic: snp.mnemonic,
password: password,
@ -64,6 +89,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: snp.addresses,
initialBalance: snp.balance,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex);
}

View file

@ -16,13 +16,13 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
with Store {
LitecoinWalletAddressesBase(
WalletInfo walletInfo,
{@required List<BitcoinAddressRecord> initialAddresses,
{required bitcoin.HDWallet mainHd,
required bitcoin.HDWallet sideHd,
required bitcoin.NetworkType networkType,
required ElectrumClient electrumClient,
List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0,
ElectrumClient electrumClient,
@required bitcoin.HDWallet mainHd,
@required bitcoin.HDWallet sideHd,
@required bitcoin.NetworkType networkType})
int initialChangeAddressIndex = 0})
: super(
walletInfo,
initialAddresses: initialAddresses,
@ -34,6 +34,6 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
networkType: networkType);
@override
String getAddress({@required int index, @required bitcoin.HDWallet hd}) =>
String getAddress({required int index, required bitcoin.HDWallet hd}) =>
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
}

View file

@ -10,6 +10,7 @@ import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:collection/collection.dart';
class LitecoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
@ -25,10 +26,10 @@ class LitecoinWalletService extends WalletService<
@override
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async {
final wallet = LitecoinWallet(
final wallet = await LitecoinWalletBase.create(
mnemonic: await generateMnemonic(),
password: credentials.password,
walletInfo: credentials.walletInfo,
password: credentials.password!,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save();
await wallet.init();
@ -42,9 +43,8 @@ class LitecoinWalletService extends WalletService<
@override
Future<LitecoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, getType()),
orElse: () => null);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await LitecoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource);
@ -69,10 +69,10 @@ class LitecoinWalletService extends WalletService<
throw BitcoinMnemonicIsIncorrectException();
}
final wallet = LitecoinWallet(
password: credentials.password,
final wallet = await LitecoinWalletBase.create(
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save();
await wallet.init();

View file

@ -1,5 +1,4 @@
import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart';
import 'package:flutter/foundation.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_bitcoin/electrum.dart';
@ -10,9 +9,9 @@ import 'package:cw_core/wallet_type.dart';
class PendingBitcoinTransaction with PendingTransaction {
PendingBitcoinTransaction(this._tx, this.type,
{@required this.electrumClient,
@required this.amount,
@required this.fee})
{required this.electrumClient,
required this.amount,
required this.fee})
: _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
final WalletType type;

View file

@ -1,8 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:crypto/crypto.dart';
String scriptHash(String address, {@required bitcoin.NetworkType networkType}) {
String scriptHash(String address, {required bitcoin.NetworkType networkType}) {
final outputScript =
bitcoin.Address.addressToOutputScript(address, networkType);
final parts = sha256.convert(outputScript).toString().split('');

View file

@ -5,51 +5,51 @@ import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
import 'package:hex/hex.dart';
bitcoin.PaymentData generatePaymentData(
{@required bitcoin.HDWallet hd, @required int index}) =>
{required bitcoin.HDWallet hd, required int index}) =>
PaymentData(
pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey)));
pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!)));
bitcoin.ECPair generateKeyPair(
{@required bitcoin.HDWallet hd,
@required int index,
bitcoin.NetworkType network}) =>
bitcoin.ECPair.fromWIF(hd.derive(index).wif, network: network);
{required bitcoin.HDWallet hd,
required int index,
required bitcoin.NetworkType network}) =>
bitcoin.ECPair.fromWIF(hd.derive(index).wif!, network: network);
String generateP2WPKHAddress(
{@required bitcoin.HDWallet hd,
@required int index,
bitcoin.NetworkType networkType}) =>
{required bitcoin.HDWallet hd,
required int index,
required bitcoin.NetworkType networkType}) =>
bitcoin
.P2WPKH(
data: PaymentData(
pubkey:
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey))),
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))),
network: networkType)
.data
.address;
.address!;
String generateP2WPKHAddressByPath(
{@required bitcoin.HDWallet hd,
@required String path,
bitcoin.NetworkType networkType}) =>
{required bitcoin.HDWallet hd,
required String path,
required bitcoin.NetworkType networkType}) =>
bitcoin
.P2WPKH(
data: PaymentData(
pubkey:
Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey))),
Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey!))),
network: networkType)
.data
.address;
.address!;
String generateP2PKHAddress(
{@required bitcoin.HDWallet hd,
@required int index,
bitcoin.NetworkType networkType}) =>
{required bitcoin.HDWallet hd,
required int index,
required bitcoin.NetworkType networkType}) =>
bitcoin
.P2PKH(
data: PaymentData(
pubkey:
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey))),
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))),
network: networkType)
.data
.address;
.address!;

View file

@ -7,64 +7,64 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "14.0.0"
version: "47.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.41.2"
version: "4.7.0"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
version: "2.3.1"
asn1lib:
dependency: transitive
description:
name: asn1lib
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.5"
version: "1.1.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.0"
version: "2.9.0"
bech32:
dependency: transitive
description:
path: "."
ref: cake
resolved-ref: "02fef082f20af13de00b4e64efb93a2c1e5e1cf2"
ref: "cake-0.2.1"
resolved-ref: cafd1c270641e95017d57d69f55cca9831d4db56
url: "https://github.com/cake-tech/bech32.git"
source: git
version: "0.2.0"
version: "0.2.1"
bip32:
dependency: transitive
description:
name: bip32
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.7"
version: "2.0.0"
bip39:
dependency: transitive
description:
name: bip39
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "1.0.6"
bitcoin_flutter:
dependency: "direct main"
description:
path: "."
ref: cake
resolved-ref: cbabfd87b6ce3cae6051a3e86ddb56e7a934e188
ref: cake-update-v2
resolved-ref: "8f86453761c0c26e368392d0ff2c6f12f3b7397b"
url: "https://github.com/cake-tech/bitcoin_flutter.git"
source: git
version: "2.0.2"
@ -81,133 +81,119 @@ packages:
name: bs58check
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.0.2"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.2"
version: "2.3.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.6"
version: "1.1.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.10"
version: "3.1.0"
build_resolvers:
dependency: "direct dev"
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.3"
version: "2.0.10"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.5"
version: "2.2.1"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.10"
version: "7.2.4"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "4.3.2"
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "7.1.0"
version: "8.4.1"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
version: "2.0.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.0"
version: "4.3.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
version: "1.16.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "3.0.2"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "3.0.2"
cryptography:
dependency: "direct main"
description:
name: cryptography
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.1"
version: "2.0.5"
cw_core:
dependency: "direct main"
description:
@ -221,35 +207,28 @@ packages:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.12"
dartx:
dependency: transitive
description:
name: dartx
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0"
version: "2.2.4"
encrypt:
dependency: "direct main"
description:
name: encrypt
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.3"
version: "5.0.1"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "2.0.1"
file:
dependency: transitive
description:
@ -263,7 +242,7 @@ packages:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.11"
version: "1.0.1"
flutter:
dependency: "direct main"
description: flutter
@ -275,12 +254,19 @@ packages:
name: flutter_mobx
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0+2"
version: "2.0.6+4"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
glob:
dependency: transitive
description:
@ -294,49 +280,49 @@ packages:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
version: "2.1.0"
hex:
dependency: transitive
description:
name: hex
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
version: "0.2.0"
hive:
dependency: transitive
description:
name: hive
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.4+1"
version: "2.2.3"
hive_generator:
dependency: "direct dev"
description:
name: hive_generator
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.2"
version: "1.1.3"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.2"
version: "0.13.5"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
version: "4.0.1"
intl:
dependency: "direct main"
description:
@ -350,7 +336,7 @@ packages:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
version: "1.0.3"
js:
dependency: transitive
description:
@ -364,7 +350,7 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.7.0"
logging:
dependency: transitive
description:
@ -378,14 +364,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.10"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.8.0"
mime:
dependency: transitive
description:
@ -399,63 +392,77 @@ packages:
name: mobx
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1+4"
version: "2.1.0"
mobx_codegen:
dependency: "direct dev"
description:
name: mobx_codegen
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "2.0.7+3"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
version: "2.1.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.8.2"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.28"
version: "2.0.11"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.20"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+2"
version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+8"
version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "2.0.5"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.5"
version: "2.1.3"
pedantic:
dependency: transitive
description:
@ -476,14 +483,14 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "2.1.3"
pointycastle:
dependency: transitive
description:
name: pointycastle
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "3.6.2"
pool:
dependency: transitive
description:
@ -511,35 +518,28 @@ packages:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.8"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "1.2.1"
rxdart:
dependency: "direct main"
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.26.0"
version: "0.27.5"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.9"
version: "1.4.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.4+1"
version: "1.0.2"
sky_engine:
dependency: transitive
description: flutter
@ -551,14 +551,21 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.10+3"
version: "1.2.5"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.3"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
@ -586,35 +593,28 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.19"
time:
dependency: transitive
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.1"
version: "0.4.12"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1+3"
version: "1.0.0"
typed_data:
dependency: transitive
description:
@ -635,7 +635,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.2"
watcher:
dependency: transitive
description:
@ -649,21 +649,21 @@ packages:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "2.2.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "3.0.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
version: "0.2.0+2"
yaml:
dependency: transitive
description:
@ -672,5 +672,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dart: ">=2.17.5 <3.0.0"
flutter: ">=3.0.0"

View file

@ -6,35 +6,35 @@ author: Cake Wallet
homepage: https://cakewallet.com
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.17.0"
sdk: ">=2.17.5 <3.0.0"
flutter: ">=1.20.0"
dependencies:
flutter:
sdk: flutter
path_provider: ^1.4.0
http: ^0.12.0+2
mobx: ^1.2.1+2
flutter_mobx: ^1.1.0+2
path_provider: ^2.0.11
http: ^0.13.4
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
cw_core:
path: ../cw_core
bitcoin_flutter:
git:
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake
rxdart: ^0.26.0
ref: cake-update-v2
rxdart: ^0.27.5
unorm_dart: ^0.2.0
cryptography: ^1.4.0
encrypt: ^4.0.0
cryptography: ^2.0.5
encrypt: ^5.0.1
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.10.3
build_resolvers: ^1.3.10
mobx_codegen: ^1.1.0+1
hive_generator: ^0.8.1
build_runner: ^2.1.11
build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7
hive_generator: ^1.1.3
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

View file

@ -1,7 +1,7 @@
class Account {
Account({this.id, this.label});
Account({required this.id, required this.label});
Account.fromMap(Map map)
Account.fromMap(Map<String, Object> map)
: this.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
this.label = (map['label'] ?? '') as String;

View file

@ -8,9 +8,9 @@ abstract class AccountList<T> {
List<T> getAll();
Future addAccount({String label});
Future<void> addAccount({required String label});
Future setLabelAccount({int accountIndex, String label});
Future<void> setLabelAccount({required int accountIndex, required String label});
void refresh();
}

View file

@ -47,7 +47,7 @@ class AmountConverter {
case CryptoCurrency.xusd:
return _moneroAmountToDouble(amount);
default:
return null;
return 0.0;
}
}
@ -71,7 +71,7 @@ class AmountConverter {
case CryptoCurrency.xusd:
return _moneroParseAmount(amount);
default:
return null;
return 0;
}
}
@ -97,11 +97,11 @@ class AmountConverter {
case CryptoCurrency.xusd:
return _moneroAmountToString(amount);
default:
return null;
return '';
}
}
static double cryptoAmountToDouble({num amount, num divider}) =>
static double cryptoAmountToDouble({required num amount, required num divider}) =>
amount / divider;
static String _moneroAmountToString(int amount) => _moneroAmountFormat.format(

View file

@ -1 +1 @@
double cryptoAmountToDouble({num amount, num divider}) => amount / divider;
double cryptoAmountToDouble({required num amount, required num divider}) => amount / divider;

View file

@ -5,12 +5,17 @@ part 'crypto_currency.g.dart';
@HiveType(typeId: 0)
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
const CryptoCurrency({final String title, this.tag, this.name, this.iconPath, final int raw})
const CryptoCurrency({
String title = '',
int raw = -1,
this.name,
this.iconPath,
this.tag,})
: super(title: title, raw: raw);
final String tag;
final String name;
final String iconPath;
final String? tag;
final String? name;
final String? iconPath;
static const all = [
CryptoCurrency.xmr,
@ -23,16 +28,49 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
CryptoCurrency.eos,
CryptoCurrency.eth,
CryptoCurrency.ltc,
CryptoCurrency.nano,
CryptoCurrency.trx,
CryptoCurrency.usdt,
CryptoCurrency.usdterc20,
CryptoCurrency.xlm,
CryptoCurrency.xrp,
CryptoCurrency.xhv,
//CryptoCurrency.zaddr,
//CryptoCurrency.zec
CryptoCurrency.ape,
CryptoCurrency.avaxc,
CryptoCurrency.btt,
CryptoCurrency.bttbsc,
CryptoCurrency.doge,
CryptoCurrency.firo,
CryptoCurrency.usdttrc20,
CryptoCurrency.hbar,
CryptoCurrency.sc,
CryptoCurrency.sol,
CryptoCurrency.usdc,
CryptoCurrency.usdcsol,
CryptoCurrency.zaddr,
CryptoCurrency.zec,
CryptoCurrency.zen,
CryptoCurrency.xvg,
CryptoCurrency.usdcpoly,
CryptoCurrency.dcr,
CryptoCurrency.husd,
CryptoCurrency.kmd,
CryptoCurrency.mana,
CryptoCurrency.maticpoly,
CryptoCurrency.matic,
CryptoCurrency.mkr,
CryptoCurrency.near,
CryptoCurrency.oxt,
CryptoCurrency.paxg,
CryptoCurrency.pivx,
CryptoCurrency.rune,
CryptoCurrency.rvn,
CryptoCurrency.scrt,
CryptoCurrency.uni,
CryptoCurrency.stx,
];
static const xmr = CryptoCurrency(title: 'XMR', iconPath: 'assets/images/monero_icon.png', name: 'Monero', raw: 0);
static const xmr = CryptoCurrency(title: 'XMR', iconPath: 'assets/images/monero_icon.png', name: 'Monero', raw: 0);
static const ada = CryptoCurrency(title: 'ADA', iconPath: 'assets/images/ada_icon.png', name: 'Cardano', raw: 1);
static const bch = CryptoCurrency(title: 'BCH', iconPath: 'assets/images/bch_icon.png',name: 'Bitcoin Cash', raw: 2);
static const bnb = CryptoCurrency(title: 'BNB', iconPath: 'assets/images/bnb_icon.png', tag: 'BSC', name: 'Binance Coin', raw: 3);
@ -41,7 +79,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
static const dash = CryptoCurrency(title: 'DASH', iconPath: 'assets/images/dash_icon.png', name: 'Dash', raw: 6);
static const eos = CryptoCurrency(title: 'EOS', iconPath: 'assets/images/eos_icon.png', name: 'EOS', raw: 7);
static const eth = CryptoCurrency(title: 'ETH', iconPath: 'assets/images/eth_icon.png', name: 'Ethereum', raw: 8);
static const ltc = CryptoCurrency(title: 'LTC', iconPath: 'assets/images/litecoin-ltc_icon.png', name: 'Litecoin',raw: 9);
static const ltc = CryptoCurrency(title: 'LTC', iconPath: 'assets/images/litecoin-ltc_icon.png', name: 'Litecoin', raw: 9);
static const nano = CryptoCurrency(title: 'NANO', raw: 10);
static const trx = CryptoCurrency(title: 'TRX', iconPath: 'assets/images/trx_icon.png', name: 'TRON', raw: 11);
static const usdt = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdt_icon.png', tag: 'OMNI', name: 'USDT', raw: 12);
@ -64,10 +102,44 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28);
static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29);
static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', name: 'Shielded Zcash', iconPath: 'assets/images/zaddr_icon.png', raw: 30);
static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', name: 'Transparent Zcash', iconPath: 'assets/images/zec_icon.png', raw: 31);
static const ape = CryptoCurrency(title: 'APE', iconPath: 'assets/images/ape_icon.png', tag: 'ETH', raw: 30);
static const avaxc = CryptoCurrency(title: 'AVAX', iconPath: 'assets/images/avaxc_icon.png', tag: 'C-CHAIN', raw: 31);
static const btt = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/btt_icon.png', raw: 32);
static const bttbsc = CryptoCurrency(title: 'BTT', iconPath: 'assets/images/bttbsc_icon.png', tag: 'BSC', raw: 33);
static const doge = CryptoCurrency(title: 'DOGE', iconPath: 'assets/images/doge_icon.png', raw: 34);
static const firo = CryptoCurrency(title: 'FIRO', iconPath: 'assets/images/firo_icon.png', raw: 35);
static const usdttrc20 = CryptoCurrency(title: 'USDT', iconPath: 'assets/images/usdttrc20_icon.png', tag: 'TRX', raw: 36);
static const hbar = CryptoCurrency(title: 'HBAR', iconPath: 'assets/images/hbar_icon.png', raw: 37);
static const sc = CryptoCurrency(title: 'SC', iconPath: 'assets/images/sc_icon.png', raw: 38);
static const sol = CryptoCurrency(title: 'SOL', iconPath: 'assets/images/sol_icon.png', raw: 39);
static const usdc = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'ETH', raw: 40);
static const usdcsol = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdcsol_icon.png', tag: 'SOL', raw: 41);
static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', name: 'Shielded Zcash', iconPath: 'assets/images/zaddr_icon.png', raw: 42);
static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', name: 'Transparent Zcash', iconPath: 'assets/images/zec_icon.png', raw: 43);
static const zen = CryptoCurrency(title: 'ZEN', iconPath: 'assets/images/zen_icon.png', raw: 44);
static const xvg = CryptoCurrency(title: 'XVG', name: 'Verge', iconPath: 'assets/images/xvg_icon.png', raw: 45);
static CryptoCurrency deserialize({int raw}) {
static const usdcpoly = CryptoCurrency(title: 'USDC', iconPath: 'assets/images/usdc_icon.png', tag: 'POLY', raw: 46);
static const dcr = CryptoCurrency(title: 'DCR', iconPath: 'assets/images/dcr_icon.png', raw: 47);
static const husd = CryptoCurrency(title: 'HUSD', iconPath: 'assets/images/husd_icon.png', tag: 'ETH', raw: 48);
static const kmd = CryptoCurrency(title: 'KMD', iconPath: 'assets/images/kmd_icon.png', raw: 49);
static const mana = CryptoCurrency(title: 'MANA', iconPath: 'assets/images/mana_icon.png', tag: 'ETH', raw: 50);
static const maticpoly = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'POLY', raw: 51);
static const matic = CryptoCurrency(title: 'MATIC', iconPath: 'assets/images/matic_icon.png', tag: 'ETH', raw: 52);
static const mkr = CryptoCurrency(title: 'MKR', iconPath: 'assets/images/mkr_icon.png', tag: 'ETH', raw: 53);
static const near = CryptoCurrency(title: 'NEAR', iconPath: 'assets/images/near_icon.png', raw: 54);
static const oxt = CryptoCurrency(title: 'OXT', iconPath: 'assets/images/oxt_icon.png', tag: 'ETH', raw: 55);
static const paxg = CryptoCurrency(title: 'PAXG', iconPath: 'assets/images/paxg_icon.png', tag: 'ETH', raw: 56);
static const pivx = CryptoCurrency(title: 'PIVX', iconPath: 'assets/images/pivx_icon.png', raw: 57);
static const rune = CryptoCurrency(title: 'RUNE', iconPath: 'assets/images/rune_icon.png', raw: 58);
static const rvn = CryptoCurrency(title: 'RVN', iconPath: 'assets/images/rvn_icon.png', raw: 59);
static const scrt = CryptoCurrency(title: 'SCRT', iconPath: 'assets/images/scrt_icon.png', raw: 60);
static const uni = CryptoCurrency(title: 'UNI', iconPath: 'assets/images/uni_icon.png', tag: 'ETH', raw: 61);
static const stx = CryptoCurrency(title: 'STX', iconPath: 'assets/images/stx_icon.png', raw: 62);
static CryptoCurrency deserialize({required int raw}) {
switch (raw) {
case 0:
return CryptoCurrency.xmr;
@ -130,11 +202,73 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
case 29:
return CryptoCurrency.xusd;
case 30:
return CryptoCurrency.zaddr;
return CryptoCurrency.ape;
case 31:
return CryptoCurrency.avaxc;
case 32:
return CryptoCurrency.btt;
case 33:
return CryptoCurrency.bttbsc;
case 34:
return CryptoCurrency.doge;
case 35:
return CryptoCurrency.firo;
case 36:
return CryptoCurrency.usdttrc20;
case 37:
return CryptoCurrency.hbar;
case 38:
return CryptoCurrency.sc;
case 39:
return CryptoCurrency.sol;
case 40:
return CryptoCurrency.usdc;
case 41:
return CryptoCurrency.usdcsol;
case 42:
return CryptoCurrency.zaddr;
case 43:
return CryptoCurrency.zec;
case 44:
return CryptoCurrency.zen;
case 45:
return CryptoCurrency.xvg;
case 46:
return CryptoCurrency.usdcpoly;
case 47:
return CryptoCurrency.dcr;
case 48:
return CryptoCurrency.husd;
case 49:
return CryptoCurrency.kmd;
case 50:
return CryptoCurrency.mana;
case 51:
return CryptoCurrency.maticpoly;
case 52:
return CryptoCurrency.matic;
case 53:
return CryptoCurrency.mkr;
case 54:
return CryptoCurrency.near;
case 55:
return CryptoCurrency.oxt;
case 56:
return CryptoCurrency.paxg;
case 57:
return CryptoCurrency.pivx;
case 58:
return CryptoCurrency.rune;
case 59:
return CryptoCurrency.rvn;
case 60:
return CryptoCurrency.scrt;
case 61:
return CryptoCurrency.uni;
case 62:
return CryptoCurrency.stx;
default:
return null;
throw Exception('Unexpected token: $raw for CryptoCurrency deserialize');
}
}
@ -164,8 +298,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
return CryptoCurrency.nano;
case 'trx':
return CryptoCurrency.trx;
case 'usdt':
return CryptoCurrency.usdt;
case 'usdc':
return CryptoCurrency.usdc;
case 'usdterc20':
return CryptoCurrency.usdterc20;
case 'xlm':
@ -200,12 +334,74 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
return CryptoCurrency.xnzd;
case 'xusd':
return CryptoCurrency.xusd;
case 'ape':
return CryptoCurrency.ape;
case 'avax':
return CryptoCurrency.avaxc;
case 'btt':
return CryptoCurrency.btt;
case 'bttbsc':
return CryptoCurrency.bttbsc;
case 'doge':
return CryptoCurrency.doge;
case 'firo':
return CryptoCurrency.firo;
case 'usdttrc20':
return CryptoCurrency.usdttrc20;
case 'hbar':
return CryptoCurrency.hbar;
case 'sc':
return CryptoCurrency.sc;
case 'sol':
return CryptoCurrency.sol;
case 'usdt':
return CryptoCurrency.usdt;
case 'usdcsol':
return CryptoCurrency.usdcsol;
case 'zaddr':
return CryptoCurrency.zaddr;
case 'zec':
return CryptoCurrency.zec;
case 'zen':
return CryptoCurrency.zen;
case 'xvg':
return CryptoCurrency.xvg;
case 'usdcpoly':
return CryptoCurrency.usdcpoly;
case 'dcr':
return CryptoCurrency.dcr;
case 'husd':
return CryptoCurrency.husd;
case 'kmd':
return CryptoCurrency.kmd;
case 'mana':
return CryptoCurrency.mana;
case 'maticpoly':
return CryptoCurrency.maticpoly;
case 'matic':
return CryptoCurrency.matic;
case 'mkr':
return CryptoCurrency.mkr;
case 'near':
return CryptoCurrency.near;
case 'oxt':
return CryptoCurrency.oxt;
case 'paxg':
return CryptoCurrency.paxg;
case 'pivx':
return CryptoCurrency.pivx;
case 'rune':
return CryptoCurrency.rune;
case 'rvn':
return CryptoCurrency.rvn;
case 'scrt':
return CryptoCurrency.scrt;
case 'uni':
return CryptoCurrency.uni;
case 'stx':
return CryptoCurrency.stx;
default:
return null;
throw Exception('Unexpected token: $raw for CryptoCurrency fromString');
}
}

View file

@ -12,6 +12,6 @@ CryptoCurrency currencyForWalletType(WalletType type) {
case WalletType.haven:
return CryptoCurrency.xhv;
default:
return null;
throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType');
}
}

View file

@ -1,7 +1,7 @@
import 'package:flutter/foundation.dart';
abstract class EnumerableItem<T> {
const EnumerableItem({@required this.title, @required this.raw});
const EnumerableItem({required this.title, required this.raw});
final T raw;
final String title;
@ -11,6 +11,6 @@ abstract class EnumerableItem<T> {
}
mixin Serializable<T> on EnumerableItem<T> {
static Serializable deserialize<T>({T raw}) => null;
static Serializable deserialize<T>({required T raw}) => throw Exception('Unimplemented');
T serialize() => raw;
}

View file

@ -85,7 +85,7 @@ final dates = {
"2020-11": 2220000
};
int getMoneroHeigthByDate({DateTime date}) {
int getMoneroHeigthByDate({required DateTime date}) {
final raw = '${date.year}' + '-' + '${date.month}';
final lastHeight = dates.values.last;
int startHeight;
@ -105,7 +105,7 @@ int getMoneroHeigthByDate({DateTime date}) {
final daysHeight = (differenceInDays * heightPerDay).round();
height = endHeight + daysHeight;
} else {
startHeight = dates[raw];
startHeight = dates[raw]!;
final index = dates.values.toList().indexOf(startHeight);
endHeight = dates.values.toList()[index + 1];
final heightPerDay = ((endHeight - startHeight) / 31).round();

View file

@ -16,14 +16,14 @@ List<String> extractKeys(String key) {
return [_key, iv];
}
Future<String> encode({encrypt.Key key, encrypt.IV iv, String data}) async {
Future<String> encode({required encrypt.Key key, required encrypt.IV iv, required String data}) async {
final encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
final encrypted = encrypter.encrypt(data, iv: iv);
return encrypted.base64;
}
Future<String> decode({String password, String data}) async {
Future<String> decode({required String password, required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);

View file

@ -7,12 +7,12 @@ final moneroAmountFormat = NumberFormat()
..maximumFractionDigits = moneroAmountLength
..minimumFractionDigits = 1;
String moneroAmountToString({int amount}) => moneroAmountFormat
String moneroAmountToString({required int amount}) => moneroAmountFormat
.format(cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider))
.replaceAll(',', '');
double moneroAmountToDouble({int amount}) =>
double moneroAmountToDouble({required int amount}) =>
cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider);
int moneroParseAmount({String amount}) =>
int moneroParseAmount({required String amount}) =>
(double.parse(amount) * moneroAmountDivider).toInt();

View file

@ -1,17 +1,16 @@
import 'package:cw_core/balance.dart';
import 'package:flutter/foundation.dart';
import 'package:cw_core/monero_amount_format.dart';
class MoneroBalance extends Balance {
MoneroBalance({@required this.fullBalance, @required this.unlockedBalance})
MoneroBalance({required this.fullBalance, required this.unlockedBalance})
: formattedFullBalance = moneroAmountToString(amount: fullBalance),
formattedUnlockedBalance =
moneroAmountToString(amount: unlockedBalance),
super(unlockedBalance, fullBalance);
MoneroBalance.fromString(
{@required this.formattedFullBalance,
@required this.formattedUnlockedBalance})
{required this.formattedFullBalance,
required this.formattedUnlockedBalance})
: fullBalance = moneroParseAmount(amount: formattedFullBalance),
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance),
super(moneroParseAmount(amount: formattedUnlockedBalance),

View file

@ -4,18 +4,18 @@ import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/enumerable_item.dart';
class MoneroTransactionPriority extends TransactionPriority {
const MoneroTransactionPriority({String title, int raw})
const MoneroTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw);
static const all = [
MoneroTransactionPriority.slow,
MoneroTransactionPriority.regular,
MoneroTransactionPriority.automatic,
MoneroTransactionPriority.medium,
MoneroTransactionPriority.fast,
MoneroTransactionPriority.fastest
];
static const slow = MoneroTransactionPriority(title: 'Slow', raw: 0);
static const regular = MoneroTransactionPriority(title: 'Regular', raw: 1);
static const automatic = MoneroTransactionPriority(title: 'Automatic', raw: 1);
static const medium = MoneroTransactionPriority(title: 'Medium', raw: 2);
static const fast = MoneroTransactionPriority(title: 'Fast', raw: 3);
static const fastest = MoneroTransactionPriority(title: 'Fastest', raw: 4);
@ -29,7 +29,7 @@ class MoneroTransactionPriority extends TransactionPriority {
case WalletType.bitcoin:
return [
MoneroTransactionPriority.slow,
MoneroTransactionPriority.regular,
MoneroTransactionPriority.automatic,
MoneroTransactionPriority.fast
];
default:
@ -37,12 +37,12 @@ class MoneroTransactionPriority extends TransactionPriority {
}
}
static MoneroTransactionPriority deserialize({int raw}) {
static MoneroTransactionPriority deserialize({required int raw}) {
switch (raw) {
case 0:
return slow;
case 1:
return regular;
return automatic;
case 2:
return medium;
case 3:
@ -50,7 +50,7 @@ class MoneroTransactionPriority extends TransactionPriority {
case 4:
return fastest;
default:
return null;
throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize');
}
}
@ -59,8 +59,8 @@ class MoneroTransactionPriority extends TransactionPriority {
switch (this) {
case MoneroTransactionPriority.slow:
return 'Slow'; // S.current.transaction_priority_slow;
case MoneroTransactionPriority.regular:
return 'Regular'; // S.current.transaction_priority_regular;
case MoneroTransactionPriority.automatic:
return 'Automatic'; // S.current.transaction_priority_regular;
case MoneroTransactionPriority.medium:
return 'Medium'; // S.current.transaction_priority_medium;
case MoneroTransactionPriority.fast:

View file

@ -1,9 +1,9 @@
class MoneroWalletKeys {
const MoneroWalletKeys(
{this.privateSpendKey,
this.privateViewKey,
this.publicSpendKey,
this.publicViewKey});
{required this.privateSpendKey,
required this.privateViewKey,
required this.publicSpendKey,
required this.publicViewKey});
final String publicViewKey;
final String privateViewKey;

View file

@ -1,7 +1,5 @@
import 'dart:io';
import 'package:cw_core/keyable.dart';
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:hive/hive.dart';
@ -11,44 +9,47 @@ import 'package:http/io_client.dart' as ioc;
part 'node.g.dart';
Uri createUriFromElectrumAddress(String address) =>
Uri.tryParse('tcp://$address');
Uri.tryParse('tcp://$address')!;
@HiveType(typeId: Node.typeId)
class Node extends HiveObject with Keyable {
Node(
{@required String uri,
@required WalletType type,
this.login,
{this.login,
this.password,
this.useSSL}) {
uriRaw = uri;
this.type = type;
this.useSSL,
String? uri,
WalletType? type,}) {
if (uri != null) {
uriRaw = uri;
}
if (type != null) {
this.type = type;
}
}
Node.fromMap(Map map)
: uriRaw = map['uri'] as String ?? '',
login = map['login'] as String,
password = map['password'] as String,
typeRaw = map['typeRaw'] as int,
useSSL = map['useSSL'] as bool;
Node.fromMap(Map<String, Object?> map)
: uriRaw = map['uri'] as String? ?? '',
login = map['login'] as String?,
password = map['password'] as String?,
useSSL = map['useSSL'] as bool?;
static const typeId = 1;
static const boxName = 'Nodes';
@HiveField(0)
String uriRaw;
@HiveField(0, defaultValue: '')
late String uriRaw;
@HiveField(1)
String login;
String? login;
@HiveField(2)
String password;
String? password;
@HiveField(3)
int typeRaw;
@HiveField(3, defaultValue: 0)
late int typeRaw;
@HiveField(4)
bool useSSL;
bool? useSSL;
bool get isSSL => useSSL ?? false;
@ -63,7 +64,7 @@ class Node extends HiveObject with Keyable {
case WalletType.haven:
return Uri.http(uriRaw, '');
default:
return null;
throw Exception('Unexpected type ${type.toString()} for Node uri');
}
}
@ -99,7 +100,6 @@ class Node extends HiveObject with Keyable {
}
Future<bool> requestMoneroNode() async {
final path = '/json_rpc';
final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path);
final realm = 'monero-rpc';

View file

@ -1,20 +1,20 @@
class OutputInfo {
const OutputInfo(
{this.fiatAmount,
this.cryptoAmount,
this.address,
this.note,
this.sendAll,
this.extractedAddress,
this.isParsedAddress,
this.formattedCryptoAmount});
{required this.address,
required this.sendAll,
required this.isParsedAddress,
this.cryptoAmount,
this.formattedCryptoAmount,
this.fiatAmount,
this.note,
this.extractedAddress,});
final String fiatAmount;
final String cryptoAmount;
final String? fiatAmount;
final String? cryptoAmount;
final String address;
final String note;
final String extractedAddress;
final String? note;
final String? extractedAddress;
final bool sendAll;
final bool isParsedAddress;
final int formattedCryptoAmount;
final int? formattedCryptoAmount;
}

View file

@ -3,7 +3,7 @@ import 'package:cw_core/wallet_type.dart';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
Future<String> pathForWalletDir({@required String name, @required WalletType type}) async {
Future<String> pathForWalletDir({required String name, required WalletType type}) async {
final root = await getApplicationDocumentsDirectory();
final prefix = walletTypeToString(type).toLowerCase();
final walletsDir = Directory('${root.path}/wallets');
@ -16,11 +16,11 @@ Future<String> pathForWalletDir({@required String name, @required WalletType ty
return walletDire.path;
}
Future<String> pathForWallet({@required String name, @required WalletType type}) async =>
Future<String> pathForWallet({required String name, required WalletType type}) async =>
await pathForWalletDir(name: name, type: type)
.then((path) => path + '/$name');
Future<String> outdatedAndroidPathForWalletDir({String name}) async {
Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
final directory = await getApplicationDocumentsDirectory();
final pathDir = directory.path + '/$name';

View file

@ -6,7 +6,7 @@ const utils = const MethodChannel('com.cake_wallet/native_utils');
Future<Uint8List> secRandom(int count) async {
try {
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count});
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
} on PlatformException catch (_) {
return Uint8List.fromList([]);
}

View file

@ -1,7 +1,7 @@
class Subaddress {
Subaddress({this.id, this.address, this.label});
Subaddress({required this.id, required this.address, required this.label});
Subaddress.fromMap(Map map)
Subaddress.fromMap(Map<String, Object?> map)
: this.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
this.address = (map['address'] ?? '') as String,
this.label = (map['label'] ?? '') as String;

View file

@ -2,16 +2,22 @@ enum TransactionDirection { incoming, outgoing }
TransactionDirection parseTransactionDirectionFromInt(int raw) {
switch (raw) {
case 0: return TransactionDirection.incoming;
case 1: return TransactionDirection.outgoing;
default: return null;
case 0:
return TransactionDirection.incoming;
case 1:
return TransactionDirection.outgoing;
default:
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
}
}
TransactionDirection parseTransactionDirectionFromNumber(String raw) {
switch (raw) {
case "0": return TransactionDirection.incoming;
case "1": return TransactionDirection.outgoing;
default: return null;
case "0":
return TransactionDirection.incoming;
case "1":
return TransactionDirection.outgoing;
default:
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
}
}

View file

@ -1,10 +1,9 @@
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_core/transaction_info.dart';
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
TransactionHistoryBase();
// : _isUpdating = false;
TransactionHistoryBase()
: transactions = ObservableMap<String, TransactionType>();
@observable
ObservableMap<String, TransactionType> transactions;

View file

@ -2,21 +2,21 @@ import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/keyable.dart';
abstract class TransactionInfo extends Object with Keyable {
String id;
int amount;
int fee;
TransactionDirection direction;
bool isPending;
DateTime date;
int height;
int confirmations;
late String id;
late int amount;
int? fee;
late TransactionDirection direction;
late bool isPending;
late DateTime date;
late int height;
late int confirmations;
String amountFormatted();
String fiatAmount();
String feeFormatted();
String? feeFormatted();
void changeFiatAmount(String amount);
@override
dynamic get keyIndex => id;
Map<String, dynamic> additionalInfo;
late Map<String, dynamic> additionalInfo;
}

View file

@ -2,5 +2,5 @@ import 'package:cw_core/enumerable_item.dart';
abstract class TransactionPriority extends EnumerableItem<int>
with Serializable<int> {
const TransactionPriority({String title, int raw}) : super(title: title, raw: raw);
const TransactionPriority({required String title, required int raw}) : super(title: title, raw: raw);
}

View file

@ -5,28 +5,32 @@ part 'unspent_coins_info.g.dart';
@HiveType(typeId: UnspentCoinsInfo.typeId)
class UnspentCoinsInfo extends HiveObject {
UnspentCoinsInfo({
this.walletId,
this.hash,
this.isFrozen,
this.isSending,
this.note});
required this.walletId,
required this.hash,
required this.isFrozen,
required this.isSending,
required this.noteRaw});
static const typeId = 9;
static const boxName = 'Unspent';
static const boxKey = 'unspentBoxKey';
@HiveField(0)
@HiveField(0, defaultValue: '')
String walletId;
@HiveField(1)
@HiveField(1, defaultValue: '')
String hash;
@HiveField(2)
@HiveField(2, defaultValue: false)
bool isFrozen;
@HiveField(3)
@HiveField(3, defaultValue: false)
bool isSending;
@HiveField(4)
String note;
String? noteRaw;
String get note => noteRaw ?? '';
set note(String value) => noteRaw = value;
}

View file

@ -1,9 +1,8 @@
import 'package:cw_core/wallet_info.dart';
abstract class WalletAddresses {
WalletAddresses(this.walletInfo) {
addressesMap = {};
}
WalletAddresses(this.walletInfo)
: addressesMap = {};
final WalletInfo walletInfo;
@ -19,10 +18,6 @@ abstract class WalletAddresses {
Future<void> saveAddressesInBox() async {
try {
if (walletInfo == null) {
return;
}
walletInfo.address = address;
walletInfo.addresses = addressesMap;

View file

@ -5,9 +5,9 @@ import 'package:cw_core/wallet_info.dart';
abstract class WalletAddressesWithAccount<T> extends WalletAddresses {
WalletAddressesWithAccount(WalletInfo walletInfo) : super(walletInfo);
T get account;
// T get account;
set account(T account);
// set account(T account);
AccountList<T> get accountList;
}

View file

@ -1,12 +1,12 @@
import 'package:mobx/mobx.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/currency_for_wallet_type.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
@ -48,15 +48,15 @@ abstract class WalletBase<
WalletAddresses get walletAddresses;
HistoryType transactionHistory;
late HistoryType transactionHistory;
Future<void> connectToNode({@required Node node});
Future<void> connectToNode({required Node node});
Future<void> startSync();
Future<PendingTransaction> createTransaction(Object credentials);
int calculateEstimatedFee(TransactionPriority priority, int amount);
int calculateEstimatedFee(TransactionPriority priority, int? amount);
// void fetchTransactionsAsync(
// void Function(TransactionType transaction) onTransactionLoaded,
@ -66,7 +66,7 @@ abstract class WalletBase<
Future<void> save();
Future<void> rescan({int height});
Future<void> rescan({required int height});
void close();

View file

@ -1,10 +1,14 @@
import 'package:cw_core/wallet_info.dart';
abstract class WalletCredentials {
WalletCredentials({this.name, this.password, this.height, this.walletInfo});
WalletCredentials({
required this.name,
this.height,
this.walletInfo,
this.password});
final String name;
final int height;
String password;
WalletInfo walletInfo;
final int? height;
String? password;
WalletInfo? walletInfo;
}

View file

@ -13,66 +13,66 @@ class WalletInfo extends HiveObject {
: _yatLastUsedAddressController = StreamController<String>.broadcast();
factory WalletInfo.external(
{@required String id,
@required String name,
@required WalletType type,
@required bool isRecovery,
@required int restoreHeight,
@required DateTime date,
@required String dirPath,
@required String path,
@required String address,
{required String id,
required String name,
required WalletType type,
required bool isRecovery,
required int restoreHeight,
required DateTime date,
required String dirPath,
required String path,
required String address,
bool? showIntroCakePayCard,
String yatEid ='',
String yatLastUsedAddressRaw = '',
bool showIntroCakePayCard}) {
String yatLastUsedAddressRaw = ''}) {
return WalletInfo(id, name, type, isRecovery, restoreHeight,
date.millisecondsSinceEpoch ?? 0, dirPath, path, address,
date.millisecondsSinceEpoch, dirPath, path, address,
yatEid, yatLastUsedAddressRaw, showIntroCakePayCard);
}
static const typeId = 4;
static const boxName = 'WalletInfo';
@HiveField(0)
@HiveField(0, defaultValue: '')
String id;
@HiveField(1)
@HiveField(1, defaultValue: '')
String name;
@HiveField(2)
WalletType type;
@HiveField(3)
@HiveField(3, defaultValue: false)
bool isRecovery;
@HiveField(4)
@HiveField(4, defaultValue: 0)
int restoreHeight;
@HiveField(5)
@HiveField(5, defaultValue: 0)
int timestamp;
@HiveField(6)
@HiveField(6, defaultValue: '')
String dirPath;
@HiveField(7)
@HiveField(7, defaultValue: '')
String path;
@HiveField(8)
@HiveField(8, defaultValue: '')
String address;
@HiveField(10)
Map<String, String> addresses;
Map<String, String>? addresses;
@HiveField(11)
String yatEid;
String? yatEid;
@HiveField(12)
String yatLastUsedAddressRaw;
String? yatLastUsedAddressRaw;
@HiveField(13)
bool showIntroCakePayCard;
bool? showIntroCakePayCard;
String get yatLastUsedAddress => yatLastUsedAddressRaw;
String get yatLastUsedAddress => yatLastUsedAddressRaw ?? '';
set yatLastUsedAddress(String address) {
yatLastUsedAddressRaw = address;
@ -85,7 +85,7 @@ class WalletInfo extends HiveObject {
if(showIntroCakePayCard == null) {
return type != WalletType.haven;
}
return showIntroCakePayCard;
return showIntroCakePayCard!;
}
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp);

View file

@ -55,7 +55,7 @@ WalletType deserializeFromInt(int raw) {
case 3:
return WalletType.haven;
default:
return null;
throw Exception('Unexpected token: $raw for WalletType deserializeFromInt');
}
}
@ -100,6 +100,6 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) {
case WalletType.haven:
return CryptoCurrency.xhv;
default:
return null;
throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency');
}
}

View file

@ -7,35 +7,35 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "14.0.0"
version: "47.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.41.2"
version: "4.7.0"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
version: "2.3.1"
asn1lib:
dependency: transitive
description:
name: asn1lib
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.1"
version: "1.1.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.0"
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
@ -49,42 +49,42 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.2"
version: "2.3.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.6"
version: "1.1.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.10"
version: "3.1.0"
build_resolvers:
dependency: "direct dev"
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.3"
version: "2.0.10"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.5"
version: "2.2.1"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.10"
version: "7.2.4"
built_collection:
dependency: transitive
description:
@ -105,98 +105,77 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
version: "2.0.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.0"
version: "4.3.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
version: "1.16.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "3.0.2"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "3.0.2"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.12"
dartx:
dependency: transitive
description:
name: dartx
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0"
version: "2.2.4"
encrypt:
dependency: "direct main"
description:
name: encrypt
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "5.0.1"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "2.0.1"
file:
dependency: transitive
description:
@ -222,12 +201,19 @@ packages:
name: flutter_mobx
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0+2"
version: "2.0.6+4"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
glob:
dependency: transitive
description:
@ -241,42 +227,42 @@ packages:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
version: "2.1.0"
hive:
dependency: transitive
description:
name: hive
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.4+1"
version: "2.2.3"
hive_generator:
dependency: "direct dev"
description:
name: hive_generator
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.2"
version: "1.1.3"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.2"
version: "0.13.5"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
version: "4.0.1"
intl:
dependency: "direct main"
description:
@ -290,7 +276,7 @@ packages:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
version: "1.0.3"
js:
dependency: transitive
description:
@ -304,7 +290,7 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.6.0"
logging:
dependency: transitive
description:
@ -318,14 +304,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.10"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.8.0"
mime:
dependency: transitive
description:
@ -339,63 +332,77 @@ packages:
name: mobx
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1+4"
version: "2.1.0"
mobx_codegen:
dependency: "direct dev"
description:
name: mobx_codegen
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "2.0.7+3"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
version: "2.1.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.8.2"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.28"
version: "2.0.11"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.20"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+2"
version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+8"
version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "2.0.4"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.5"
version: "2.1.3"
pedantic:
dependency: transitive
description:
@ -416,14 +423,14 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "2.1.3"
pointycastle:
dependency: transitive
description:
name: pointycastle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "3.6.2"
pool:
dependency: transitive
description:
@ -451,21 +458,21 @@ packages:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.8"
version: "1.2.1"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.9"
version: "1.3.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.4+1"
version: "1.0.2"
sky_engine:
dependency: transitive
description: flutter
@ -477,14 +484,21 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.10+3"
version: "1.2.3"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.3"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
@ -512,35 +526,28 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.19"
time:
dependency: transitive
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.1"
version: "0.4.12"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1+3"
version: "1.0.0"
typed_data:
dependency: transitive
description:
@ -554,7 +561,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.2"
watcher:
dependency: transitive
description:
@ -568,21 +575,21 @@ packages:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "2.2.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "3.0.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
version: "0.2.0+2"
yaml:
dependency: transitive
description:
@ -591,5 +598,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dart: ">=2.17.5 <3.0.0"
flutter: ">=3.0.0"

View file

@ -6,26 +6,26 @@ author: Cake Wallet
homepage: https://cakewallet.com
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.17.0"
sdk: ">=2.17.5 <3.0.0"
flutter: ">=1.20.0"
dependencies:
flutter:
sdk: flutter
http: ^0.12.0+2
path_provider: ^1.3.0
mobx: ^1.2.1+2
flutter_mobx: ^1.1.0+2
http: ^0.13.4
path_provider: ^2.0.11
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
encrypt: ^4.0.0
encrypt: ^5.0.1
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.10.3
build_resolvers: ^1.3.10
mobx_codegen: ^1.1.0+1
hive_generator: ^0.8.1
build_runner: ^2.1.11
build_resolvers: ^2.0.9
mobx_codegen: ^2.0.7
hive_generator: ^1.1.3
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

View file

@ -50,16 +50,16 @@ List<AccountRow> getAllAccount() {
.toList();
}
void addAccountSync({String label}) {
final labelPointer = Utf8.toUtf8(label);
void addAccountSync({required String label}) {
final labelPointer = label.toNativeUtf8();
accountAddNewNative(labelPointer);
free(labelPointer);
calloc.free(labelPointer);
}
void setLabelForAccountSync({int accountIndex, String label}) {
final labelPointer = Utf8.toUtf8(label);
void setLabelForAccountSync({required int accountIndex, required String label}) {
final labelPointer = label.toNativeUtf8();
accountSetLabelNative(accountIndex, labelPointer);
free(labelPointer);
calloc.free(labelPointer);
}
void _addAccount(String label) => addAccountSync(label: label);
@ -71,12 +71,12 @@ void _setLabelForAccount(Map<String, dynamic> args) {
setLabelForAccountSync(label: label, accountIndex: accountIndex);
}
Future<void> addAccount({String label}) async {
Future<void> addAccount({required String label}) async {
await compute(_addAccount, label);
await store();
}
Future<void> setLabelForAccount({int accountIndex, String label}) async {
Future<void> setLabelForAccount({required int accountIndex, required String label}) async {
await compute(
_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
await store();

View file

@ -1,8 +1,8 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
String convertUTF8ToString({Pointer<Utf8> pointer}) {
final str = Utf8.fromUtf8(pointer);
free(pointer);
String convertUTF8ToString({required Pointer<Utf8> pointer}) {
final str = pointer.toDartString();
calloc.free(pointer);
return str;
}

View file

@ -8,7 +8,7 @@ class CwHaven {
const MethodChannel('cw_haven');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
final String version = await _channel.invokeMethod<String>('getPlatformVersion') ?? '';
return version;
}
}

View file

@ -1,5 +1,5 @@
class ConnectionToNodeException implements Exception {
ConnectionToNodeException({this.message});
ConnectionToNodeException({required this.message});
final String message;
}

View file

@ -1,5 +1,5 @@
class CreationTransactionException implements Exception {
CreationTransactionException({this.message});
CreationTransactionException({required this.message});
final String message;

View file

@ -1,5 +1,5 @@
class SetupWalletException implements Exception {
SetupWalletException({this.message});
SetupWalletException({required this.message});
final String message;
}

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