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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,12 +5,17 @@ part 'crypto_currency.g.dart';
@HiveType(typeId: 0)
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
const CryptoCurrency({final String title, this.tag, this.name, this.iconPath, final int raw})
const CryptoCurrency({
String title = '',
int raw = -1,
this.name,
this.iconPath,
this.tag,})
: super(title: title, raw: raw);
final String tag;
final String name;
final String iconPath;
final String? tag;
final String? name;
final String? iconPath;
static const all = [
CryptoCurrency.xmr,
@ -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 xvg = CryptoCurrency(title: 'XVG', name: 'Verge', iconPath: 'assets/images/xvg_icon.png', raw: 45);
static CryptoCurrency deserialize({int raw}) {
static CryptoCurrency deserialize({required int raw}) {
switch (raw) {
case 0:
return CryptoCurrency.xmr;
@ -195,7 +197,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
case 45:
return CryptoCurrency.xvg;
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':
return CryptoCurrency.xvg;
default:
return null;
throw Exception('Unexpected token: $raw for CryptoCurrency fromString');
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,5 @@
import 'dart:io';
import 'package:cw_core/keyable.dart';
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:hive/hive.dart';
@ -11,46 +9,49 @@ import 'package:http/io_client.dart' as ioc;
part 'node.g.dart';
Uri createUriFromElectrumAddress(String address) =>
Uri.tryParse('tcp://$address');
Uri.tryParse('tcp://$address')!;
@HiveType(typeId: Node.typeId)
class Node extends HiveObject with Keyable {
Node(
{@required String uri,
@required WalletType type,
this.login,
{this.login,
this.password,
this.useSSL,
this.trusted}) {
uriRaw = uri;
this.type = type;
this.trusted = false,
String? uri,
WalletType? type,}) {
if (uri != null) {
uriRaw = uri;
}
if (type != null) {
this.type = type;
}
}
Node.fromMap(Map map)
: uriRaw = map['uri'] as String ?? '',
login = map['login'] as String,
password = map['password'] as String,
typeRaw = map['typeRaw'] as int,
useSSL = map['useSSL'] as bool,
trusted = map['trusted'] as bool ?? false;
Node.fromMap(Map<String, Object?> map)
: uriRaw = map['uri'] as String? ?? '',
login = map['login'] as String?,
password = map['password'] as String?,
useSSL = map['useSSL'] as bool?,
trusted = map['trusted'] as bool? ?? false;
static const typeId = 1;
static const boxName = 'Nodes';
@HiveField(0)
String uriRaw;
late String uriRaw;
@HiveField(1)
String login;
String? login;
@HiveField(2)
String password;
String? password;
@HiveField(3)
int typeRaw;
late int typeRaw;
@HiveField(4)
bool useSSL;
bool? useSSL;
@HiveField(5)
bool trusted;
@ -68,7 +69,7 @@ class Node extends HiveObject with Keyable {
case WalletType.haven:
return Uri.http(uriRaw, '');
default:
return null;
throw Exception('Unexpected type ${type.toString()} for Node uri');
}
}
@ -104,33 +105,32 @@ class Node extends HiveObject with Keyable {
}
Future<bool> requestMoneroNode() async {
final path = '/json_rpc';
final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path);
final realm = 'monero-rpc';
final body = {
'jsonrpc': '2.0',
'id': '0',
'jsonrpc': '2.0',
'id': '0',
'method': 'get_info'
};
try {
final authenticatingClient = HttpClient();
authenticatingClient.addCredentials(
rpcUri,
realm,
realm,
HttpClientDigestCredentials(login ?? '', password ?? ''),
);
final http.Client client = ioc.IOClient(authenticatingClient);
final response = await client.post(
rpcUri,
headers: {'Content-Type': 'application/json'},
body: json.encode(body),
);
client.close();
final resBody = json.decode(response.body) as Map<String, dynamic>;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,11 +5,11 @@ part 'unspent_coins_info.g.dart';
@HiveType(typeId: UnspentCoinsInfo.typeId)
class UnspentCoinsInfo extends HiveObject {
UnspentCoinsInfo({
this.walletId,
this.hash,
this.isFrozen,
this.isSending,
this.note});
required this.walletId,
required this.hash,
required this.isFrozen,
required this.isSending,
required this.note});
static const typeId = 9;
static const boxName = 'Unspent';

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -39,7 +39,7 @@ typedef get_node_height = Int64 Function();
typedef is_connected = 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();
@ -86,7 +86,7 @@ typedef account_set_label = 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();

View file

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

View file

@ -3,9 +3,10 @@ import 'package:ffi/ffi.dart';
class HavenBalanceRow extends Struct {
@Int64()
int amount;
Pointer<Utf8> assetType;
external int amount;
external Pointer<Utf8> assetType;
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 {
@Int64()
int rate;
Pointer<Utf8> assetType;
external int rate;
external Pointer<Utf8> assetType;
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 {
@Int64()
int amount;
external int amount;
@Int64()
int fee;
external int fee;
Pointer<Utf8> hash;
external Pointer<Utf8> hash;
String getHash() => Utf8.fromUtf8(hash);
String getHash() => hash.toDartString();
}
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 fee;

View file

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

View file

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

View file

@ -2,7 +2,7 @@ import 'dart:ffi';
import 'package:ffi/ffi.dart';
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;
void refreshSubaddresses({@required int accountIndex}) {
void refreshSubaddresses({required int accountIndex}) {
try {
isUpdating = true;
subaddressRefreshNative(accountIndex);
@ -50,18 +50,18 @@ List<SubaddressRow> getAllSubaddresses() {
.toList();
}
void addSubaddressSync({int accountIndex, String label}) {
final labelPointer = Utf8.toUtf8(label);
void addSubaddressSync({required int accountIndex, required String label}) {
final labelPointer = label.toNativeUtf8();
subaddrressAddNewNative(accountIndex, labelPointer);
free(labelPointer);
calloc.free(labelPointer);
}
void setLabelForSubaddressSync(
{int accountIndex, int addressIndex, String label}) {
final labelPointer = Utf8.toUtf8(label);
{required int accountIndex, required int addressIndex, required String label}) {
final labelPointer = label.toNativeUtf8();
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
free(labelPointer);
calloc.free(labelPointer);
}
void _addSubaddress(Map<String, dynamic> args) {
@ -80,14 +80,14 @@ void _setLabelForSubaddress(Map<String, dynamic> args) {
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>(
_addSubaddress, {'accountIndex': accountIndex, 'label': label});
await store();
}
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, {
'accountIndex': accountIndex,
'addressIndex': addressIndex,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,20 +10,20 @@ class HavenTransactionInfo extends TransactionInfo {
HavenTransactionInfo(this.id, this.height, this.direction, this.date,
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,
height = (map['height'] ?? 0) as int,
direction =
parseTransactionDirectionFromNumber(map['direction'] as String) ??
TransactionDirection.incoming,
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),
amount = map['amount'] as int,
accountIndex = int.parse(map['accountIndex'] as String),
addressIndex = map['addressIndex'] as int,
key = getTxKey((map['hash'] ?? '') as String),
fee = map['fee'] as int ?? 0;
fee = map['fee'] as int? ?? 0;
HavenTransactionInfo.fromRow(TransactionInfoRow row)
: id = row.getHash(),
@ -48,11 +48,10 @@ class HavenTransactionInfo extends TransactionInfo {
final int amount;
final int fee;
final int addressIndex;
String recipientAddress;
String key;
String assetType;
String _fiatAmount;
late String recipientAddress;
late String assetType;
String? _fiatAmount;
String? key;
@override
String amountFormatted() =>

View file

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

View file

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

View file

@ -1,4 +1,5 @@
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/monero_wallet_utils.dart';
import 'package:hive/hive.dart';
@ -13,7 +14,7 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
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);
final String language;
@ -21,7 +22,10 @@ class HavenNewWalletCredentials extends WalletCredentials {
class HavenRestoreWalletFromSeedCredentials extends WalletCredentials {
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);
final String mnemonic;
@ -34,13 +38,13 @@ class HavenWalletLoadingException implements Exception {
class HavenRestoreWalletFromKeysCredentials extends WalletCredentials {
HavenRestoreWalletFromKeysCredentials(
{String name,
String password,
this.language,
this.address,
this.viewKey,
this.spendKey,
int height})
{required String name,
required String password,
required this.language,
required this.address,
required this.viewKey,
required this.spendKey,
required int height})
: super(name: name, password: password, height: height);
final String language;
@ -69,9 +73,9 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.createWallet(
path: path,
password: credentials.password,
password: credentials.password!,
language: credentials.language);
final wallet = HavenWallet(walletInfo: credentials.walletInfo);
final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init();
return wallet;
} catch (e) {
@ -104,9 +108,8 @@ class HavenWalletService extends WalletService<
await haven_wallet_manager
.openWalletAsync({'path': path, 'password': password});
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, getType()),
orElse: () => null);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = HavenWallet(walletInfo: walletInfo);
final isValid = wallet.walletAddresses.validate();
@ -155,13 +158,13 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.restoreFromKeys(
path: path,
password: credentials.password,
password: credentials.password!,
language: credentials.language,
restoreHeight: credentials.height,
restoreHeight: credentials.height!,
address: credentials.address,
viewKey: credentials.viewKey,
spendKey: credentials.spendKey);
final wallet = HavenWallet(walletInfo: credentials.walletInfo);
final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init();
return wallet;
@ -179,10 +182,10 @@ class HavenWalletService extends WalletService<
final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.restoreFromSeed(
path: path,
password: credentials.password,
password: credentials.password!,
seed: credentials.mnemonic,
restoreHeight: credentials.height);
final wallet = HavenWallet(walletInfo: credentials.walletInfo);
restoreHeight: credentials.height!);
final wallet = HavenWallet(walletInfo: credentials.walletInfo!);
await wallet.init();
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'
as haven_transaction_history;
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';
class DoubleSpendException implements Exception {
@ -25,13 +25,17 @@ class PendingHavenTransaction with PendingTransaction {
@override
String get hex => '';
// FIX-ME: AmountConverter
@override
String get amountFormatted => AmountConverter.amountIntToString(
cryptoCurrency, pendingTransactionDescription.amount);
String get amountFormatted => '';
// AmountConverter.amountIntToString(
// cryptoCurrency, pendingTransactionDescription.amount);
// FIX-ME: AmountConverter
@override
String get feeFormatted => AmountConverter.amountIntToString(
cryptoCurrency, pendingTransactionDescription.fee);
String get feeFormatted => '';
// AmountConverter.amountIntToString(
// cryptoCurrency, pendingTransactionDescription.fee);
@override
Future<void> commit() async {

View file

@ -1,7 +1,7 @@
//import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cw_core/crypto_currency.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 {
// final rate = getRate();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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