Merge branch 'flutter-upgrade' of https://github.com/cake-tech/cake_wallet into CW-182-allow-trusted-nodes

 Conflicts:
	cw_core/lib/node.dart
	lib/view_model/node_list/node_create_or_edit_view_model.dart
This commit is contained in:
OmarHatem 2022-10-20 13:18:00 +02:00
commit 469f23c09b
507 changed files with 6832 additions and 5981 deletions

View file

@ -1,51 +1,73 @@
include: package:lints/recommended.yaml
analyzer: analyzer:
strong-mode: exclude: [
implicit-casts: false build/**,
implicit-dynamic: false lib/**.g.dart,
exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**] 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: linter:
rules: 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 - cancel_subscriptions
- close_sinks
- comment_references
- constant_identifier_names # analyzer:
- control_flow_in_finally # strong-mode:
- empty_catches # implicit-casts: false
- empty_constructor_bodies # implicit-dynamic: false
- empty_statements # exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**]
- hash_and_equals
- invariant_booleans # linter:
- iterable_contains_unrelated_type # rules:
- library_names # - always_declare_return_types
- library_prefixes # - annotate_overrides
- list_remove_unrelated_type # - avoid_empty_else
- literal_only_boolean_expressions # - avoid_init_to_null
- non_constant_identifier_names # - avoid_return_types_on_setters
- one_member_abstracts # - await_only_futures
- only_throw_errors # - camel_case_types
- overridden_fields # - cancel_subscriptions
- package_api_docs # - close_sinks
- package_names # - comment_references
- package_prefixed_library_names # - constant_identifier_names
- parameter_assignments # - control_flow_in_finally
- prefer_final_fields # - empty_catches
- prefer_final_locals # - empty_constructor_bodies
- prefer_is_not_empty # - empty_statements
- slash_for_doc_comments # - hash_and_equals
- sort_constructors_first # - invariant_booleans
- sort_unnamed_constructors_first # - iterable_contains_unrelated_type
- test_types_in_equals # - library_names
- throw_in_finally # - library_prefixes
- type_init_formals # - list_remove_unrelated_type
- unawaited_futures # - literal_only_boolean_expressions
- unnecessary_getters_setters # - non_constant_identifier_names
- unrelated_type_equality_checks # - one_member_abstracts
- valid_regexps # - 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 { android {
compileSdkVersion 29 compileSdkVersion 33
lintOptions { lintOptions {
disable 'InvalidPackage' disable 'InvalidPackage'
@ -80,6 +80,8 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
ndkVersion "25.1.8937393"
} }
flutter { flutter {

View file

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

View file

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

View file

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

View file

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

View file

@ -106,15 +106,18 @@ Future<String> generateMnemonic(
return result; return result;
} }
Uint8List mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) { Future<Uint8List> mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async {
final pbkdf2 = cryptography.Pbkdf2( final pbkdf2 = cryptography.Pbkdf2(
macAlgorithm: cryptography.Hmac(cryptography.sha512), macAlgorithm: cryptography.Hmac.sha512(),
iterations: 2048, iterations: 2048,
bits: 512); bits: 512);
final text = normalizeText(mnemonic); final text = normalizeText(mnemonic);
// pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce)
return pbkdf2.deriveBitsSync(text.codeUnits, final key = await pbkdf2.deriveKey(
nonce: cryptography.Nonce('electrum'.codeUnits)); secretKey: cryptography.SecretKey(text.codeUnits),
nonce: 'electrum'.codeUnits);
final bytes = await key.extractBytes();
return Uint8List.fromList(bytes);
} }
bool matchesAnyPrefix(String mnemonic) => 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'; import 'package:cw_core/output_info.dart';
class BitcoinTransactionCredentials { class BitcoinTransactionCredentials {
BitcoinTransactionCredentials(this.outputs, {this.priority, this.feeRate}); BitcoinTransactionCredentials(this.outputs, {required this.priority, this.feeRate});
final List<OutputInfo> outputs; final List<OutputInfo> outputs;
final BitcoinTransactionPriority priority; final BitcoinTransactionPriority? priority;
final int feeRate; final int? feeRate;
} }

View file

@ -2,7 +2,7 @@ import 'package:cw_core/transaction_priority.dart';
//import 'package:cake_wallet/generated/i18n.dart'; //import 'package:cake_wallet/generated/i18n.dart';
class BitcoinTransactionPriority extends TransactionPriority { class BitcoinTransactionPriority extends TransactionPriority {
const BitcoinTransactionPriority({String title, int raw}) const BitcoinTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw); : super(title: title, raw: raw);
static const List<BitcoinTransactionPriority> all = [fast, medium, slow]; static const List<BitcoinTransactionPriority> all = [fast, medium, slow];
@ -13,7 +13,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
static const BitcoinTransactionPriority fast = static const BitcoinTransactionPriority fast =
BitcoinTransactionPriority(title: 'Fast', raw: 2); BitcoinTransactionPriority(title: 'Fast', raw: 2);
static BitcoinTransactionPriority deserialize({int raw}) { static BitcoinTransactionPriority deserialize({required int raw}) {
switch (raw) { switch (raw) {
case 0: case 0:
return slow; return slow;
@ -22,7 +22,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
case 2: case 2:
return fast; return fast;
default: default:
return null; throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize');
} }
} }
@ -53,7 +53,7 @@ class BitcoinTransactionPriority extends TransactionPriority {
} }
class LitecoinTransactionPriority extends BitcoinTransactionPriority { class LitecoinTransactionPriority extends BitcoinTransactionPriority {
const LitecoinTransactionPriority({String title, int raw}) const LitecoinTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw); : super(title: title, raw: raw);
static const List<LitecoinTransactionPriority> all = [fast, medium, slow]; static const List<LitecoinTransactionPriority> all = [fast, medium, slow];
@ -64,7 +64,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
static const LitecoinTransactionPriority fast = static const LitecoinTransactionPriority fast =
LitecoinTransactionPriority(title: 'Fast', raw: 2); LitecoinTransactionPriority(title: 'Fast', raw: 2);
static LitecoinTransactionPriority deserialize({int raw}) { static LitecoinTransactionPriority deserialize({required int raw}) {
switch (raw) { switch (raw) {
case 0: case 0:
return slow; return slow;
@ -73,7 +73,7 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
case 2: case 2:
return fast; return fast;
default: 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_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/unspent_coins_info.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
@ -17,12 +18,13 @@ class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
abstract class BitcoinWalletBase extends ElectrumWallet with Store { abstract class BitcoinWalletBase extends ElectrumWallet with Store {
BitcoinWalletBase( BitcoinWalletBase(
{@required String mnemonic, {required String mnemonic,
@required String password, required String password,
@required WalletInfo walletInfo, required WalletInfo walletInfo,
@required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord> initialAddresses, required Uint8List seedBytes,
ElectrumBalance initialBalance, List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0, int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0}) int initialChangeAddressIndex = 0})
: super( : super(
@ -32,7 +34,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
networkType: bitcoin.bitcoin, networkType: bitcoin.bitcoin,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialBalance: initialBalance) { initialBalance: initialBalance,
seedBytes: seedBytes,
currency: CryptoCurrency.btc) {
walletAddresses = BitcoinWalletAddresses( walletAddresses = BitcoinWalletAddresses(
walletInfo, walletInfo,
electrumClient: electrumClient, electrumClient: electrumClient,
@ -40,20 +44,40 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd, mainHd: hd,
sideHd: bitcoin.HDWallet.fromSeed( sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
mnemonicToSeedBytes(mnemonic), network: networkType)
.derivePath("m/0'/1"), .derivePath("m/0'/1"),
networkType: networkType); networkType: networkType);
} }
static Future<BitcoinWallet> open({ static Future<BitcoinWallet> create({
@required String name, required String mnemonic,
@required WalletInfo walletInfo, required String password,
@required Box<UnspentCoinsInfo> unspentCoinsInfo, required WalletInfo walletInfo,
@required String password, required Box<UnspentCoinsInfo> unspentCoinsInfo,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0
}) async { }) async {
final snp = ElectrumWallletSnapshot(name, walletInfo.type, password); return BitcoinWallet(
await snp.load(); 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( return BitcoinWallet(
mnemonic: snp.mnemonic, mnemonic: snp.mnemonic,
password: password, password: password,
@ -61,6 +85,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: snp.addresses, initialAddresses: snp.addresses,
initialBalance: snp.balance, initialBalance: snp.balance,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
initialRegularAddressIndex: snp.regularAddressIndex, initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex); initialChangeAddressIndex: snp.changeAddressIndex);
} }

View file

@ -16,13 +16,13 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses
with Store { with Store {
BitcoinWalletAddressesBase( BitcoinWalletAddressesBase(
WalletInfo walletInfo, 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 initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0, int initialChangeAddressIndex = 0})
ElectrumClient electrumClient,
@required bitcoin.HDWallet mainHd,
@required bitcoin.HDWallet sideHd,
@required bitcoin.NetworkType networkType})
: super( : super(
walletInfo, walletInfo,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
@ -34,6 +34,6 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses
networkType: networkType); networkType: networkType);
@override @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); 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'; import 'package:cw_core/wallet_info.dart';
class BitcoinNewWalletCredentials extends WalletCredentials { class BitcoinNewWalletCredentials extends WalletCredentials {
BitcoinNewWalletCredentials({String name, WalletInfo walletInfo}) BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo})
: super(name: name, walletInfo: walletInfo); : super(name: name, walletInfo: walletInfo);
} }
class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials { class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
BitcoinRestoreWalletFromSeedCredentials( 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); : super(name: name, password: password, walletInfo: walletInfo);
final String mnemonic; final String mnemonic;
@ -16,7 +16,7 @@ class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials { class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
BitcoinRestoreWalletFromWIFCredentials( 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); : super(name: name, password: password, walletInfo: walletInfo);
final String wif; final String wif;

View file

@ -1,7 +1,5 @@
import 'package:flutter/foundation.dart';
class BitcoinWalletKeys { 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 wif;
final String privateKey; 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_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:collection/collection.dart';
class BitcoinWalletService extends WalletService< class BitcoinWalletService extends WalletService<
BitcoinNewWalletCredentials, BitcoinNewWalletCredentials,
@ -25,10 +26,10 @@ class BitcoinWalletService extends WalletService<
@override @override
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async { Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
final wallet = BitcoinWallet( final wallet = await BitcoinWalletBase.create(
mnemonic: await generateMnemonic(), mnemonic: await generateMnemonic(),
password: credentials.password, password: credentials.password!,
walletInfo: credentials.walletInfo, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();
@ -41,9 +42,8 @@ class BitcoinWalletService extends WalletService<
@override @override
Future<BitcoinWallet> openWallet(String name, String password) async { Future<BitcoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhere( final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()), (info) => info.id == WalletBase.idFor(name, getType()))!;
orElse: () => null);
final wallet = await BitcoinWalletBase.open( final wallet = await BitcoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo, password: password, name: name, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
@ -68,10 +68,10 @@ class BitcoinWalletService extends WalletService<
throw BitcoinMnemonicIsIncorrectException(); throw BitcoinMnemonicIsIncorrectException();
} }
final wallet = BitcoinWallet( final wallet = await BitcoinWalletBase.create(
password: credentials.password, password: credentials.password!,
mnemonic: credentials.mnemonic, mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save(); await wallet.save();
await wallet.init(); 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:cw_bitcoin/script_hash.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
import 'package:collection/collection.dart';
String jsonrpcparams(List<Object> params) { String jsonrpcparams(List<Object> params) {
final _params = params?.map((val) => '"${val.toString()}"')?.join(','); final _params = params?.map((val) => '"${val.toString()}"')?.join(',');
@ -14,14 +15,20 @@ String jsonrpcparams(List<Object> params) {
} }
String jsonrpc( 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'; '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n';
class SocketTask { class SocketTask {
SocketTask({this.completer, this.isSubscription, this.subject}); SocketTask({
required this.isSubscription,
this.completer,
this.subject});
final Completer completer; final Completer<dynamic>? completer;
final BehaviorSubject subject; final BehaviorSubject<dynamic>? subject;
final bool isSubscription; final bool isSubscription;
} }
@ -36,18 +43,18 @@ class ElectrumClient {
static const aliveTimerDuration = Duration(seconds: 2); static const aliveTimerDuration = Duration(seconds: 2);
bool get isConnected => _isConnected; bool get isConnected => _isConnected;
Socket socket; Socket? socket;
void Function(bool) onConnectionStatusChange; void Function(bool)? onConnectionStatusChange;
int _id; int _id;
final Map<String, SocketTask> _tasks; final Map<String, SocketTask> _tasks;
bool _isConnected; bool _isConnected;
Timer _aliveTimer; Timer? _aliveTimer;
String unterminatedString; String unterminatedString;
Future<void> connectToUri(Uri uri) async => Future<void> connectToUri(Uri uri) async =>
await connect(host: uri.host, port: uri.port); 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 { try {
await socket?.close(); await socket?.close();
} catch (_) {} } catch (_) {}
@ -56,10 +63,11 @@ class ElectrumClient {
timeout: connectionTimeout, onBadCertificate: (_) => true); timeout: connectionTimeout, onBadCertificate: (_) => true);
_setIsConnected(true); _setIsConnected(true);
socket.listen((Uint8List event) { socket!.listen((Uint8List event) {
try { try {
final msg = utf8.decode(event.toList());
final response = final response =
json.decode(utf8.decode(event.toList())) as Map<String, Object>; json.decode(msg) as Map<String, dynamic>;
_handleResponse(response); _handleResponse(response);
} on FormatException catch (e) { } on FormatException catch (e) {
final msg = e.message.toLowerCase(); final msg = e.message.toLowerCase();
@ -75,12 +83,12 @@ class ElectrumClient {
if (isJSONStringCorrect(unterminatedString)) { if (isJSONStringCorrect(unterminatedString)) {
final response = final response =
json.decode(unterminatedString) as Map<String, Object>; json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response); _handleResponse(response);
unterminatedString = ''; unterminatedString = '';
} }
} on TypeError catch (e) { } 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; return;
} }
@ -89,9 +97,10 @@ class ElectrumClient {
if (isJSONStringCorrect(unterminatedString)) { if (isJSONStringCorrect(unterminatedString)) {
final response = final response =
json.decode(unterminatedString) as Map<String, Object>; json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response); _handleResponse(response);
unterminatedString = null; // unterminatedString = null;
unterminatedString = '';
} }
} catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
@ -128,14 +137,14 @@ class ElectrumClient {
return []; return [];
}); });
Future<Map<String, Object>> getBalance(String scriptHash) => Future<Map<String, dynamic>> getBalance(String scriptHash) =>
call(method: 'blockchain.scripthash.get_balance', params: [scriptHash]) call(method: 'blockchain.scripthash.get_balance', params: [scriptHash])
.then((dynamic result) { .then((dynamic result) {
if (result is Map<String, Object>) { if (result is Map<String, dynamic>) {
return result; return result;
} }
return <String, Object>{}; return <String, dynamic>{};
}); });
Future<List<Map<String, dynamic>>> getHistory(String scriptHash) => Future<List<Map<String, dynamic>>> getHistory(String scriptHash) =>
@ -143,11 +152,11 @@ class ElectrumClient {
.then((dynamic result) { .then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) { return result.map((dynamic val) {
if (val is Map<String, Object>) { if (val is Map<String, dynamic>) {
return val; return val;
} }
return <String, Object>{}; return <String, dynamic>{};
}).toList(); }).toList();
} }
@ -162,12 +171,12 @@ class ElectrumClient {
.then((dynamic result) { .then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) { return result.map((dynamic val) {
if (val is Map<String, Object>) { if (val is Map<String, dynamic>) {
val['address'] = address; val['address'] = address;
return val; return val;
} }
return <String, Object>{}; return <String, dynamic>{};
}).toList(); }).toList();
} }
@ -179,11 +188,11 @@ class ElectrumClient {
.then((dynamic result) { .then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) { return result.map((dynamic val) {
if (val is Map<String, Object>) { if (val is Map<String, dynamic>) {
return val; return val;
} }
return <String, Object>{}; return <String, dynamic>{};
}).toList(); }).toList();
} }
@ -195,30 +204,30 @@ class ElectrumClient {
.then((dynamic result) { .then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) { return result.map((dynamic val) {
if (val is Map<String, Object>) { if (val is Map<String, dynamic>) {
return val; return val;
} }
return <String, Object>{}; return <String, dynamic>{};
}).toList(); }).toList();
} }
return []; return [];
}); });
Future<Map<String, Object>> getTransactionRaw( Future<Map<String, dynamic>> getTransactionRaw(
{@required String hash}) async => {required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, true]) call(method: 'blockchain.transaction.get', params: [hash, true])
.then((dynamic result) { .then((dynamic result) {
if (result is Map<String, Object>) { if (result is Map<String, dynamic>) {
return result; return result;
} }
return <String, Object>{}; return <String, dynamic>{};
}); });
Future<String> getTransactionHex( Future<String> getTransactionHex(
{@required String hash}) async => {required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, false]) call(method: 'blockchain.transaction.get', params: [hash, false])
.then((dynamic result) { .then((dynamic result) {
if (result is String) { if (result is String) {
@ -229,7 +238,7 @@ class ElectrumClient {
}); });
Future<String> broadcastTransaction( Future<String> broadcastTransaction(
{@required String transactionRaw}) async => {required String transactionRaw}) async =>
call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) { .then((dynamic result) {
if (result is String) { if (result is String) {
@ -240,16 +249,16 @@ class ElectrumClient {
}); });
Future<Map<String, dynamic>> getMerkle( Future<Map<String, dynamic>> getMerkle(
{@required String hash, @required int height}) async => {required String hash, required int height}) async =>
await call( await call(
method: 'blockchain.transaction.get_merkle', method: 'blockchain.transaction.get_merkle',
params: [hash, height]) as Map<String, dynamic>; 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]) await call(method: 'blockchain.block.get_header', params: [height])
as Map<String, dynamic>; as Map<String, dynamic>;
Future<double> estimatefee({@required int p}) => Future<double> estimatefee({required int p}) =>
call(method: 'blockchain.estimatefee', params: [p]) call(method: 'blockchain.estimatefee', params: [p])
.then((dynamic result) { .then((dynamic result) {
if (result is double) { if (result is double) {
@ -266,13 +275,26 @@ class ElectrumClient {
Future<List<List<int>>> feeHistogram() => Future<List<List<int>>> feeHistogram() =>
call(method: 'mempool.get_fee_histogram').then((dynamic result) { call(method: 'mempool.get_fee_histogram').then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic e) { // return result.map((dynamic e) {
if (e is List) { // if (e is List) {
return e.map((dynamic ee) => ee is int ? ee : null).toList(); // return e.map((dynamic ee) => ee is int ? ee : null).toList();
} // }
return null; // return null;
}).toList(); // }).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 []; return [];
@ -299,7 +321,7 @@ class ElectrumClient {
} }
} }
BehaviorSubject<Object> scripthashUpdate(String scripthash) { BehaviorSubject<Object>? scripthashUpdate(String scripthash) {
_id += 1; _id += 1;
return subscribe<Object>( return subscribe<Object>(
id: 'blockchain.scripthash.subscribe:$scripthash', id: 'blockchain.scripthash.subscribe:$scripthash',
@ -307,14 +329,14 @@ class ElectrumClient {
params: [scripthash]); params: [scripthash]);
} }
BehaviorSubject<T> subscribe<T>( BehaviorSubject<T>? subscribe<T>(
{@required String id, {required String id,
@required String method, required String method,
List<Object> params = const []}) { List<Object> params = const []}) {
try { try {
final subscription = BehaviorSubject<T>(); final subscription = BehaviorSubject<T>();
_regisrySubscription(id, subscription); _regisrySubscription(id, subscription);
socket.write(jsonrpc(method: method, id: _id, params: params)); socket!.write(jsonrpc(method: method, id: _id, params: params));
return subscription; return subscription;
} catch(e) { } 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>(); final completer = Completer<dynamic>();
_id += 1; _id += 1;
final id = _id; final id = _id;
_registryTask(id, completer); _registryTask(id, completer);
socket.write(jsonrpc(method: method, id: id, params: params)); socket!.write(jsonrpc(method: method, id: id, params: params));
return completer.future; return completer.future;
} }
Future<dynamic> callWithTimeout( Future<dynamic> callWithTimeout(
{String method, {required String method,
List<Object> params = const [], List<Object> params = const [],
int timeout = 2000}) async { int timeout = 2000}) async {
try { try {
@ -342,7 +364,7 @@ class ElectrumClient {
_id += 1; _id += 1;
final id = _id; final id = _id;
_registryTask(id, completer); _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), () { Timer(Duration(milliseconds: timeout), () {
if (!completer.isCompleted) { if (!completer.isCompleted) {
completer.completeError(RequestFailedTimeoutException(method, id)); completer.completeError(RequestFailedTimeoutException(method, id));
@ -356,35 +378,35 @@ class ElectrumClient {
} }
Future<void> close() async { Future<void> close() async {
_aliveTimer.cancel(); _aliveTimer?.cancel();
await socket.close(); await socket?.close();
onConnectionStatusChange = null; 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); 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); _tasks[id] = SocketTask(subject: subject, isSubscription: true);
void _finish(String id, Object data) { void _finish(String id, Object? data) {
if (_tasks[id] == null) { if (_tasks[id] == null) {
return; return;
} }
if (!(_tasks[id]?.completer?.isCompleted ?? false)) { if (!(_tasks[id]?.completer?.isCompleted ?? false)) {
_tasks[id]?.completer?.complete(data); _tasks[id]?.completer!.complete(data);
} }
if (!(_tasks[id]?.isSubscription ?? false)) { if (!(_tasks[id]?.isSubscription ?? false)) {
_tasks[id] = null; _tasks.remove(id);
} else { } else {
_tasks[id].subject.add(data); _tasks[id]?.subject?.add(data);
} }
} }
void _methodHandler( void _methodHandler(
{@required String method, @required Map<String, Object> request}) { {required String method, required Map<String, dynamic> request}) {
switch (method) { switch (method) {
case 'blockchain.scripthash.subscribe': case 'blockchain.scripthash.subscribe':
final params = request['params'] as List<dynamic>; final params = request['params'] as List<dynamic>;
@ -406,7 +428,7 @@ class ElectrumClient {
_isConnected = isConnected; _isConnected = isConnected;
} }
void _handleResponse(Map<String, Object> response) { void _handleResponse(Map<String, dynamic> response) {
final method = response['method']; final method = response['method'];
final id = response['id'] as String; final id = response['id'] as String;
final result = response['result']; final result = response['result'];

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,6 @@ import 'package:cw_bitcoin/electrum.dart';
import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/script_hash.dart';
import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
part 'electrum_wallet_addresses.g.dart'; part 'electrum_wallet_addresses.g.dart';
@ -14,13 +13,13 @@ class ElectrumWalletAddresses = ElectrumWalletAddressesBase
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
ElectrumWalletAddressesBase(WalletInfo walletInfo, 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 initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0, int initialChangeAddressIndex = 0})
this.mainHd,
this.sideHd,
this.electrumClient,
this.networkType})
: addresses = ObservableList<BitcoinAddressRecord>.of( : addresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? []).toSet()), (initialAddresses ?? []).toSet()),
receiveAddresses = ObservableList<BitcoinAddressRecord>.of( receiveAddresses = ObservableList<BitcoinAddressRecord>.of(
@ -31,10 +30,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
(initialAddresses ?? []) (initialAddresses ?? [])
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed)
.toSet()), .toSet()),
super(walletInfo) { currentReceiveAddressIndex = initialRegularAddressIndex,
currentReceiveAddressIndex = initialRegularAddressIndex; currentChangeAddressIndex = initialChangeAddressIndex,
currentChangeAddressIndex = initialChangeAddressIndex; super(walletInfo);
}
static const defaultReceiveAddressesCount = 22; static const defaultReceiveAddressesCount = 22;
static const defaultChangeAddressesCount = 17; static const defaultChangeAddressesCount = 17;
@ -124,17 +122,18 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
} }
Future<BitcoinAddressRecord> generateNewAddress( Future<BitcoinAddressRecord> generateNewAddress(
{bool isHidden = false, bitcoin.HDWallet hd}) async { {bitcoin.HDWallet? hd, bool isHidden = false}) async {
currentReceiveAddressIndex += 1; currentReceiveAddressIndex += 1;
// FIX-ME: Check logic for whichi HD should be used here ???
final address = BitcoinAddressRecord( final address = BitcoinAddressRecord(
getAddress(index: currentReceiveAddressIndex, hd: hd), getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd),
index: currentReceiveAddressIndex, index: currentReceiveAddressIndex,
isHidden: isHidden); isHidden: isHidden);
addresses.add(address); addresses.add(address);
return address; return address;
} }
String getAddress({@required int index, @required bitcoin.HDWallet hd}) => ''; String getAddress({required int index, required bitcoin.HDWallet hd}) => '';
@override @override
Future<void> updateAddressesInBox() async { Future<void> updateAddressesInBox() async {
@ -239,7 +238,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
} }
Future<List<BitcoinAddressRecord>> _createNewAddresses(int count, 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>[]; final list = <BitcoinAddressRecord>[];
for (var i = startIndex; i < count + startIndex; i++) { 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'; import 'package:cw_core/wallet_type.dart';
class ElectrumWallletSnapshot { 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 name;
final String password; final String password;
@ -18,28 +26,34 @@ class ElectrumWallletSnapshot {
int regularAddressIndex; int regularAddressIndex;
int changeAddressIndex; int changeAddressIndex;
Future<void> load() async { static Future<ElectrumWallletSnapshot> load(String name, WalletType type, String password) async {
try { final path = await pathForWallet(name: name, type: type);
final path = await pathForWallet(name: name, type: type); final jsonSource = await read(path: path, password: password);
final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map;
final data = json.decode(jsonSource) as Map; final addressesTmp = data['addresses'] as List? ?? <Object>[];
final addressesTmp = data['addresses'] as List ?? <Object>[]; final mnemonic = data['mnemonic'] as String;
mnemonic = data['mnemonic'] as String; final addresses = addressesTmp
addresses = addressesTmp .whereType<String>()
.whereType<String>() .map((addr) => BitcoinAddressRecord.fromJSON(addr))
.map((addr) => BitcoinAddressRecord.fromJSON(addr)) .toList();
.toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ??
balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0);
ElectrumBalance(confirmed: 0, unconfirmed: 0); var regularAddressIndex = 0;
regularAddressIndex = 0; var changeAddressIndex = 0;
changeAddressIndex = 0;
try { try {
regularAddressIndex = int.parse(data['account_index'] as String); regularAddressIndex = int.parse(data['account_index'] as String? ?? '0');
changeAddressIndex = int.parse(data['change_address_index'] as String); changeAddressIndex = int.parse(data['change_address_index'] as String? ?? '0');
} catch (_) {} } catch (_) {}
} catch (e) {
print(e); 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 'dart:io';
import 'package:cw_core/key.dart'; import 'package:cw_core/key.dart';
import 'package:encrypt/encrypt.dart' as encrypt; import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
Future<void> write( Future<void> write(
{@required String path, {required String path,
@required String password, required String password,
@required String data}) async { required String data}) async {
final keys = extractKeys(password); final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first); final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last); final iv = encrypt.IV.fromBase64(keys.last);
@ -16,9 +15,9 @@ Future<void> write(
} }
Future<void> writeData( Future<void> writeData(
{@required String path, {required String path,
@required String password, required String password,
@required String data}) async { required String data}) async {
final keys = extractKeys(password); final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first); final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last); final iv = encrypt.IV.fromBase64(keys.last);
@ -27,7 +26,7 @@ Future<void> writeData(
f.writeAsStringSync(encrypted); 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); final file = File(path);
if (!file.existsSync()) { if (!file.existsSync()) {

View file

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

View file

@ -16,13 +16,13 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
with Store { with Store {
LitecoinWalletAddressesBase( LitecoinWalletAddressesBase(
WalletInfo walletInfo, 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 initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0, int initialChangeAddressIndex = 0})
ElectrumClient electrumClient,
@required bitcoin.HDWallet mainHd,
@required bitcoin.HDWallet sideHd,
@required bitcoin.NetworkType networkType})
: super( : super(
walletInfo, walletInfo,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
@ -34,6 +34,6 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
networkType: networkType); networkType: networkType);
@override @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); 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_type.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:collection/collection.dart';
class LitecoinWalletService extends WalletService< class LitecoinWalletService extends WalletService<
BitcoinNewWalletCredentials, BitcoinNewWalletCredentials,
@ -25,10 +26,10 @@ class LitecoinWalletService extends WalletService<
@override @override
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async { Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async {
final wallet = LitecoinWallet( final wallet = await LitecoinWalletBase.create(
mnemonic: await generateMnemonic(), mnemonic: await generateMnemonic(),
password: credentials.password, password: credentials.password!,
walletInfo: credentials.walletInfo, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();
@ -42,9 +43,8 @@ class LitecoinWalletService extends WalletService<
@override @override
Future<LitecoinWallet> openWallet(String name, String password) async { Future<LitecoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhere( final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()), (info) => info.id == WalletBase.idFor(name, getType()))!;
orElse: () => null);
final wallet = await LitecoinWalletBase.open( final wallet = await LitecoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo, password: password, name: name, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
@ -69,10 +69,10 @@ class LitecoinWalletService extends WalletService<
throw BitcoinMnemonicIsIncorrectException(); throw BitcoinMnemonicIsIncorrectException();
} }
final wallet = LitecoinWallet( final wallet = await LitecoinWalletBase.create(
password: credentials.password, password: credentials.password!,
mnemonic: credentials.mnemonic, mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();

View file

@ -1,5 +1,4 @@
import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; 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:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/pending_transaction.dart';
import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum.dart';
@ -10,9 +9,9 @@ import 'package:cw_core/wallet_type.dart';
class PendingBitcoinTransaction with PendingTransaction { class PendingBitcoinTransaction with PendingTransaction {
PendingBitcoinTransaction(this._tx, this.type, PendingBitcoinTransaction(this._tx, this.type,
{@required this.electrumClient, {required this.electrumClient,
@required this.amount, required this.amount,
@required this.fee}) required this.fee})
: _listeners = <void Function(ElectrumTransactionInfo transaction)>[]; : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
final WalletType type; 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:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
String scriptHash(String address, {@required bitcoin.NetworkType networkType}) { String scriptHash(String address, {required bitcoin.NetworkType networkType}) {
final outputScript = final outputScript =
bitcoin.Address.addressToOutputScript(address, networkType); bitcoin.Address.addressToOutputScript(address, networkType);
final parts = sha256.convert(outputScript).toString().split(''); 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'; import 'package:hex/hex.dart';
bitcoin.PaymentData generatePaymentData( bitcoin.PaymentData generatePaymentData(
{@required bitcoin.HDWallet hd, @required int index}) => {required bitcoin.HDWallet hd, required int index}) =>
PaymentData( PaymentData(
pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey))); pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!)));
bitcoin.ECPair generateKeyPair( bitcoin.ECPair generateKeyPair(
{@required bitcoin.HDWallet hd, {required bitcoin.HDWallet hd,
@required int index, required int index,
bitcoin.NetworkType network}) => required bitcoin.NetworkType network}) =>
bitcoin.ECPair.fromWIF(hd.derive(index).wif, network: network); bitcoin.ECPair.fromWIF(hd.derive(index).wif!, network: network);
String generateP2WPKHAddress( String generateP2WPKHAddress(
{@required bitcoin.HDWallet hd, {required bitcoin.HDWallet hd,
@required int index, required int index,
bitcoin.NetworkType networkType}) => required bitcoin.NetworkType networkType}) =>
bitcoin bitcoin
.P2WPKH( .P2WPKH(
data: PaymentData( data: PaymentData(
pubkey: pubkey:
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey))), Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))),
network: networkType) network: networkType)
.data .data
.address; .address!;
String generateP2WPKHAddressByPath( String generateP2WPKHAddressByPath(
{@required bitcoin.HDWallet hd, {required bitcoin.HDWallet hd,
@required String path, required String path,
bitcoin.NetworkType networkType}) => required bitcoin.NetworkType networkType}) =>
bitcoin bitcoin
.P2WPKH( .P2WPKH(
data: PaymentData( data: PaymentData(
pubkey: pubkey:
Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey))), Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey!))),
network: networkType) network: networkType)
.data .data
.address; .address!;
String generateP2PKHAddress( String generateP2PKHAddress(
{@required bitcoin.HDWallet hd, {required bitcoin.HDWallet hd,
@required int index, required int index,
bitcoin.NetworkType networkType}) => required bitcoin.NetworkType networkType}) =>
bitcoin bitcoin
.P2PKH( .P2PKH(
data: PaymentData( data: PaymentData(
pubkey: pubkey:
Uint8List.fromList(HEX.decode(hd.derive(index).pubKey))), Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))),
network: networkType) network: networkType)
.data .data
.address; .address!;

View file

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

View file

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

View file

@ -1,7 +1,7 @@
class Account { 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.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
this.label = (map['label'] ?? '') as String; this.label = (map['label'] ?? '') as String;

View file

@ -8,9 +8,9 @@ abstract class AccountList<T> {
List<T> getAll(); 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(); void refresh();
} }

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) @HiveType(typeId: 0)
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> { 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); : super(title: title, raw: raw);
final String tag; final String? tag;
final String name; final String? name;
final String iconPath; final String? iconPath;
static const all = [ static const all = [
CryptoCurrency.xmr, CryptoCurrency.xmr,
@ -97,10 +102,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
static const zen = CryptoCurrency(title: 'ZEN', iconPath: 'assets/images/zen_icon.png', raw: 44); 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 const xvg = CryptoCurrency(title: 'XVG', name: 'Verge', iconPath: 'assets/images/xvg_icon.png', raw: 45);
static CryptoCurrency deserialize({required int raw}) {
static CryptoCurrency deserialize({int raw}) {
switch (raw) { switch (raw) {
case 0: case 0:
return CryptoCurrency.xmr; return CryptoCurrency.xmr;
@ -195,7 +197,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
case 45: case 45:
return CryptoCurrency.xvg; return CryptoCurrency.xvg;
default: default:
return null; throw Exception('Unexpected token: $raw for CryptoCurrency deserialize');
} }
} }
@ -294,7 +296,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
case 'xvg': case 'xvg':
return CryptoCurrency.xvg; return CryptoCurrency.xvg;
default: default:
return null; throw Exception('Unexpected token: $raw for CryptoCurrency fromString');
} }
} }

View file

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

View file

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

View file

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

View file

@ -16,14 +16,14 @@ List<String> extractKeys(String key) {
return [_key, iv]; 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 encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
final encrypted = encrypter.encrypt(data, iv: iv); final encrypted = encrypter.encrypt(data, iv: iv);
return encrypted.base64; 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 keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first); final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last); final iv = encrypt.IV.fromBase64(keys.last);

View file

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

View file

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

View file

@ -4,7 +4,7 @@ import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/enumerable_item.dart'; import 'package:cw_core/enumerable_item.dart';
class MoneroTransactionPriority extends TransactionPriority { class MoneroTransactionPriority extends TransactionPriority {
const MoneroTransactionPriority({String title, int raw}) const MoneroTransactionPriority({required String title, required int raw})
: super(title: title, raw: raw); : super(title: title, raw: raw);
static const all = [ static const all = [
@ -37,7 +37,7 @@ class MoneroTransactionPriority extends TransactionPriority {
} }
} }
static MoneroTransactionPriority deserialize({int raw}) { static MoneroTransactionPriority deserialize({required int raw}) {
switch (raw) { switch (raw) {
case 0: case 0:
return slow; return slow;
@ -50,7 +50,7 @@ class MoneroTransactionPriority extends TransactionPriority {
case 4: case 4:
return fastest; return fastest;
default: default:
return null; throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize');
} }
} }

View file

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

View file

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

View file

@ -1,20 +1,20 @@
class OutputInfo { class OutputInfo {
const OutputInfo( const OutputInfo(
{this.fiatAmount, {required this.address,
this.cryptoAmount, required this.sendAll,
this.address, required this.isParsedAddress,
this.note, this.cryptoAmount,
this.sendAll, this.formattedCryptoAmount,
this.extractedAddress, this.fiatAmount,
this.isParsedAddress, this.note,
this.formattedCryptoAmount}); this.extractedAddress,});
final String fiatAmount; final String? fiatAmount;
final String cryptoAmount; final String? cryptoAmount;
final String address; final String address;
final String note; final String? note;
final String extractedAddress; final String? extractedAddress;
final bool sendAll; final bool sendAll;
final bool isParsedAddress; 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:flutter/foundation.dart';
import 'package:path_provider/path_provider.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 root = await getApplicationDocumentsDirectory();
final prefix = walletTypeToString(type).toLowerCase(); final prefix = walletTypeToString(type).toLowerCase();
final walletsDir = Directory('${root.path}/wallets'); final walletsDir = Directory('${root.path}/wallets');
@ -16,11 +16,11 @@ Future<String> pathForWalletDir({@required String name, @required WalletType ty
return walletDire.path; 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) await pathForWalletDir(name: name, type: type)
.then((path) => path + '/$name'); .then((path) => path + '/$name');
Future<String> outdatedAndroidPathForWalletDir({String name}) async { Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
final directory = await getApplicationDocumentsDirectory(); final directory = await getApplicationDocumentsDirectory();
final pathDir = directory.path + '/$name'; 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 { Future<Uint8List> secRandom(int count) async {
try { try {
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}); return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
} on PlatformException catch (_) { } on PlatformException catch (_) {
return Uint8List.fromList([]); return Uint8List.fromList([]);
} }

View file

@ -1,7 +1,7 @@
class Subaddress { 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.id = map['id'] == null ? 0 : int.parse(map['id'] as String),
this.address = (map['address'] ?? '') as String, this.address = (map['address'] ?? '') as String,
this.label = (map['label'] ?? '') as String; this.label = (map['label'] ?? '') as String;

View file

@ -2,16 +2,22 @@ enum TransactionDirection { incoming, outgoing }
TransactionDirection parseTransactionDirectionFromInt(int raw) { TransactionDirection parseTransactionDirectionFromInt(int raw) {
switch (raw) { switch (raw) {
case 0: return TransactionDirection.incoming; case 0:
case 1: return TransactionDirection.outgoing; return TransactionDirection.incoming;
default: return null; case 1:
return TransactionDirection.outgoing;
default:
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
} }
} }
TransactionDirection parseTransactionDirectionFromNumber(String raw) { TransactionDirection parseTransactionDirectionFromNumber(String raw) {
switch (raw) { switch (raw) {
case "0": return TransactionDirection.incoming; case "0":
case "1": return TransactionDirection.outgoing; return TransactionDirection.incoming;
default: return null; 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:mobx/mobx.dart';
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> { abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
TransactionHistoryBase(); TransactionHistoryBase()
// : _isUpdating = false; : transactions = ObservableMap<String, TransactionType>();
@observable @observable
ObservableMap<String, TransactionType> transactions; ObservableMap<String, TransactionType> transactions;

View file

@ -2,21 +2,21 @@ import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/keyable.dart'; import 'package:cw_core/keyable.dart';
abstract class TransactionInfo extends Object with Keyable { abstract class TransactionInfo extends Object with Keyable {
String id; late String id;
int amount; late int amount;
int fee; int? fee;
TransactionDirection direction; late TransactionDirection direction;
bool isPending; late bool isPending;
DateTime date; late DateTime date;
int height; late int height;
int confirmations; late int confirmations;
String amountFormatted(); String amountFormatted();
String fiatAmount(); String fiatAmount();
String feeFormatted(); String? feeFormatted();
void changeFiatAmount(String amount); void changeFiatAmount(String amount);
@override @override
dynamic get keyIndex => id; 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> abstract class TransactionPriority extends EnumerableItem<int>
with Serializable<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,11 +5,11 @@ part 'unspent_coins_info.g.dart';
@HiveType(typeId: UnspentCoinsInfo.typeId) @HiveType(typeId: UnspentCoinsInfo.typeId)
class UnspentCoinsInfo extends HiveObject { class UnspentCoinsInfo extends HiveObject {
UnspentCoinsInfo({ UnspentCoinsInfo({
this.walletId, required this.walletId,
this.hash, required this.hash,
this.isFrozen, required this.isFrozen,
this.isSending, required this.isSending,
this.note}); required this.note});
static const typeId = 9; static const typeId = 9;
static const boxName = 'Unspent'; static const boxName = 'Unspent';

View file

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

View file

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

View file

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

View file

@ -1,10 +1,14 @@
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
abstract class WalletCredentials { 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 String name;
final int height; final int? height;
String password; String? password;
WalletInfo walletInfo; WalletInfo? walletInfo;
} }

View file

@ -13,20 +13,20 @@ class WalletInfo extends HiveObject {
: _yatLastUsedAddressController = StreamController<String>.broadcast(); : _yatLastUsedAddressController = StreamController<String>.broadcast();
factory WalletInfo.external( factory WalletInfo.external(
{@required String id, {required String id,
@required String name, required String name,
@required WalletType type, required WalletType type,
@required bool isRecovery, required bool isRecovery,
@required int restoreHeight, required int restoreHeight,
@required DateTime date, required DateTime date,
@required String dirPath, required String dirPath,
@required String path, required String path,
@required String address, required String address,
bool? showIntroCakePayCard,
String yatEid ='', String yatEid ='',
String yatLastUsedAddressRaw = '', String yatLastUsedAddressRaw = ''}) {
bool showIntroCakePayCard}) {
return WalletInfo(id, name, type, isRecovery, restoreHeight, return WalletInfo(id, name, type, isRecovery, restoreHeight,
date.millisecondsSinceEpoch ?? 0, dirPath, path, address, date.millisecondsSinceEpoch, dirPath, path, address,
yatEid, yatLastUsedAddressRaw, showIntroCakePayCard); yatEid, yatLastUsedAddressRaw, showIntroCakePayCard);
} }
@ -61,7 +61,7 @@ class WalletInfo extends HiveObject {
String address; String address;
@HiveField(10) @HiveField(10)
Map<String, String> addresses; Map<String, String>? addresses;
@HiveField(11) @HiveField(11)
String yatEid; String yatEid;
@ -70,7 +70,7 @@ class WalletInfo extends HiveObject {
String yatLastUsedAddressRaw; String yatLastUsedAddressRaw;
@HiveField(13) @HiveField(13)
bool showIntroCakePayCard; bool? showIntroCakePayCard;
String get yatLastUsedAddress => yatLastUsedAddressRaw; String get yatLastUsedAddress => yatLastUsedAddressRaw;
@ -85,7 +85,7 @@ class WalletInfo extends HiveObject {
if(showIntroCakePayCard == null) { if(showIntroCakePayCard == null) {
return type != WalletType.haven; return type != WalletType.haven;
} }
return showIntroCakePayCard; return showIntroCakePayCard!;
} }
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp); DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
class MoneroOutput { class MoneroOutput {
MoneroOutput({@required this.address, @required this.amount}); MoneroOutput({required this.address, required this.amount});
final String address; final String address;
final String amount; final String amount;

View file

@ -39,7 +39,7 @@ typedef get_node_height = Int64 Function();
typedef is_connected = Int8 Function(); typedef is_connected = Int8 Function();
typedef setup_node = Int8 Function( typedef setup_node = Int8 Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int8, Int8, Pointer<Utf8>); Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>);
typedef start_refresh = Void Function(); typedef start_refresh = Void Function();
@ -86,7 +86,7 @@ typedef account_set_label = Void Function(
typedef transactions_refresh = Void Function(); typedef transactions_refresh = Void Function();
typedef get_tx_key = Pointer<Utf8> Function(Pointer<Utf8> txId); typedef get_tx_key = Pointer<Utf8>? Function(Pointer<Utf8> txId);
typedef transactions_count = Int64 Function(); typedef transactions_count = Int64 Function();

View file

@ -3,9 +3,10 @@ import 'package:ffi/ffi.dart';
class AccountRow extends Struct { class AccountRow extends Struct {
@Int64() @Int64()
int id; external int id;
Pointer<Utf8> label;
String getLabel() => Utf8.fromUtf8(label); external Pointer<Utf8> label;
String getLabel() => label.toDartString();
int getId() => id; int getId() => id;
} }

View file

@ -3,9 +3,10 @@ import 'package:ffi/ffi.dart';
class HavenBalanceRow extends Struct { class HavenBalanceRow extends Struct {
@Int64() @Int64()
int amount; external int amount;
Pointer<Utf8> assetType;
external Pointer<Utf8> assetType;
int getAmount() => amount; int getAmount() => amount;
String getAssetType() => Utf8.fromUtf8(assetType); String getAssetType() => assetType.toDartString();
} }

View file

@ -3,9 +3,10 @@ import 'package:ffi/ffi.dart';
class HavenRate extends Struct { class HavenRate extends Struct {
@Int64() @Int64()
int rate; external int rate;
Pointer<Utf8> assetType;
external Pointer<Utf8> assetType;
int getRate() => rate; int getRate() => rate;
String getAssetType() => Utf8.fromUtf8(assetType); String getAssetType() => assetType.toDartString();
} }

View file

@ -3,18 +3,22 @@ import 'package:ffi/ffi.dart';
class PendingTransactionRaw extends Struct { class PendingTransactionRaw extends Struct {
@Int64() @Int64()
int amount; external int amount;
@Int64() @Int64()
int fee; external int fee;
Pointer<Utf8> hash; external Pointer<Utf8> hash;
String getHash() => Utf8.fromUtf8(hash); String getHash() => hash.toDartString();
} }
class PendingTransactionDescription { class PendingTransactionDescription {
PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress}); PendingTransactionDescription({
required this.amount,
required this.fee,
required this.hash,
required this.pointerAddress});
final int amount; final int amount;
final int fee; final int fee;

View file

@ -3,11 +3,13 @@ import 'package:ffi/ffi.dart';
class SubaddressRow extends Struct { class SubaddressRow extends Struct {
@Int64() @Int64()
int id; external int id;
Pointer<Utf8> address;
Pointer<Utf8> label;
String getLabel() => Utf8.fromUtf8(label); external Pointer<Utf8> address;
String getAddress() => Utf8.fromUtf8(address);
external Pointer<Utf8> label;
String getLabel() => label.toDartString();
String getAddress() => address.toDartString();
int getId() => id; int getId() => id;
} }

View file

@ -3,42 +3,42 @@ import 'package:ffi/ffi.dart';
class TransactionInfoRow extends Struct { class TransactionInfoRow extends Struct {
@Uint64() @Uint64()
int amount; external int amount;
@Uint64() @Uint64()
int fee; external int fee;
@Uint64() @Uint64()
int blockHeight; external int blockHeight;
@Uint64() @Uint64()
int confirmations; external int confirmations;
@Uint32() @Uint32()
int subaddrAccount; external int subaddrAccount;
@Int8() @Int8()
int direction; external int direction;
@Int8() @Int8()
int isPending; external int isPending;
@Uint32() @Uint32()
int subaddrIndex; external int subaddrIndex;
Pointer<Utf8> hash; external Pointer<Utf8> hash;
Pointer<Utf8> paymentId; external Pointer<Utf8> paymentId;
Pointer<Utf8> assetType; external Pointer<Utf8> assetType;
@Int64() @Int64()
int datetime; external int datetime;
int getDatetime() => datetime; int getDatetime() => datetime;
int getAmount() => amount >= 0 ? amount : amount * -1; int getAmount() => amount >= 0 ? amount : amount * -1;
bool getIsPending() => isPending != 0; bool getIsPending() => isPending != 0;
String getHash() => Utf8.fromUtf8(hash); String getHash() => hash.toDartString();
String getPaymentId() => Utf8.fromUtf8(paymentId); String getPaymentId() => paymentId.toDartString();
String getAssetType() => Utf8.fromUtf8(assetType); String getAssetType() => assetType.toDartString();
} }

View file

@ -2,7 +2,7 @@ import 'dart:ffi';
import 'package:ffi/ffi.dart'; import 'package:ffi/ffi.dart';
class Utf8Box extends Struct { class Utf8Box extends Struct {
Pointer<Utf8> value; external Pointer<Utf8> value;
String getValue() => Utf8.fromUtf8(value); String getValue() => value.toDartString();
} }

View file

@ -29,7 +29,7 @@ final subaddrressSetLabelNative = havenApi
bool isUpdating = false; bool isUpdating = false;
void refreshSubaddresses({@required int accountIndex}) { void refreshSubaddresses({required int accountIndex}) {
try { try {
isUpdating = true; isUpdating = true;
subaddressRefreshNative(accountIndex); subaddressRefreshNative(accountIndex);
@ -50,18 +50,18 @@ List<SubaddressRow> getAllSubaddresses() {
.toList(); .toList();
} }
void addSubaddressSync({int accountIndex, String label}) { void addSubaddressSync({required int accountIndex, required String label}) {
final labelPointer = Utf8.toUtf8(label); final labelPointer = label.toNativeUtf8();
subaddrressAddNewNative(accountIndex, labelPointer); subaddrressAddNewNative(accountIndex, labelPointer);
free(labelPointer); calloc.free(labelPointer);
} }
void setLabelForSubaddressSync( void setLabelForSubaddressSync(
{int accountIndex, int addressIndex, String label}) { {required int accountIndex, required int addressIndex, required String label}) {
final labelPointer = Utf8.toUtf8(label); final labelPointer = label.toNativeUtf8();
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer); subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
free(labelPointer); calloc.free(labelPointer);
} }
void _addSubaddress(Map<String, dynamic> args) { void _addSubaddress(Map<String, dynamic> args) {
@ -80,14 +80,14 @@ void _setLabelForSubaddress(Map<String, dynamic> args) {
accountIndex: accountIndex, addressIndex: addressIndex, label: label); accountIndex: accountIndex, addressIndex: addressIndex, label: label);
} }
Future addSubaddress({int accountIndex, String label}) async { Future addSubaddress({required int accountIndex, required String label}) async {
await compute<Map<String, Object>, void>( await compute<Map<String, Object>, void>(
_addSubaddress, {'accountIndex': accountIndex, 'label': label}); _addSubaddress, {'accountIndex': accountIndex, 'label': label});
await store(); await store();
} }
Future setLabelForSubaddress( Future setLabelForSubaddress(
{int accountIndex, int addressIndex, String label}) async { {required int accountIndex, required int addressIndex, required String label}) async {
await compute<Map<String, Object>, void>(_setLabelForSubaddress, { await compute<Map<String, Object>, void>(_setLabelForSubaddress, {
'accountIndex': accountIndex, 'accountIndex': accountIndex,
'addressIndex': addressIndex, 'addressIndex': addressIndex,

View file

@ -40,16 +40,16 @@ final getTxKeyNative = havenApi
.asFunction<GetTxKey>(); .asFunction<GetTxKey>();
String getTxKey(String txId) { String getTxKey(String txId) {
final txIdPointer = Utf8.toUtf8(txId); final txIdPointer = txId.toNativeUtf8();
final keyPointer = getTxKeyNative(txIdPointer); final keyPointer = getTxKeyNative(txIdPointer);
free(txIdPointer); calloc.free(txIdPointer);
if (keyPointer != null) { if (keyPointer != null) {
return convertUTF8ToString(pointer: keyPointer); return convertUTF8ToString(pointer: keyPointer);
} }
return null; return '';
} }
void refreshTransactions() => transactionsRefreshNative(); void refreshTransactions() => transactionsRefreshNative();
@ -67,18 +67,18 @@ List<TransactionInfoRow> getAllTransations() {
} }
PendingTransactionDescription createTransactionSync( PendingTransactionDescription createTransactionSync(
{String address, {required String address,
String assetType, required String assetType,
String paymentId, required String paymentId,
String amount, required int priorityRaw,
int priorityRaw, String? amount,
int accountIndex = 0}) { int accountIndex = 0}) {
final addressPointer = Utf8.toUtf8(address); final addressPointer = address.toNativeUtf8();
final assetTypePointer = Utf8.toUtf8(assetType); final assetTypePointer = assetType.toNativeUtf8();
final paymentIdPointer = Utf8.toUtf8(paymentId); final paymentIdPointer = paymentId.toNativeUtf8();
final amountPointer = amount != null ? Utf8.toUtf8(amount) : nullptr; final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr;
final errorMessagePointer = allocate<Utf8Box>(); final errorMessagePointer = calloc<Utf8Box>();
final pendingTransactionRawPointer = allocate<PendingTransactionRaw>(); final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
final created = transactionCreateNative( final created = transactionCreateNative(
addressPointer, addressPointer,
assetTypePointer, assetTypePointer,
@ -90,17 +90,17 @@ PendingTransactionDescription createTransactionSync(
pendingTransactionRawPointer) != pendingTransactionRawPointer) !=
0; 0;
free(addressPointer); calloc.free(addressPointer);
free(assetTypePointer); calloc.free(assetTypePointer);
free(paymentIdPointer); calloc.free(paymentIdPointer);
if (amountPointer != nullptr) { if (amountPointer != nullptr) {
free(amountPointer); calloc.free(amountPointer);
} }
if (!created) { if (!created) {
final message = errorMessagePointer.ref.getValue(); final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer); calloc.free(errorMessagePointer);
throw CreationTransactionException(message: message); throw CreationTransactionException(message: message);
} }
@ -112,28 +112,28 @@ PendingTransactionDescription createTransactionSync(
} }
PendingTransactionDescription createTransactionMultDestSync( PendingTransactionDescription createTransactionMultDestSync(
{List<MoneroOutput> outputs, {required List<MoneroOutput> outputs,
String assetType, required String assetType,
String paymentId, required String paymentId,
int priorityRaw, required int priorityRaw,
int accountIndex = 0}) { int accountIndex = 0}) {
final int size = outputs.length; final int size = outputs.length;
final List<Pointer<Utf8>> addressesPointers = outputs.map((output) => final List<Pointer<Utf8>> addressesPointers = outputs.map((output) =>
Utf8.toUtf8(output.address)).toList(); output.address.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> addressesPointerPointer = allocate(count: size); final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size);
final List<Pointer<Utf8>> amountsPointers = outputs.map((output) => final List<Pointer<Utf8>> amountsPointers = outputs.map((output) =>
Utf8.toUtf8(output.amount)).toList(); output.amount.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> amountsPointerPointer = allocate(count: size); final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc( size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
addressesPointerPointer[i] = addressesPointers[i]; addressesPointerPointer[i] = addressesPointers[i];
amountsPointerPointer[i] = amountsPointers[i]; amountsPointerPointer[i] = amountsPointers[i];
} }
final assetTypePointer = Utf8.toUtf8(assetType); final assetTypePointer = assetType.toNativeUtf8();
final paymentIdPointer = Utf8.toUtf8(paymentId); final paymentIdPointer = paymentId.toNativeUtf8();
final errorMessagePointer = allocate<Utf8Box>(); final errorMessagePointer = calloc<Utf8Box>();
final pendingTransactionRawPointer = allocate<PendingTransactionRaw>(); final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
final created = transactionCreateMultDestNative( final created = transactionCreateMultDestNative(
addressesPointerPointer, addressesPointerPointer,
assetTypePointer, assetTypePointer,
@ -146,18 +146,18 @@ PendingTransactionDescription createTransactionMultDestSync(
pendingTransactionRawPointer) != pendingTransactionRawPointer) !=
0; 0;
free(addressesPointerPointer); calloc.free(addressesPointerPointer);
free(assetTypePointer); calloc.free(assetTypePointer);
free(amountsPointerPointer); calloc.free(amountsPointerPointer);
addressesPointers.forEach((element) => free(element)); addressesPointers.forEach((element) => calloc.free(element));
amountsPointers.forEach((element) => free(element)); amountsPointers.forEach((element) => calloc.free(element));
free(paymentIdPointer); calloc.free(paymentIdPointer);
if (!created) { if (!created) {
final message = errorMessagePointer.ref.getValue(); final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer); calloc.free(errorMessagePointer);
throw CreationTransactionException(message: message); throw CreationTransactionException(message: message);
} }
@ -168,17 +168,17 @@ PendingTransactionDescription createTransactionMultDestSync(
pointerAddress: pendingTransactionRawPointer.address); pointerAddress: pendingTransactionRawPointer.address);
} }
void commitTransactionFromPointerAddress({int address}) => commitTransaction( void commitTransactionFromPointerAddress({required int address}) => commitTransaction(
transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address)); transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
void commitTransaction({Pointer<PendingTransactionRaw> transactionPointer}) { void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) {
final errorMessagePointer = allocate<Utf8Box>(); final errorMessagePointer = calloc<Utf8Box>();
final isCommited = final isCommited =
transactionCommitNative(transactionPointer, errorMessagePointer) != 0; transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
if (!isCommited) { if (!isCommited) {
final message = errorMessagePointer.ref.getValue(); final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer); calloc.free(errorMessagePointer);
throw CreationTransactionException(message: message); throw CreationTransactionException(message: message);
} }
} }
@ -216,11 +216,11 @@ PendingTransactionDescription _createTransactionMultDestSync(Map args) {
} }
Future<PendingTransactionDescription> createTransaction( Future<PendingTransactionDescription> createTransaction(
{String address, {required String address,
String assetType, required String assetType,
required int priorityRaw,
String? amount,
String paymentId = '', String paymentId = '',
String amount,
int priorityRaw,
int accountIndex = 0}) => int accountIndex = 0}) =>
compute(_createTransactionSync, { compute(_createTransactionSync, {
'address': address, 'address': address,
@ -232,10 +232,10 @@ Future<PendingTransactionDescription> createTransaction(
}); });
Future<PendingTransactionDescription> createTransactionMultDest( Future<PendingTransactionDescription> createTransactionMultDest(
{List<MoneroOutput> outputs, {required List<MoneroOutput> outputs,
String assetType, required int priorityRaw,
String? assetType,
String paymentId = '', String paymentId = '',
int priorityRaw,
int accountIndex = 0}) => int accountIndex = 0}) =>
compute(_createTransactionMultDestSync, { compute(_createTransactionMultDestSync, {
'outputs': outputs, 'outputs': outputs,

View file

@ -39,7 +39,7 @@ typedef GetNodeHeight = int Function();
typedef IsConnected = int Function(); typedef IsConnected = int Function();
typedef SetupNode = int Function( typedef SetupNode = int Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>); Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>);
typedef StartRefresh = void Function(); typedef StartRefresh = void Function();
@ -84,7 +84,7 @@ typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
typedef TransactionsRefresh = void Function(); typedef TransactionsRefresh = void Function();
typedef GetTxKey = Pointer<Utf8> Function(Pointer<Utf8> txId); typedef GetTxKey = Pointer<Utf8>? Function(Pointer<Utf8> txId);
typedef TransactionsCount = int Function(); typedef TransactionsCount = int Function();

View file

@ -150,24 +150,24 @@ int getNodeHeightSync() => getNodeHeightNative();
bool isConnectedSync() => isConnectedNative() != 0; bool isConnectedSync() => isConnectedNative() != 0;
bool setupNodeSync( bool setupNodeSync(
{String address, {required String address,
String login, String? login,
String password, String? password,
bool useSSL = false, bool useSSL = false,
bool isLightWallet = false}) { bool isLightWallet = false}) {
final addressPointer = Utf8.toUtf8(address); final addressPointer = address.toNativeUtf8();
Pointer<Utf8> loginPointer; Pointer<Utf8>? loginPointer;
Pointer<Utf8> passwordPointer; Pointer<Utf8>? passwordPointer;
if (login != null) { if (login != null) {
loginPointer = Utf8.toUtf8(login); loginPointer = login.toNativeUtf8();
} }
if (password != null) { if (password != null) {
passwordPointer = Utf8.toUtf8(password); passwordPointer = password.toNativeUtf8();
} }
final errorMessagePointer = allocate<Utf8>(); final errorMessagePointer = ''.toNativeUtf8();
final isSetupNode = setupNodeNative( final isSetupNode = setupNodeNative(
addressPointer, addressPointer,
loginPointer, loginPointer,
@ -177,9 +177,15 @@ bool setupNodeSync(
errorMessagePointer) != errorMessagePointer) !=
0; 0;
free(addressPointer); calloc.free(addressPointer);
free(loginPointer);
free(passwordPointer); if (loginPointer != null) {
calloc.free(loginPointer);
}
if (passwordPointer != null) {
calloc.free(passwordPointer);
}
if (!isSetupNode) { if (!isSetupNode) {
throw SetupWalletException( throw SetupWalletException(
@ -193,31 +199,31 @@ void startRefreshSync() => startRefreshNative();
Future<bool> connectToNode() async => connecToNodeNative() != 0; Future<bool> connectToNode() async => connecToNodeNative() != 0;
void setRefreshFromBlockHeight({int height}) => void setRefreshFromBlockHeight({required int height}) =>
setRefreshFromBlockHeightNative(height); setRefreshFromBlockHeightNative(height);
void setRecoveringFromSeed({bool isRecovery}) => void setRecoveringFromSeed({required bool isRecovery}) =>
setRecoveringFromSeedNative(_boolToInt(isRecovery)); setRecoveringFromSeedNative(_boolToInt(isRecovery));
void storeSync() { void storeSync() {
final pathPointer = Utf8.toUtf8(''); final pathPointer = ''.toNativeUtf8();
storeNative(pathPointer); storeNative(pathPointer);
free(pathPointer); calloc.free(pathPointer);
} }
void setPasswordSync(String password) { void setPasswordSync(String password) {
final passwordPointer = Utf8.toUtf8(password); final passwordPointer = password.toNativeUtf8();
final errorMessagePointer = allocate<Utf8Box>(); final errorMessagePointer = calloc<Utf8Box>();
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0; final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
free(passwordPointer); calloc.free(passwordPointer);
if (!changed) { if (!changed) {
final message = errorMessagePointer.ref.getValue(); final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer); calloc.free(errorMessagePointer);
throw Exception(message); throw Exception(message);
} }
free(errorMessagePointer); calloc.free(errorMessagePointer);
} }
void closeCurrentWallet() => closeCurrentWalletNative(); void closeCurrentWallet() => closeCurrentWalletNative();
@ -235,16 +241,15 @@ String getPublicSpendKey() =>
convertUTF8ToString(pointer: getPublicSpendKeyNative()); convertUTF8ToString(pointer: getPublicSpendKeyNative());
class SyncListener { class SyncListener {
SyncListener(this.onNewBlock, this.onNewTransaction) { SyncListener(this.onNewBlock, this.onNewTransaction)
_cachedBlockchainHeight = 0; : _cachedBlockchainHeight = 0,
_lastKnownBlockHeight = 0; _lastKnownBlockHeight = 0,
_initialSyncHeight = 0; _initialSyncHeight = 0;
}
void Function(int, int, double) onNewBlock; void Function(int, int, double) onNewBlock;
void Function() onNewTransaction; void Function() onNewTransaction;
Timer _updateSyncInfoTimer; Timer? _updateSyncInfoTimer;
int _cachedBlockchainHeight; int _cachedBlockchainHeight;
int _lastKnownBlockHeight; int _lastKnownBlockHeight;
int _initialSyncHeight; int _initialSyncHeight;
@ -333,13 +338,13 @@ int _getNodeHeight(Object _) => getNodeHeightSync();
void startRefresh() => startRefreshSync(); void startRefresh() => startRefreshSync();
Future setupNode( Future<void> setupNode(
{String address, {required String address,
String login, String? login,
String password, String? password,
bool useSSL = false, bool useSSL = false,
bool isLightWallet = false}) => bool isLightWallet = false}) =>
compute<Map<String, Object>, void>(_setupNodeSync, { compute<Map<String, Object?>, void>(_setupNodeSync, {
'address': address, 'address': address,
'login': login, 'login': login,
'password': password, 'password': password,
@ -347,7 +352,7 @@ Future setupNode(
'isLightWallet': isLightWallet 'isLightWallet': isLightWallet
}); });
Future store() => compute<int, void>(_storeSync, 0); Future<void> store() => compute<int, void>(_storeSync, 0);
Future<bool> isConnected() => compute(_isConnected, 0); Future<bool> isConnected() => compute(_isConnected, 0);

View file

@ -38,18 +38,18 @@ final errorStringNative = havenApi
.asFunction<ErrorString>(); .asFunction<ErrorString>();
void createWalletSync( void createWalletSync(
{String path, String password, String language, int nettype = 0}) { {required String path, required String password, required String language, int nettype = 0}) {
final pathPointer = Utf8.toUtf8(path); final pathPointer = path.toNativeUtf8();
final passwordPointer = Utf8.toUtf8(password); final passwordPointer = password.toNativeUtf8();
final languagePointer = Utf8.toUtf8(language); final languagePointer = language.toNativeUtf8();
final errorMessagePointer = allocate<Utf8>(); final errorMessagePointer = ''.toNativeUtf8();
final isWalletCreated = createWalletNative(pathPointer, passwordPointer, final isWalletCreated = createWalletNative(pathPointer, passwordPointer,
languagePointer, nettype, errorMessagePointer) != languagePointer, nettype, errorMessagePointer) !=
0; 0;
free(pathPointer); calloc.free(pathPointer);
free(passwordPointer); calloc.free(passwordPointer);
free(languagePointer); calloc.free(languagePointer);
if (!isWalletCreated) { if (!isWalletCreated) {
throw WalletCreationException( throw WalletCreationException(
@ -59,25 +59,25 @@ void createWalletSync(
// setupNodeSync(address: "node.moneroworld.com:18089"); // setupNodeSync(address: "node.moneroworld.com:18089");
} }
bool isWalletExistSync({String path}) { bool isWalletExistSync({required String path}) {
final pathPointer = Utf8.toUtf8(path); final pathPointer = path.toNativeUtf8();
final isExist = isWalletExistNative(pathPointer) != 0; final isExist = isWalletExistNative(pathPointer) != 0;
free(pathPointer); calloc.free(pathPointer);
return isExist; return isExist;
} }
void restoreWalletFromSeedSync( void restoreWalletFromSeedSync(
{String path, {required String path,
String password, required String password,
String seed, required String seed,
int nettype = 0, int nettype = 0,
int restoreHeight = 0}) { int restoreHeight = 0}) {
final pathPointer = Utf8.toUtf8(path); final pathPointer = path.toNativeUtf8();
final passwordPointer = Utf8.toUtf8(password); final passwordPointer = password.toNativeUtf8();
final seedPointer = Utf8.toUtf8(seed); final seedPointer = seed.toNativeUtf8();
final errorMessagePointer = allocate<Utf8>(); final errorMessagePointer = ''.toNativeUtf8();
final isWalletRestored = restoreWalletFromSeedNative( final isWalletRestored = restoreWalletFromSeedNative(
pathPointer, pathPointer,
passwordPointer, passwordPointer,
@ -87,9 +87,9 @@ void restoreWalletFromSeedSync(
errorMessagePointer) != errorMessagePointer) !=
0; 0;
free(pathPointer); calloc.free(pathPointer);
free(passwordPointer); calloc.free(passwordPointer);
free(seedPointer); calloc.free(seedPointer);
if (!isWalletRestored) { if (!isWalletRestored) {
throw WalletRestoreFromSeedException( throw WalletRestoreFromSeedException(
@ -98,21 +98,21 @@ void restoreWalletFromSeedSync(
} }
void restoreWalletFromKeysSync( void restoreWalletFromKeysSync(
{String path, {required String path,
String password, required String password,
String language, required String language,
String address, required String address,
String viewKey, required String viewKey,
String spendKey, required String spendKey,
int nettype = 0, int nettype = 0,
int restoreHeight = 0}) { int restoreHeight = 0}) {
final pathPointer = Utf8.toUtf8(path); final pathPointer = path.toNativeUtf8();
final passwordPointer = Utf8.toUtf8(password); final passwordPointer = password.toNativeUtf8();
final languagePointer = Utf8.toUtf8(language); final languagePointer = language.toNativeUtf8();
final addressPointer = Utf8.toUtf8(address); final addressPointer = address.toNativeUtf8();
final viewKeyPointer = Utf8.toUtf8(viewKey); final viewKeyPointer = viewKey.toNativeUtf8();
final spendKeyPointer = Utf8.toUtf8(spendKey); final spendKeyPointer = spendKey.toNativeUtf8();
final errorMessagePointer = allocate<Utf8>(); final errorMessagePointer = ''.toNativeUtf8();
final isWalletRestored = restoreWalletFromKeysNative( final isWalletRestored = restoreWalletFromKeysNative(
pathPointer, pathPointer,
passwordPointer, passwordPointer,
@ -125,12 +125,12 @@ void restoreWalletFromKeysSync(
errorMessagePointer) != errorMessagePointer) !=
0; 0;
free(pathPointer); calloc.free(pathPointer);
free(passwordPointer); calloc.free(passwordPointer);
free(languagePointer); calloc.free(languagePointer);
free(addressPointer); calloc.free(addressPointer);
free(viewKeyPointer); calloc.free(viewKeyPointer);
free(spendKeyPointer); calloc.free(spendKeyPointer);
if (!isWalletRestored) { if (!isWalletRestored) {
throw WalletRestoreFromKeysException( throw WalletRestoreFromKeysException(
@ -138,12 +138,12 @@ void restoreWalletFromKeysSync(
} }
} }
void loadWallet({String path, String password, int nettype = 0}) { void loadWallet({required String path, required String password, int nettype = 0}) {
final pathPointer = Utf8.toUtf8(path); final pathPointer = path.toNativeUtf8();
final passwordPointer = Utf8.toUtf8(password); final passwordPointer = password.toNativeUtf8();
final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0; final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0;
free(pathPointer); calloc.free(pathPointer);
free(passwordPointer); calloc.free(passwordPointer);
if (!loaded) { if (!loaded) {
throw WalletOpeningException( throw WalletOpeningException(
@ -189,20 +189,20 @@ void _restoreFromKeys(Map<String, dynamic> args) {
} }
Future<void> _openWallet(Map<String, String> args) async => Future<void> _openWallet(Map<String, String> args) async =>
loadWallet(path: args['path'], password: args['password']); loadWallet(path: args['path'] as String, password: args['password'] as String);
bool _isWalletExist(String path) => isWalletExistSync(path: path); bool _isWalletExist(String path) => isWalletExistSync(path: path);
void openWallet({String path, String password, int nettype = 0}) async => void openWallet({required String path, required String password, int nettype = 0}) async =>
loadWallet(path: path, password: password, nettype: nettype); loadWallet(path: path, password: password, nettype: nettype);
Future<void> openWalletAsync(Map<String, String> args) async => Future<void> openWalletAsync(Map<String, String> args) async =>
compute(_openWallet, args); compute(_openWallet, args);
Future<void> createWallet( Future<void> createWallet(
{String path, {required String path,
String password, required String password,
String language, required String language,
int nettype = 0}) async => int nettype = 0}) async =>
compute(_createWallet, { compute(_createWallet, {
'path': path, 'path': path,
@ -211,10 +211,10 @@ Future<void> createWallet(
'nettype': nettype 'nettype': nettype
}); });
Future restoreFromSeed( Future<void> restoreFromSeed(
{String path, {required String path,
String password, required String password,
String seed, required String seed,
int nettype = 0, int nettype = 0,
int restoreHeight = 0}) async => int restoreHeight = 0}) async =>
compute<Map<String, Object>, void>(_restoreFromSeed, { compute<Map<String, Object>, void>(_restoreFromSeed, {
@ -225,13 +225,13 @@ Future restoreFromSeed(
'restoreHeight': restoreHeight 'restoreHeight': restoreHeight
}); });
Future restoreFromKeys( Future<void> restoreFromKeys(
{String path, {required String path,
String password, required String password,
String language, required String language,
String address, required String address,
String viewKey, required String viewKey,
String spendKey, required String spendKey,
int nettype = 0, int nettype = 0,
int restoreHeight = 0}) async => int restoreHeight = 0}) async =>
compute<Map<String, Object>, void>(_restoreFromKeys, { compute<Map<String, Object>, void>(_restoreFromKeys, {
@ -245,4 +245,4 @@ Future restoreFromKeys(
'restoreHeight': restoreHeight 'restoreHeight': restoreHeight
}); });
Future<bool> isWalletExist({String path}) => compute(_isWalletExist, path); Future<bool> isWalletExist({required String path}) => compute(_isWalletExist, path);

View file

@ -53,13 +53,13 @@ abstract class HavenAccountListBase extends AccountList<Account> with Store {
.toList(); .toList();
@override @override
Future addAccount({String label}) async { Future<void> addAccount({required String label}) async {
await account_list.addAccount(label: label); await account_list.addAccount(label: label);
update(); update();
} }
@override @override
Future setLabelAccount({int accountIndex, String label}) async { Future<void> setLabelAccount({required int accountIndex, required String label}) async {
await account_list.setLabelForAccount( await account_list.setLabelForAccount(
accountIndex: accountIndex, label: label); accountIndex: accountIndex, label: label);
update(); update();

View file

@ -9,7 +9,7 @@ const inactiveBalances = [
CryptoCurrency.xnok, CryptoCurrency.xnok,
CryptoCurrency.xnzd]; CryptoCurrency.xnzd];
Map<CryptoCurrency, MoneroBalance> getHavenBalance({int accountIndex}) { Map<CryptoCurrency, MoneroBalance> getHavenBalance({required int accountIndex}) {
final fullBalances = getHavenFullBalance(accountIndex: accountIndex); final fullBalances = getHavenFullBalance(accountIndex: accountIndex);
final unlockedBalances = getHavenUnlockedBalance(accountIndex: accountIndex); final unlockedBalances = getHavenUnlockedBalance(accountIndex: accountIndex);
final havenBalances = <CryptoCurrency, MoneroBalance>{}; final havenBalances = <CryptoCurrency, MoneroBalance>{};

View file

@ -10,11 +10,10 @@ class HavenSubaddressList = HavenSubaddressListBase
with _$HavenSubaddressList; with _$HavenSubaddressList;
abstract class HavenSubaddressListBase with Store { abstract class HavenSubaddressListBase with Store {
HavenSubaddressListBase() { HavenSubaddressListBase()
_isRefreshing = false; : _isRefreshing = false,
_isUpdating = false; _isUpdating = false,
subaddresses = ObservableList<Subaddress>(); subaddresses = ObservableList<Subaddress>();
}
@observable @observable
ObservableList<Subaddress> subaddresses; ObservableList<Subaddress> subaddresses;
@ -22,7 +21,7 @@ abstract class HavenSubaddressListBase with Store {
bool _isRefreshing; bool _isRefreshing;
bool _isUpdating; bool _isUpdating;
void update({int accountIndex}) { void update({required int accountIndex}) {
if (_isUpdating) { if (_isUpdating) {
return; return;
} }
@ -56,20 +55,20 @@ abstract class HavenSubaddressListBase with Store {
.toList(); .toList();
} }
Future addSubaddress({int accountIndex, String label}) async { Future<void> addSubaddress({required int accountIndex, required String label}) async {
await subaddress_list.addSubaddress( await subaddress_list.addSubaddress(
accountIndex: accountIndex, label: label); accountIndex: accountIndex, label: label);
update(accountIndex: accountIndex); update(accountIndex: accountIndex);
} }
Future setLabelSubaddress( Future<void> setLabelSubaddress(
{int accountIndex, int addressIndex, String label}) async { {required int accountIndex, required int addressIndex, required String label}) async {
await subaddress_list.setLabelForSubaddress( await subaddress_list.setLabelForSubaddress(
accountIndex: accountIndex, addressIndex: addressIndex, label: label); accountIndex: accountIndex, addressIndex: addressIndex, label: label);
update(accountIndex: accountIndex); update(accountIndex: accountIndex);
} }
void refresh({int accountIndex}) { void refresh({required int accountIndex}) {
if (_isRefreshing) { if (_isRefreshing) {
return; return;
} }

View file

@ -2,7 +2,10 @@ import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_core/output_info.dart'; import 'package:cw_core/output_info.dart';
class HavenTransactionCreationCredentials { class HavenTransactionCreationCredentials {
HavenTransactionCreationCredentials({this.outputs, this.priority, this.assetType}); HavenTransactionCreationCredentials({
required this.outputs,
required this.priority,
required this.assetType});
final List<OutputInfo> outputs; final List<OutputInfo> outputs;
final MoneroTransactionPriority priority; final MoneroTransactionPriority priority;

View file

@ -10,20 +10,20 @@ class HavenTransactionInfo extends TransactionInfo {
HavenTransactionInfo(this.id, this.height, this.direction, this.date, HavenTransactionInfo(this.id, this.height, this.direction, this.date,
this.isPending, this.amount, this.accountIndex, this.addressIndex, this.fee); this.isPending, this.amount, this.accountIndex, this.addressIndex, this.fee);
HavenTransactionInfo.fromMap(Map map) HavenTransactionInfo.fromMap(Map<String, Object> map)
: id = (map['hash'] ?? '') as String, : id = (map['hash'] ?? '') as String,
height = (map['height'] ?? 0) as int, height = (map['height'] ?? 0) as int,
direction = direction =
parseTransactionDirectionFromNumber(map['direction'] as String) ?? parseTransactionDirectionFromNumber(map['direction'] as String) ??
TransactionDirection.incoming, TransactionDirection.incoming,
date = DateTime.fromMillisecondsSinceEpoch( date = DateTime.fromMillisecondsSinceEpoch(
(int.parse(map['timestamp'] as String) ?? 0) * 1000), int.parse(map['timestamp'] as String? ?? '0') * 1000),
isPending = parseBoolFromString(map['isPending'] as String), isPending = parseBoolFromString(map['isPending'] as String),
amount = map['amount'] as int, amount = map['amount'] as int,
accountIndex = int.parse(map['accountIndex'] as String), accountIndex = int.parse(map['accountIndex'] as String),
addressIndex = map['addressIndex'] as int, addressIndex = map['addressIndex'] as int,
key = getTxKey((map['hash'] ?? '') as String), key = getTxKey((map['hash'] ?? '') as String),
fee = map['fee'] as int ?? 0; fee = map['fee'] as int? ?? 0;
HavenTransactionInfo.fromRow(TransactionInfoRow row) HavenTransactionInfo.fromRow(TransactionInfoRow row)
: id = row.getHash(), : id = row.getHash(),
@ -48,11 +48,10 @@ class HavenTransactionInfo extends TransactionInfo {
final int amount; final int amount;
final int fee; final int fee;
final int addressIndex; final int addressIndex;
String recipientAddress; late String recipientAddress;
String key; late String assetType;
String assetType; String? _fiatAmount;
String? key;
String _fiatAmount;
@override @override
String amountFormatted() => String amountFormatted() =>

View file

@ -37,15 +37,19 @@ class HavenWallet = HavenWalletBase with _$HavenWallet;
abstract class HavenWalletBase extends WalletBase<MoneroBalance, abstract class HavenWalletBase extends WalletBase<MoneroBalance,
HavenTransactionHistory, HavenTransactionInfo> with Store { HavenTransactionHistory, HavenTransactionInfo> with Store {
HavenWalletBase({WalletInfo walletInfo}) HavenWalletBase({required WalletInfo walletInfo})
: super(walletInfo) { : balance = ObservableMap.of(getHavenBalance(accountIndex: 0)),
_isTransactionUpdating = false,
_hasSyncAfterStartup = false,
walletAddresses = HavenWalletAddresses(walletInfo),
syncStatus = NotConnectedSyncStatus(),
super(walletInfo) {
transactionHistory = HavenTransactionHistory(); transactionHistory = HavenTransactionHistory();
balance = ObservableMap.of(getHavenBalance(accountIndex: 0));
_isTransactionUpdating = false;
_hasSyncAfterStartup = false;
walletAddresses = HavenWalletAddresses(walletInfo);
_onAccountChangeReaction = reaction((_) => walletAddresses.account, _onAccountChangeReaction = reaction((_) => walletAddresses.account,
(Account account) { (Account? account) {
if (account == null) {
return;
}
balance.addAll(getHavenBalance(accountIndex: account.id)); balance.addAll(getHavenBalance(accountIndex: account.id));
walletAddresses.updateSubaddressList(accountIndex: account.id); walletAddresses.updateSubaddressList(accountIndex: account.id);
}); });
@ -74,15 +78,15 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
publicSpendKey: haven_wallet.getPublicSpendKey(), publicSpendKey: haven_wallet.getPublicSpendKey(),
publicViewKey: haven_wallet.getPublicViewKey()); publicViewKey: haven_wallet.getPublicViewKey());
haven_wallet.SyncListener _listener; haven_wallet.SyncListener? _listener;
ReactionDisposer _onAccountChangeReaction; ReactionDisposer? _onAccountChangeReaction;
bool _isTransactionUpdating; bool _isTransactionUpdating;
bool _hasSyncAfterStartup; bool _hasSyncAfterStartup;
Timer _autoSaveTimer; Timer? _autoSaveTimer;
Future<void> init() async { Future<void> init() async {
await walletAddresses.init(); await walletAddresses.init();
balance.addAll(getHavenBalance(accountIndex: walletAddresses.account.id ?? 0)); balance.addAll(getHavenBalance(accountIndex: walletAddresses.account?.id ?? 0));
_setListeners(); _setListeners();
await updateTransactions(); await updateTransactions();
@ -103,19 +107,19 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
@override @override
void close() { void close() {
_listener?.stop(); _listener?.stop();
_onAccountChangeReaction?.reaction?.dispose(); _onAccountChangeReaction?.reaction.dispose();
_autoSaveTimer?.cancel(); _autoSaveTimer?.cancel();
} }
@override @override
Future<void> connectToNode({@required Node node}) async { Future<void> connectToNode({required Node node}) async {
try { try {
syncStatus = ConnectingSyncStatus(); syncStatus = ConnectingSyncStatus();
await haven_wallet.setupNode( await haven_wallet.setupNode(
address: node.uriRaw, address: node.uriRaw,
login: node.login, login: node.login,
password: node.password, password: node.password,
useSSL: node.useSSL, useSSL: node.useSSL ?? false,
isLightWallet: false); // FIXME: hardcoded value isLightWallet: false); // FIXME: hardcoded value
syncStatus = ConnectedSyncStatus(); syncStatus = ConnectedSyncStatus();
} catch (e) { } catch (e) {
@ -148,8 +152,8 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
final outputs = _credentials.outputs; final outputs = _credentials.outputs;
final hasMultiDestination = outputs.length > 1; final hasMultiDestination = outputs.length > 1;
final assetType = CryptoCurrency.fromString(_credentials.assetType.toLowerCase()); final assetType = CryptoCurrency.fromString(_credentials.assetType.toLowerCase());
final balances = getHavenBalance(accountIndex: walletAddresses.account.id); final balances = getHavenBalance(accountIndex: walletAddresses.account!.id);
final unlockedBalance = balances[assetType].unlockedBalance; final unlockedBalance = balances[assetType]!.unlockedBalance;
PendingTransactionDescription pendingTransactionDescription; PendingTransactionDescription pendingTransactionDescription;
@ -159,12 +163,12 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
if (hasMultiDestination) { if (hasMultiDestination) {
if (outputs.any((item) => item.sendAll if (outputs.any((item) => item.sendAll
|| item.formattedCryptoAmount <= 0)) { || (item.formattedCryptoAmount ?? 0) <= 0)) {
throw HavenTransactionCreationException('Wrong balance. Not enough XMR on your balance.'); throw HavenTransactionCreationException('Wrong balance. Not enough XMR on your balance.');
} }
final int totalAmount = outputs.fold(0, (acc, value) => final int totalAmount = outputs.fold(0, (acc, value) =>
acc + value.formattedCryptoAmount); acc + (value.formattedCryptoAmount ?? 0));
if (unlockedBalance < totalAmount) { if (unlockedBalance < totalAmount) {
throw HavenTransactionCreationException('Wrong balance. Not enough XMR on your balance.'); throw HavenTransactionCreationException('Wrong balance. Not enough XMR on your balance.');
@ -173,21 +177,21 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
final moneroOutputs = outputs.map((output) => final moneroOutputs = outputs.map((output) =>
MoneroOutput( MoneroOutput(
address: output.address, address: output.address,
amount: output.cryptoAmount.replaceAll(',', '.'))) amount: output.cryptoAmount!.replaceAll(',', '.')))
.toList(); .toList();
pendingTransactionDescription = pendingTransactionDescription =
await transaction_history.createTransactionMultDest( await transaction_history.createTransactionMultDest(
outputs: moneroOutputs, outputs: moneroOutputs,
priorityRaw: _credentials.priority.serialize(), priorityRaw: _credentials.priority.serialize(),
accountIndex: walletAddresses.account.id); accountIndex: walletAddresses.account!.id);
} else { } else {
final output = outputs.first; final output = outputs.first;
final address = output.address; final address = output.address;
final amount = output.sendAll final amount = output.sendAll
? null ? null
: output.cryptoAmount.replaceAll(',', '.'); : output.cryptoAmount!.replaceAll(',', '.');
final formattedAmount = output.sendAll final int? formattedAmount = output.sendAll
? null ? null
: output.formattedCryptoAmount; : output.formattedCryptoAmount;
@ -205,14 +209,14 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
assetType: _credentials.assetType, assetType: _credentials.assetType,
amount: amount, amount: amount,
priorityRaw: _credentials.priority.serialize(), priorityRaw: _credentials.priority.serialize(),
accountIndex: walletAddresses.account.id); accountIndex: walletAddresses.account!.id);
} }
return PendingHavenTransaction(pendingTransactionDescription, assetType); return PendingHavenTransaction(pendingTransactionDescription, assetType);
} }
@override @override
int calculateEstimatedFee(TransactionPriority priority, int amount) { int calculateEstimatedFee(TransactionPriority priority, int? amount) {
// FIXME: hardcoded value; // FIXME: hardcoded value;
if (priority is MoneroTransactionPriority) { if (priority is MoneroTransactionPriority) {
@ -255,7 +259,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
} }
@override @override
Future<void> rescan({int height}) async { Future<void> rescan({required int height}) async {
walletInfo.restoreHeight = height; walletInfo.restoreHeight = height;
walletInfo.isRecovery = true; walletInfo.isRecovery = true;
haven_wallet.setRefreshFromBlockHeight(height: height); haven_wallet.setRefreshFromBlockHeight(height: height);
@ -346,7 +350,7 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
} }
void _askForUpdateBalance() => void _askForUpdateBalance() =>
balance.addAll(getHavenBalance(accountIndex: walletAddresses.account.id)); balance.addAll(getHavenBalance(accountIndex: walletAddresses.account!.id));
Future<void> _askForUpdateTransactionHistory() async => Future<void> _askForUpdateTransactionHistory() async =>
await updateTransactions(); await updateTransactions();

View file

@ -12,21 +12,22 @@ class HavenWalletAddresses = HavenWalletAddressesBase
with _$HavenWalletAddresses; with _$HavenWalletAddresses;
abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Account> with Store { abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Account> with Store {
HavenWalletAddressesBase(WalletInfo walletInfo) : super(walletInfo) { HavenWalletAddressesBase(WalletInfo walletInfo)
accountList = HavenAccountList(); : accountList = HavenAccountList(),
subaddressList = HavenSubaddressList(); subaddressList = HavenSubaddressList(),
} address = '',
super(walletInfo);
@override @override
@observable @observable
String address; String address;
@override // @override
@observable @observable
Account account; Account? account;
@observable @observable
Subaddress subaddress; Subaddress? subaddress;
HavenSubaddressList subaddressList; HavenSubaddressList subaddressList;
@ -36,7 +37,7 @@ abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Accou
Future<void> init() async { Future<void> init() async {
accountList.update(); accountList.update();
account = accountList.accounts.first; account = accountList.accounts.first;
updateSubaddressList(accountIndex: account.id ?? 0); updateSubaddressList(accountIndex: account?.id ?? 0);
await updateAddressesInBox(); await updateAddressesInBox();
} }
@ -62,14 +63,14 @@ abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Accou
bool validate() { bool validate() {
accountList.update(); accountList.update();
final accountListLength = accountList.accounts?.length ?? 0; final accountListLength = accountList.accounts.length ?? 0;
if (accountListLength <= 0) { if (accountListLength <= 0) {
return false; return false;
} }
subaddressList.update(accountIndex: accountList.accounts.first.id); subaddressList.update(accountIndex: accountList.accounts.first.id);
final subaddressListLength = subaddressList.subaddresses?.length ?? 0; final subaddressListLength = subaddressList.subaddresses.length ?? 0;
if (subaddressListLength <= 0) { if (subaddressListLength <= 0) {
return false; return false;
@ -78,9 +79,9 @@ abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount<Accou
return true; return true;
} }
void updateSubaddressList({int accountIndex}) { void updateSubaddressList({required int accountIndex}) {
subaddressList.update(accountIndex: accountIndex); subaddressList.update(accountIndex: accountIndex);
subaddress = subaddressList.subaddresses.first; subaddress = subaddressList.subaddresses.first;
address = subaddress.address; address = subaddress!.address;
} }
} }

View file

@ -1,4 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:collection/collection.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/monero_wallet_utils.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
@ -13,7 +14,7 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
class HavenNewWalletCredentials extends WalletCredentials { class HavenNewWalletCredentials extends WalletCredentials {
HavenNewWalletCredentials({String name, String password, this.language}) HavenNewWalletCredentials({required String name, required this.language, String? password})
: super(name: name, password: password); : super(name: name, password: password);
final String language; final String language;
@ -21,7 +22,10 @@ class HavenNewWalletCredentials extends WalletCredentials {
class HavenRestoreWalletFromSeedCredentials extends WalletCredentials { class HavenRestoreWalletFromSeedCredentials extends WalletCredentials {
HavenRestoreWalletFromSeedCredentials( HavenRestoreWalletFromSeedCredentials(
{String name, String password, int height, this.mnemonic}) {required String name,
required String password,
required int height,
required this.mnemonic})
: super(name: name, password: password, height: height); : super(name: name, password: password, height: height);
final String mnemonic; final String mnemonic;
@ -34,13 +38,13 @@ class HavenWalletLoadingException implements Exception {
class HavenRestoreWalletFromKeysCredentials extends WalletCredentials { class HavenRestoreWalletFromKeysCredentials extends WalletCredentials {
HavenRestoreWalletFromKeysCredentials( HavenRestoreWalletFromKeysCredentials(
{String name, {required String name,
String password, required String password,
this.language, required this.language,
this.address, required this.address,
this.viewKey, required this.viewKey,
this.spendKey, required this.spendKey,
int height}) required int height})
: super(name: name, password: password, height: height); : super(name: name, password: password, height: height);
final String language; final String language;
@ -69,9 +73,9 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.createWallet( await haven_wallet_manager.createWallet(
path: path, path: path,
password: credentials.password, password: credentials.password!,
language: credentials.language); language: credentials.language);
final wallet = HavenWallet(walletInfo: credentials.walletInfo); final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init(); await wallet.init();
return wallet; return wallet;
} catch (e) { } catch (e) {
@ -104,9 +108,8 @@ class HavenWalletService extends WalletService<
await haven_wallet_manager await haven_wallet_manager
.openWalletAsync({'path': path, 'password': password}); .openWalletAsync({'path': path, 'password': password});
final walletInfo = walletInfoSource.values.firstWhere( final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()), (info) => info.id == WalletBase.idFor(name, getType()))!;
orElse: () => null);
final wallet = HavenWallet(walletInfo: walletInfo); final wallet = HavenWallet(walletInfo: walletInfo);
final isValid = wallet.walletAddresses.validate(); final isValid = wallet.walletAddresses.validate();
@ -155,13 +158,13 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.restoreFromKeys( await haven_wallet_manager.restoreFromKeys(
path: path, path: path,
password: credentials.password, password: credentials.password!,
language: credentials.language, language: credentials.language,
restoreHeight: credentials.height, restoreHeight: credentials.height!,
address: credentials.address, address: credentials.address,
viewKey: credentials.viewKey, viewKey: credentials.viewKey,
spendKey: credentials.spendKey); spendKey: credentials.spendKey);
final wallet = HavenWallet(walletInfo: credentials.walletInfo); final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init(); await wallet.init();
return wallet; return wallet;
@ -179,10 +182,10 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.restoreFromSeed( await haven_wallet_manager.restoreFromSeed(
path: path, path: path,
password: credentials.password, password: credentials.password!,
seed: credentials.mnemonic, seed: credentials.mnemonic,
restoreHeight: credentials.height); restoreHeight: credentials.height!);
final wallet = HavenWallet(walletInfo: credentials.walletInfo); final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init(); await wallet.init();
return wallet; return wallet;

View file

@ -2,7 +2,7 @@ import 'package:cw_haven/api/structs/pending_transaction.dart';
import 'package:cw_haven/api/transaction_history.dart' import 'package:cw_haven/api/transaction_history.dart'
as haven_transaction_history; as haven_transaction_history;
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/core/amount_converter.dart'; // import 'package:cake_wallet/core/amount_converter.dart';
import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/pending_transaction.dart';
class DoubleSpendException implements Exception { class DoubleSpendException implements Exception {
@ -25,13 +25,17 @@ class PendingHavenTransaction with PendingTransaction {
@override @override
String get hex => ''; String get hex => '';
// FIX-ME: AmountConverter
@override @override
String get amountFormatted => AmountConverter.amountIntToString( String get amountFormatted => '';
cryptoCurrency, pendingTransactionDescription.amount); // AmountConverter.amountIntToString(
// cryptoCurrency, pendingTransactionDescription.amount);
// FIX-ME: AmountConverter
@override @override
String get feeFormatted => AmountConverter.amountIntToString( String get feeFormatted => '';
cryptoCurrency, pendingTransactionDescription.fee); // AmountConverter.amountIntToString(
// cryptoCurrency, pendingTransactionDescription.fee);
@override @override
Future<void> commit() async { Future<void> commit() async {

View file

@ -1,7 +1,7 @@
//import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; //import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_haven/balance_list.dart'; import 'package:cw_haven/api/balance_list.dart';
//Future<void> updateHavenRate(FiatConversionStore fiatConversionStore) async { //Future<void> updateHavenRate(FiatConversionStore fiatConversionStore) async {
// final rate = getRate(); // final rate = getRate();

View file

@ -7,35 +7,35 @@ packages:
name: _fe_analyzer_shared name: _fe_analyzer_shared
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "14.0.0" version: "47.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.41.2" version: "4.7.0"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.0" version: "2.3.1"
asn1lib: asn1lib:
dependency: transitive dependency: transitive
description: description:
name: asn1lib name: asn1lib
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.8.1" version: "1.1.1"
async: async:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.5.0" version: "2.9.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -49,42 +49,42 @@ packages:
name: build name: build
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.2" version: "2.3.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.6" version: "1.1.0"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.10" version: "3.1.0"
build_resolvers: build_resolvers:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_resolvers name: build_resolvers
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.3" version: "2.0.10"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.5" version: "2.2.1"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.10" version: "7.2.4"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -105,63 +105,49 @@ packages:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.2.1"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
name: code_builder name: code_builder
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.7.0" version: "4.3.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "3.0.2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.5" version: "3.0.2"
cw_core: cw_core:
dependency: "direct main" dependency: "direct main"
description: description:
@ -175,35 +161,28 @@ packages:
name: dart_style name: dart_style
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.12" version: "2.2.4"
dartx:
dependency: transitive
description:
name: dartx
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0"
encrypt: encrypt:
dependency: transitive dependency: transitive
description: description:
name: encrypt name: encrypt
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.0" version: "5.0.1"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.1"
ffi: ffi:
dependency: "direct main" dependency: "direct main"
description: description:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "1.2.1"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -229,12 +208,19 @@ packages:
name: flutter_mobx name: flutter_mobx
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0+2" version: "2.0.6+4"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" 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: glob:
dependency: transitive dependency: transitive
description: description:
@ -248,42 +234,42 @@ packages:
name: graphs name: graphs
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0" version: "2.1.0"
hive: hive:
dependency: transitive dependency: transitive
description: description:
name: hive name: hive
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.4+1" version: "2.2.3"
hive_generator: hive_generator:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: hive_generator name: hive_generator
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.8.2" version: "1.1.3"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.2" version: "0.13.5"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
name: http_multi_server name: http_multi_server
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.0" version: "3.2.1"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.4" version: "4.0.1"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -297,7 +283,7 @@ packages:
name: io name: io
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.5" version: "1.0.3"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -311,7 +297,7 @@ packages:
name: json_annotation name: json_annotation
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.1" version: "4.6.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -325,14 +311,21 @@ packages:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted 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: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.8.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -346,63 +339,77 @@ packages:
name: mobx name: mobx
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.1+4" version: "2.1.0"
mobx_codegen: mobx_codegen:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mobx_codegen name: mobx_codegen
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.2" version: "2.0.7+3"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
name: package_config name: package_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.3" version: "2.1.0"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.2"
path_provider: path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted 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: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.1+2" version: "2.1.7"
path_provider_macos: path_provider_macos:
dependency: transitive dependency: transitive
description: description:
name: path_provider_macos name: path_provider_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.4+8" version: "2.0.6"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "2.0.4"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.4+3" version: "2.0.7"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -423,14 +430,14 @@ packages:
name: plugin_platform_interface name: plugin_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "2.1.3"
pointycastle: pointycastle:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "3.6.2"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -458,21 +465,21 @@ packages:
name: pubspec_parse name: pubspec_parse
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.8" version: "1.2.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.7.9" version: "1.3.2"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.4+1" version: "1.0.2"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -484,14 +491,21 @@ packages:
name: source_gen name: source_gen
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted 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: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.9.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -519,35 +533,28 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.19" version: "0.4.12"
time:
dependency: transitive
description:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.1"
timing: timing:
dependency: transitive dependency: transitive
description: description:
name: timing name: timing
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.1+3" version: "1.0.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -561,7 +568,7 @@ packages:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.2"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@ -575,21 +582,21 @@ packages:
name: web_socket_channel name: web_socket_channel
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "2.2.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.4+1" version: "2.6.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.2" version: "0.2.0+2"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
@ -598,5 +605,5 @@ packages:
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
sdks: sdks:
dart: ">=2.12.0 <3.0.0" dart: ">=2.17.5 <3.0.0"
flutter: ">=1.20.0" flutter: ">=2.8.1"

View file

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

View file

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

View file

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

View file

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

View file

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

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