This commit is contained in:
Rafael Saes 2023-11-14 20:17:15 -03:00
parent ff2650ad75
commit 06d9231f8d
90 changed files with 1152 additions and 719 deletions

View file

@ -4,8 +4,8 @@
# This file should be version controlled. # This file should be version controlled.
version: version:
revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: stable channel: unknown
project_type: app project_type: app
@ -13,14 +13,26 @@ project_type: app
migration: migration:
platforms: platforms:
- platform: root - platform: root
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos - platform: android
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: ios
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: linux - platform: linux
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: web
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: windows
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
# User provided section # User provided section

View file

@ -2,25 +2,24 @@ import 'dart:convert';
class BitcoinAddressRecord { class BitcoinAddressRecord {
BitcoinAddressRecord(this.address, BitcoinAddressRecord(this.address,
{required this.index, this.isHidden = false, bool isUsed = false}) {required this.index, this.isHidden = false, bool isUsed = false, this.silentAddressLabel})
: _isUsed = isUsed; : _isUsed = isUsed;
factory BitcoinAddressRecord.fromJSON(String jsonSource) { factory BitcoinAddressRecord.fromJSON(String jsonSource) {
final decoded = json.decode(jsonSource) as Map; final decoded = json.decode(jsonSource) as Map;
return BitcoinAddressRecord( return BitcoinAddressRecord(decoded['address'] as String,
decoded['address'] as String,
index: decoded['index'] as int, index: decoded['index'] as int,
isHidden: decoded['isHidden'] as bool? ?? false, isHidden: decoded['isHidden'] as bool? ?? false,
isUsed: decoded['isUsed'] as bool? ?? false); isUsed: decoded['isUsed'] as bool? ?? false);
} }
@override @override
bool operator ==(Object o) => bool operator ==(Object o) => o is BitcoinAddressRecord && address == o.address;
o is BitcoinAddressRecord && address == o.address;
final String address; final String address;
final bool isHidden; final bool isHidden;
final String? silentAddressLabel;
final int index; final int index;
bool get isUsed => _isUsed; bool get isUsed => _isUsed;
@ -32,9 +31,5 @@ class BitcoinAddressRecord {
void setAsUsed() => _isUsed = true; void setAsUsed() => _isUsed = true;
String toJSON() => String toJSON() =>
json.encode({ json.encode({'address': address, 'index': index, 'isHidden': isHidden, 'isUsed': isUsed});
'address': address,
'index': index,
'isHidden': isHidden,
'isUsed': isUsed});
} }

View file

@ -6,10 +6,9 @@ class BitcoinUnspent extends Unspent {
: bitcoinAddressRecord = addressRecord, : bitcoinAddressRecord = addressRecord,
super(addressRecord.address, hash, value, vout, null); super(addressRecord.address, hash, value, vout, null);
factory BitcoinUnspent.fromJSON( factory BitcoinUnspent.fromJSON(BitcoinAddressRecord address, Map<String, dynamic> json) =>
BitcoinAddressRecord address, Map<String, dynamic> json) => BitcoinUnspent(
BitcoinUnspent(address, json['tx_hash'] as String, json['value'] as int, address, json['tx_hash'] as String, json['value'] as int, json['tx_pos'] as int);
json['tx_pos'] as int);
final BitcoinAddressRecord bitcoinAddressRecord; final BitcoinAddressRecord bitcoinAddressRecord;
} }

View file

@ -23,77 +23,84 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
required String password, required String password,
required WalletInfo walletInfo, required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
bitcoin.NetworkType? networkType,
required Uint8List seedBytes, required Uint8List seedBytes,
required EncryptionFileUtils encryptionFileUtils, required EncryptionFileUtils encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance, ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0, int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0}) int initialChangeAddressIndex = 0,
bitcoin.SilentPaymentReceiver? silentAddress})
: super( : super(
mnemonic: mnemonic, mnemonic: mnemonic,
password: password, password: password,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
networkType: bitcoin.bitcoin, networkType: networkType ?? bitcoin.bitcoin,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialBalance: initialBalance, initialBalance: initialBalance,
seedBytes: seedBytes, seedBytes: seedBytes,
currency: CryptoCurrency.btc, currency: CryptoCurrency.btc,
encryptionFileUtils: encryptionFileUtils) { encryptionFileUtils: encryptionFileUtils) {
walletAddresses = BitcoinWalletAddresses( walletAddresses = BitcoinWalletAddresses(walletInfo,
walletInfo,
electrumClient: electrumClient, electrumClient: electrumClient,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd, mainHd: hd,
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"),
.derivePath("m/0'/1"), networkType: networkType ?? bitcoin.bitcoin,
networkType: networkType); silentAddress: silentAddress);
} }
static Future<BitcoinWallet> create({ static Future<BitcoinWallet> create(
required String mnemonic, {required String mnemonic,
required String password, required String password,
required WalletInfo walletInfo, required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
bitcoin.NetworkType? networkType,
required EncryptionFileUtils encryptionFileUtils, required EncryptionFileUtils encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance, ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0, int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0 int initialChangeAddressIndex = 0}) async {
}) async {
return BitcoinWallet( return BitcoinWallet(
mnemonic: mnemonic, mnemonic: mnemonic,
password: password, password: password,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
networkType: networkType,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialBalance: initialBalance, initialBalance: initialBalance,
encryptionFileUtils: encryptionFileUtils, encryptionFileUtils: encryptionFileUtils,
seedBytes: await mnemonicToSeedBytes(mnemonic), seedBytes: await mnemonicToSeedBytes(mnemonic),
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex); initialChangeAddressIndex: initialChangeAddressIndex,
silentAddress: await bitcoin.SilentPaymentReceiver.fromMnemonic(mnemonic,
hrp: networkType == bitcoin.bitcoin ? 'sp' : 'tsp'));
} }
static Future<BitcoinWallet> open({ static Future<BitcoinWallet> open(
required String name, {required String name,
required WalletInfo walletInfo, required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password, required String password,
required EncryptionFileUtils encryptionFileUtils, required EncryptionFileUtils encryptionFileUtils}) async {
}) async { final snp =
final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password); await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password);
return BitcoinWallet( return BitcoinWallet(
mnemonic: snp.mnemonic, mnemonic: snp.mnemonic,
password: password, password: password,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
networkType: snp.networkType,
initialAddresses: snp.addresses, initialAddresses: snp.addresses,
initialBalance: snp.balance, initialBalance: snp.balance,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic), seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
encryptionFileUtils: encryptionFileUtils, encryptionFileUtils: encryptionFileUtils,
initialRegularAddressIndex: snp.regularAddressIndex, initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex); initialChangeAddressIndex: snp.changeAddressIndex,
silentAddress: await bitcoin.SilentPaymentReceiver.fromMnemonic(snp.mnemonic,
hrp: snp.networkType == bitcoin.bitcoin ? 'sp' : 'tsp'));
} }
} }

View file

@ -18,7 +18,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
required ElectrumClient electrumClient, required ElectrumClient electrumClient,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0, int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0}) int initialChangeAddressIndex = 0,
bitcoin.SilentPaymentReceiver? silentAddress})
: super(walletInfo, : super(walletInfo,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
@ -26,9 +27,11 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
mainHd: mainHd, mainHd: mainHd,
sideHd: sideHd, sideHd: sideHd,
electrumClient: electrumClient, electrumClient: electrumClient,
networkType: networkType); networkType: networkType,
silentAddress: silentAddress);
@override @override
String getAddress({required int index, required bitcoin.HDWallet hd}) => String getAddress({required int index, required bitcoin.HDWallet hd}) =>
generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); generateP2WPKHAddress(hd: hd, index: index, networkType: networkType);
} }

View file

@ -12,11 +12,10 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
class BitcoinWalletService extends WalletService< class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
BitcoinNewWalletCredentials, BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> {
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials> {
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
@ -27,12 +26,13 @@ class BitcoinWalletService extends WalletService<
WalletType getType() => WalletType.bitcoin; WalletType getType() => WalletType.bitcoin;
@override @override
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async { Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
final wallet = await BitcoinWalletBase.create( final wallet = await BitcoinWalletBase.create(
mnemonic: await generateMnemonic(), mnemonic: await generateMnemonic(),
password: credentials.password!, password: credentials.password!,
walletInfo: credentials.walletInfo!, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource, unspentCoinsInfo: unspentCoinsInfoSource,
networkType: isTestnet == true ? bitcoin.testnet : bitcoin.bitcoin,
encryptionFileUtils: encryptionFileUtilsFor(isDirect)); encryptionFileUtils: encryptionFileUtilsFor(isDirect));
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();
@ -45,8 +45,8 @@ class BitcoinWalletService extends WalletService<
@override @override
Future<BitcoinWallet> openWallet(String name, String password) async { Future<BitcoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull( final walletInfo = walletInfoSource.values
(info) => info.id == WalletBase.idFor(name, getType()))!; .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await BitcoinWalletBase.open( final wallet = await BitcoinWalletBase.open(
password: password, password: password,
name: name, name: name,
@ -59,17 +59,16 @@ class BitcoinWalletService extends WalletService<
@override @override
Future<void> remove(String wallet) async { Future<void> remove(String wallet) async {
File(await pathForWalletDir(name: wallet, type: getType())) File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
.delete(recursive: true); final walletInfo = walletInfoSource.values
final walletInfo = walletInfoSource.values.firstWhereOrNull( .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
await walletInfoSource.delete(walletInfo.key); await walletInfoSource.delete(walletInfo.key);
} }
@override @override
Future<void> rename(String currentName, String password, String newName) async { Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( final currentWalletInfo = walletInfoSource.values
(info) => info.id == WalletBase.idFor(currentName, getType()))!; .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await BitcoinWalletBase.open( final currentWallet = await BitcoinWalletBase.open(
password: password, password: password,
name: currentName, name: currentName,
@ -87,13 +86,11 @@ class BitcoinWalletService extends WalletService<
} }
@override @override
Future<BitcoinWallet> restoreFromKeys( Future<BitcoinWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async =>
BitcoinRestoreWalletFromWIFCredentials credentials) async =>
throw UnimplementedError(); throw UnimplementedError();
@override @override
Future<BitcoinWallet> restoreFromSeed( Future<BitcoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async {
BitcoinRestoreWalletFromSeedCredentials credentials) async {
if (!validateMnemonic(credentials.mnemonic)) { if (!validateMnemonic(credentials.mnemonic)) {
throw BitcoinMnemonicIsIncorrectException(); throw BitcoinMnemonicIsIncorrectException();
} }

View file

@ -8,6 +8,7 @@ import 'package:cw_bitcoin/script_hash.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:http/http.dart' as http;
String jsonrpcparams(List<Object> params) { String jsonrpcparams(List<Object> params) {
final _params = params?.map((val) => '"${val.toString()}"')?.join(','); final _params = params?.map((val) => '"${val.toString()}"')?.join(',');
@ -22,10 +23,7 @@ String jsonrpc(
'{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n'; '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n';
class SocketTask { class SocketTask {
SocketTask({ SocketTask({required this.isSubscription, this.completer, this.subject});
required this.isSubscription,
this.completer,
this.subject});
final Completer<dynamic>? completer; final Completer<dynamic>? completer;
final BehaviorSubject<dynamic>? subject; final BehaviorSubject<dynamic>? subject;
@ -51,8 +49,7 @@ class ElectrumClient {
Timer? _aliveTimer; Timer? _aliveTimer;
String unterminatedString; String unterminatedString;
Future<void> connectToUri(Uri uri) async => Future<void> connectToUri(Uri uri) async => await connect(host: uri.host, port: uri.port);
await connect(host: uri.host, port: uri.port);
Future<void> connect({required String host, required int port}) async { Future<void> connect({required String host, required int port}) async {
try { try {
@ -104,21 +101,20 @@ class ElectrumClient {
} }
if (isJSONStringCorrect(unterminatedString)) { if (isJSONStringCorrect(unterminatedString)) {
final response = final response = json.decode(unterminatedString) as Map<String, dynamic>;
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response); _handleResponse(response);
unterminatedString = ''; unterminatedString = '';
} }
} on TypeError catch (e) { } on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) { if (!e.toString().contains('Map<String, Object>') &&
!e.toString().contains('Map<String, dynamic>')) {
return; return;
} }
unterminatedString += message; unterminatedString += message;
if (isJSONStringCorrect(unterminatedString)) { if (isJSONStringCorrect(unterminatedString)) {
final response = final response = json.decode(unterminatedString) as Map<String, dynamic>;
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response); _handleResponse(response);
// unterminatedString = null; // unterminatedString = null;
unterminatedString = ''; unterminatedString = '';
@ -142,8 +138,7 @@ class ElectrumClient {
} }
} }
Future<List<String>> version() => Future<List<String>> version() => call(method: 'server.version').then((dynamic result) {
call(method: 'server.version').then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) => val.toString()).toList(); return result.map((dynamic val) => val.toString()).toList();
} }
@ -181,8 +176,7 @@ class ElectrumClient {
String address, NetworkType networkType) => String address, NetworkType networkType) =>
call( call(
method: 'blockchain.scripthash.listunspent', method: 'blockchain.scripthash.listunspent',
params: [scriptHash(address, networkType: networkType)]) params: [scriptHash(address, networkType: networkType)]).then((dynamic result) {
.then((dynamic result) {
if (result is List) { if (result is List) {
return result.map((dynamic val) { return result.map((dynamic val) {
if (val is Map<String, dynamic>) { if (val is Map<String, dynamic>) {
@ -229,19 +223,25 @@ class ElectrumClient {
return []; return [];
}); });
Future<Map<String, dynamic>> getTransactionRaw( Future<dynamic> getTransactionRaw(
{required String hash}) async => {required String hash, required NetworkType networkType}) async =>
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000) callWithTimeout(
method: 'blockchain.transaction.get',
params: networkType == bitcoin ? [hash, true] : [hash],
timeout: 10000)
.then((dynamic result) { .then((dynamic result) {
if (result is Map<String, dynamic>) { if (result is Map<String, dynamic>) {
return result; return result;
} }
if (networkType == testnet && result is String) {
return result;
}
return <String, dynamic>{}; return <String, dynamic>{};
}); });
Future<String> getTransactionHex( Future<String> getTransactionHex({required String hash}) async =>
{required String hash}) async =>
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000) callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000)
.then((dynamic result) { .then((dynamic result) {
if (result is String) { if (result is String) {
@ -251,9 +251,19 @@ class ElectrumClient {
return ''; return '';
}); });
Future<String> broadcastTransaction( Future<String> broadcastTransaction({required String transactionRaw}) async {
{required String transactionRaw}) async => return http
call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'),
headers: <String, String>{'Content-Type': 'application/json; charset=utf-8'},
body: transactionRaw)
.then((http.Response response) {
if (response.statusCode == 200) {
return response.body;
}
return '';
});
return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) { .then((dynamic result) {
if (result is String) { if (result is String) {
return result; return result;
@ -261,20 +271,17 @@ class ElectrumClient {
return ''; return '';
}); });
}
Future<Map<String, dynamic>> getMerkle( Future<Map<String, dynamic>> getMerkle({required String hash, required int height}) async =>
{required String hash, required int height}) async => await call(method: 'blockchain.transaction.get_merkle', params: [hash, height])
await call(
method: 'blockchain.transaction.get_merkle',
params: [hash, height]) as Map<String, dynamic>;
Future<Map<String, dynamic>> getHeader({required int height}) async =>
await call(method: 'blockchain.block.get_header', params: [height])
as Map<String, dynamic>; as Map<String, dynamic>;
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]) call(method: 'blockchain.estimatefee', params: [p]).then((dynamic result) {
.then((dynamic result) {
if (result is double) { if (result is double) {
return result; return result;
} }
@ -319,15 +326,9 @@ class ElectrumClient {
final topDoubleString = await estimatefee(p: 1); final topDoubleString = await estimatefee(p: 1);
final middleDoubleString = await estimatefee(p: 5); final middleDoubleString = await estimatefee(p: 5);
final bottomDoubleString = await estimatefee(p: 100); final bottomDoubleString = await estimatefee(p: 100);
final top = final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000).round();
(stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000) final middle = (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000).round();
.round(); final bottom = (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000).round();
final middle =
(stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000)
.round();
final bottom =
(stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000)
.round();
return [bottom, middle, top]; return [bottom, middle, top];
} catch (_) { } catch (_) {
@ -335,6 +336,21 @@ class ElectrumClient {
} }
} }
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-headers-subscribe
// example response:
// {
// "height": 520481,
// "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4"
// }
Future<int?> getCurrentBlockChainTip() =>
call(method: 'blockchain.headers.subscribe').then((result) {
if (result is Map<String, dynamic>) {
return result["height"] as int;
}
return null;
});
BehaviorSubject<Object>? scripthashUpdate(String scripthash) { BehaviorSubject<Object>? scripthashUpdate(String scripthash) {
_id += 1; _id += 1;
return subscribe<Object>( return subscribe<Object>(
@ -344,16 +360,14 @@ class ElectrumClient {
} }
BehaviorSubject<T>? subscribe<T>( BehaviorSubject<T>? subscribe<T>(
{required String id, {required String id, required String method, List<Object> params = const []}) {
required String method,
List<Object> params = const []}) {
try { try {
final subscription = BehaviorSubject<T>(); final subscription = BehaviorSubject<T>();
_regisrySubscription(id, subscription); _regisrySubscription(id, subscription);
socket!.write(jsonrpc(method: method, id: _id, params: params)); socket!.write(jsonrpc(method: method, id: _id, params: params));
return subscription; return subscription;
} catch(e) { } catch (e) {
print(e.toString()); print(e.toString());
return null; return null;
} }
@ -370,9 +384,7 @@ class ElectrumClient {
} }
Future<dynamic> callWithTimeout( Future<dynamic> callWithTimeout(
{required String method, {required String method, List<Object> params = const [], int timeout = 4000}) async {
List<Object> params = const [],
int timeout = 4000}) async {
try { try {
final completer = Completer<dynamic>(); final completer = Completer<dynamic>();
_id += 1; _id += 1;
@ -386,7 +398,7 @@ class ElectrumClient {
}); });
return completer.future; return completer.future;
} catch(e) { } catch (e) {
print(e.toString()); print(e.toString());
} }
} }
@ -397,8 +409,8 @@ class ElectrumClient {
onConnectionStatusChange = null; onConnectionStatusChange = null;
} }
void _registryTask(int id, Completer<dynamic> completer) => _tasks[id.toString()] = void _registryTask(int id, Completer<dynamic> completer) =>
SocketTask(completer: completer, isSubscription: false); _tasks[id.toString()] = SocketTask(completer: completer, isSubscription: false);
void _regisrySubscription(String id, BehaviorSubject<dynamic> subject) => void _regisrySubscription(String id, BehaviorSubject<dynamic> subject) =>
_tasks[id] = SocketTask(subject: subject, isSubscription: true); _tasks[id] = SocketTask(subject: subject, isSubscription: true);
@ -419,8 +431,7 @@ class ElectrumClient {
} }
} }
void _methodHandler( void _methodHandler({required String method, required Map<String, dynamic> request}) {
{required String method, required Map<String, dynamic> request}) {
switch (method) { switch (method) {
case 'blockchain.scripthash.subscribe': case 'blockchain.scripthash.subscribe':
final params = request['params'] as List<dynamic>; final params = request['params'] as List<dynamic>;
@ -452,7 +463,7 @@ class ElectrumClient {
return; return;
} }
if (id != null){ if (id != null) {
_finish(id, result); _finish(id, result);
} }
} }

View file

@ -36,7 +36,8 @@ import 'package:cw_bitcoin/electrum.dart';
import 'package:hex/hex.dart'; import 'package:hex/hex.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:bip32/bip32.dart'; // import 'package:bip32/bip32.dart';
import 'package:http/http.dart' as http;
part 'electrum_wallet.g.dart'; part 'electrum_wallet.g.dart';
@ -76,16 +77,12 @@ abstract class ElectrumWalletBase
super(walletInfo) { super(walletInfo) {
this.electrumClient = electrumClient ?? ElectrumClient(); this.electrumClient = electrumClient ?? ElectrumClient();
this.walletInfo = walletInfo; this.walletInfo = walletInfo;
transactionHistory = transactionHistory = ElectrumTransactionHistory(
ElectrumTransactionHistory( walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils);
walletInfo: walletInfo,
password: password,
encryptionFileUtils: encryptionFileUtils);
} }
static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) =>
bitcoin.HDWallet.fromSeed(seedBytes) bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0");
.derivePath("m/44'/145'/0'/0");
static int estimatedTransactionSize(int inputsCount, int outputsCounts) => static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
inputsCount * 146 + outputsCounts * 33 + 8; inputsCount * 146 + outputsCounts * 33 + 8;
@ -210,9 +207,7 @@ abstract class ElectrumWalletBase
throw BitcoinTransactionNoInputsException(); throw BitcoinTransactionNoInputsException();
} }
final allAmountFee = transactionCredentials.feeRate != null final allAmountFee = 222;
? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length)
: feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length);
final allAmount = allInputsAmount - allAmountFee; final allAmount = allInputsAmount - allAmountFee;
@ -261,14 +256,14 @@ abstract class ElectrumWalletBase
} }
} }
if (fee == 0) { if (fee == 0 && networkType == bitcoin.bitcoin) {
throw BitcoinTransactionWrongBalanceException(currency); // throw BitcoinTransactionWrongBalanceException(currency);
} }
final totalAmount = amount + fee; final totalAmount = amount + fee;
if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) {
throw BitcoinTransactionWrongBalanceException(currency); // throw BitcoinTransactionWrongBalanceException(currency);
} }
final txb = bitcoin.TransactionBuilder(network: networkType); final txb = bitcoin.TransactionBuilder(network: networkType);
@ -295,16 +290,33 @@ abstract class ElectrumWalletBase
} }
if (amount <= 0 || totalInputAmount < totalAmount) { if (amount <= 0 || totalInputAmount < totalAmount) {
throw BitcoinTransactionWrongBalanceException(currency); // throw BitcoinTransactionWrongBalanceException(currency);
} }
txb.setVersion(1); txb.setVersion(1);
List<bitcoin.PrivateKeyInfo> inputPrivKeys = [];
List<bitcoin.Outpoint> outpoints = [];
inputs.forEach((input) { inputs.forEach((input) {
inputPrivKeys.add(bitcoin.PrivateKeyInfo(
bitcoin.PrivateKey.fromHex(
bitcoin.getSecp256k1(),
HEX.encode(generateKeyPair(
hd: input.bitcoinAddressRecord.isHidden
? walletAddresses.sideHd
: walletAddresses.mainHd,
index: input.bitcoinAddressRecord.index,
network: networkType)
.privateKey!)),
false));
outpoints.add(bitcoin.Outpoint(txid: input.hash, index: input.vout));
if (input.isP2wpkh) { if (input.isP2wpkh) {
final p2wpkh = bitcoin final p2wpkh = bitcoin
.P2WPKH( .P2WPKH(
data: generatePaymentData( data: generatePaymentData(
hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, hd: input.bitcoinAddressRecord.isHidden
? walletAddresses.sideHd
: walletAddresses.mainHd,
index: input.bitcoinAddressRecord.index), index: input.bitcoinAddressRecord.index),
network: networkType) network: networkType)
.data; .data;
@ -315,21 +327,48 @@ abstract class ElectrumWalletBase
} }
}); });
List<bitcoin.SilentPaymentDestination> silentAddresses = [];
outputs.forEach((item) { outputs.forEach((item) {
final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
if (outputAddress.startsWith('tsp1')) {
silentAddresses
.add(bitcoin.SilentPaymentDestination.fromAddress(outputAddress, outputAmount!));
} else {
txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!); txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!);
}
}); });
final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); if (silentAddresses.isNotEmpty) {
var feeAmount = 0; final outpointsHash = bitcoin.SilentPayment.hashOutpoints(outpoints);
if (transactionCredentials.feeRate != null) { final aSum = bitcoin.SilentPayment.getSumInputPrivKeys(inputPrivKeys);
feeAmount = transactionCredentials.feeRate! * estimatedSize;
} else { final generatedOutputs = bitcoin.SilentPayment.generateMultipleRecipientPubkeys(
feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; aSum, outpointsHash, silentAddresses);
generatedOutputs.forEach((recipientSilentAddress, generatedOutput) {
generatedOutput.forEach((output) {
final generatedPubkey = output.$1.toCompressedHex();
txb.addOutput(
bitcoin.ECPublic.fromHex(generatedPubkey)
.toTaprootAddress()
.toScriptPubKey()
.toBytes(),
amount);
});
});
} }
final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1);
var feeAmount = 222;
// if (transactionCredentials.feeRate != null) {
// feeAmount = transactionCredentials.feeRate! * estimatedSize;
// } else {
// feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize;
// }
final changeValue = totalInputAmount - amount - feeAmount; final changeValue = totalInputAmount - amount - feeAmount;
if (changeValue > minAmount) { if (changeValue > minAmount) {
@ -360,7 +399,8 @@ abstract class ElectrumWalletBase
'account_index': walletAddresses.currentReceiveAddressIndex.toString(), 'account_index': walletAddresses.currentReceiveAddressIndex.toString(),
'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(),
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
'balance': balance[currency]?.toJSON() 'balance': balance[currency]?.toJSON(),
'network_type': networkType.toString()
}); });
int feeRate(TransactionPriority priority) { int feeRate(TransactionPriority priority) {
@ -476,17 +516,78 @@ abstract class ElectrumWalletBase
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
Future<void> updateUnspent() async { Future<void> updateUnspent() async {
final unspent = await Future.wait(walletAddresses final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient
.addresses.map((address) => electrumClient
.getListUnspentWithAddress(address.address, networkType) .getListUnspentWithAddress(address.address, networkType)
.then((unspent) => unspent .then((unspent) => unspent.map((unspent) {
.map((unspent) {
try { try {
return BitcoinUnspent.fromJSON(address, unspent); return BitcoinUnspent.fromJSON(address, unspent);
} catch(_) { } catch (_) {
return null; return null;
} }
}).whereNotNull()))); }).whereNotNull())));
final txid = "28a21e8b6373bf20928107f8f1f1ea5a98ada793f2676372d03466e874d4e762";
final uri = Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx/$txid');
// final uri = Uri(scheme: 'https', host: 'blockstream.info', path: 'testnet/api/block-height/0');
await http.get(uri).then((response) {
// print(response.body);
final obj = json.decode(response.body);
final scanPrivateKey = walletAddresses.silentAddress!.scanPrivkey;
final spendPublicKey = walletAddresses.silentAddress!.spendPubkey;
List<String> pubkeys = [];
List<bitcoin.Outpoint> outpoints = [];
obj["vin"].forEach((input) {
final witness = input["witness"] as List<dynamic>;
final pubkey = witness[1] as String;
pubkeys.add(pubkey);
outpoints.add(bitcoin.Outpoint(txid: input["txid"] as String, index: input["vout"] as int));
});
Uint8List sumOfInputPublicKeys =
bitcoin.getSumInputPubKeys(pubkeys).toCompressedHex().fromHex;
final outpointHash = bitcoin.SilentPayment.hashOutpoints(outpoints);
Map<String, bitcoin.Outpoint> outpointsByP2TRpubkey = {};
int i = 0;
obj['vout'].forEach((out) {
if (out["scriptpubkey_type"] == "v1_p2tr")
outpointsByP2TRpubkey[out['scriptpubkey_address'] as String] =
bitcoin.Outpoint(txid: txid, index: i, value: out["value"] as int);
i++;
});
final result = bitcoin.scanOutputs(
scanPrivateKey.toCompressedHex().fromHex,
spendPublicKey.toCompressedHex().fromHex,
sumOfInputPublicKeys,
outpointHash,
outpointsByP2TRpubkey.keys.toList());
// print(result);
result.forEach((key, value) {
final outpoint = outpointsByP2TRpubkey[key];
// if (outpoint != null) {
// unspentCoins.add(BitcoinUnspent(
// BitcoinAddressRecord(walletAddresses.silentAddress.toString(), index: 0),
// outpoint.txid,
// outpoint.value!,
// outpoint.n));
// final currentBalance = balance[currency];
// if (currentBalance != null) {
// balance[currency] = ElectrumBalance(
// confirmed: currentBalance.confirmed + outpoint.value!,
// unconfirmed: currentBalance.unconfirmed,
// frozen: currentBalance.frozen);
// } else {
// balance[currency] =
// ElectrumBalance(confirmed: outpoint.value!, unconfirmed: 0, frozen: 0);
// }
// }
});
});
unspentCoins = unspent.expand((e) => e).toList(); unspentCoins = unspent.expand((e) => e).toList();
if (unspentCoinsInfo.isEmpty) { if (unspentCoinsInfo.isEmpty) {
@ -555,12 +656,23 @@ abstract class ElectrumWalletBase
Future<ElectrumTransactionBundle> getTransactionExpanded( Future<ElectrumTransactionBundle> getTransactionExpanded(
{required String hash, required int height}) async { {required String hash, required int height}) async {
final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); final verboseTransaction =
final transactionHex = verboseTransaction['hex'] as String; await electrumClient.getTransactionRaw(hash: hash, networkType: networkType);
String transactionHex;
int? time;
int confirmations = 0;
if (networkType == bitcoin.testnet) {
transactionHex = verboseTransaction as String;
confirmations = 1;
} else {
transactionHex = verboseTransaction['hex'] as String;
time = verboseTransaction['time'] as int?;
confirmations = verboseTransaction['confirmations'] as int? ?? 0;
}
final original = bitcoin.Transaction.fromHex(transactionHex); final original = bitcoin.Transaction.fromHex(transactionHex);
final ins = <bitcoin.Transaction>[]; final ins = <bitcoin.Transaction>[];
final time = verboseTransaction['time'] as int?;
final confirmations = verboseTransaction['confirmations'] as int? ?? 0;
for (final vin in original.ins) { for (final vin in original.ins) {
final id = HEX.encode(vin.hash!.reversed.toList()); final id = HEX.encode(vin.hash!.reversed.toList());
@ -666,7 +778,7 @@ abstract class ElectrumWalletBase
final addresses = walletAddresses.addresses.toList(); final addresses = walletAddresses.addresses.toList();
final balanceFutures = <Future<Map<String, dynamic>>>[]; final balanceFutures = <Future<Map<String, dynamic>>>[];
for (var i = 0; i < addresses.length; i++) { for (var i = 0; i < addresses.length; i++) {
final addressRecord = addresses[i] ; final addressRecord = addresses[i];
final sh = scriptHash(addressRecord.address, networkType: networkType); final sh = scriptHash(addressRecord.address, networkType: networkType);
final balanceFuture = electrumClient.getBalance(sh); final balanceFuture = electrumClient.getBalance(sh);
balanceFutures.add(balanceFuture); balanceFutures.add(balanceFuture);
@ -734,4 +846,32 @@ abstract class ElectrumWalletBase
? base64Encode(hd.sign(message)) ? base64Encode(hd.sign(message))
: base64Encode(hd.derive(index).sign(message)); : base64Encode(hd.derive(index).sign(message));
} }
// int _getHeightByDate(DateTime date) {
// final nodeHeight = monero_wallet.getNodeHeightSync();
// final heightDistance = _getHeightDistance(date);
// if (nodeHeight <= 0) {
// return 0;
// }
// return nodeHeight - heightDistance;
// }
// Silent payments initial sync height
// inspiried my monero_wallet.dart's _setInitialHeight()
void _setInitialHeight() async {
if (walletInfo.isRecovery) {
return;
}
final currentHeight = await electrumClient.getCurrentBlockChainTip();
if (currentHeight == null) return;
// if (currentHeight <= 1) {
// final height = _getHeightByDate(walletInfo.date);
// monero_wallet.setRecoveringFromSeed(isRecovery: true);
// monero_wallet.setRefreshFromBlockHeight(height: height);
// }
}
} }

View file

@ -10,8 +10,7 @@ import 'package:mobx/mobx.dart';
part 'electrum_wallet_addresses.g.dart'; part 'electrum_wallet_addresses.g.dart';
class ElectrumWalletAddresses = ElectrumWalletAddressesBase class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
with _$ElectrumWalletAddresses;
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
ElectrumWalletAddressesBase(WalletInfo walletInfo, ElectrumWalletAddressesBase(WalletInfo walletInfo,
@ -21,17 +20,19 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
required this.networkType, required this.networkType,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0, int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0}) int initialChangeAddressIndex = 0,
: addresses = ObservableList<BitcoinAddressRecord>.of( bitcoin.SilentPaymentReceiver? silentAddress})
(initialAddresses ?? []).toSet()), : addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
receiveAddresses = ObservableList<BitcoinAddressRecord>.of( silentAddress = silentAddress,
(initialAddresses ?? []) receiveAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed)
.toSet()), .toSet()),
changeAddresses = ObservableList<BitcoinAddressRecord>.of( changeAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
(initialAddresses ?? [])
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed)
.toSet()), .toSet()),
silentAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
.where((addressRecord) => addressRecord.silentAddressLabel != null)
.toSet()),
currentReceiveAddressIndex = initialRegularAddressIndex, currentReceiveAddressIndex = initialRegularAddressIndex,
currentChangeAddressIndex = initialChangeAddressIndex, currentChangeAddressIndex = initialChangeAddressIndex,
super(walletInfo); super(walletInfo);
@ -45,14 +46,20 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final ObservableList<BitcoinAddressRecord> addresses; final ObservableList<BitcoinAddressRecord> addresses;
final ObservableList<BitcoinAddressRecord> receiveAddresses; final ObservableList<BitcoinAddressRecord> receiveAddresses;
final ObservableList<BitcoinAddressRecord> changeAddresses; final ObservableList<BitcoinAddressRecord> changeAddresses;
final ObservableList<BitcoinAddressRecord> silentAddresses;
final ElectrumClient electrumClient; final ElectrumClient electrumClient;
final bitcoin.NetworkType networkType; final bitcoin.NetworkType networkType;
final bitcoin.HDWallet mainHd; final bitcoin.HDWallet mainHd;
final bitcoin.HDWallet sideHd; final bitcoin.HDWallet sideHd;
@override // TODO: labels -> disable edit on receive page
final bitcoin.SilentPaymentReceiver? silentAddress;
@observable
String? activeAddress;
@computed @computed
String get address { String get receiveAddress {
if (receiveAddresses.isEmpty) { if (receiveAddresses.isEmpty) {
final address = generateNewAddress().address; final address = generateNewAddress().address;
return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address;
@ -63,14 +70,27 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
} }
@override @override
set address(String addr) => null; @computed
String get address {
if (activeAddress != null) {
return activeAddress!;
}
if (receiveAddresses.isEmpty) {
return generateNewAddress().address;
}
return receiveAddresses.first.address;
}
@override
set address(String addr) => activeAddress = addr;
int currentReceiveAddressIndex; int currentReceiveAddressIndex;
int currentChangeAddressIndex; int currentChangeAddressIndex;
@computed @computed
int get totalCountOfReceiveAddresses => int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) {
addresses.fold(0, (acc, addressRecord) {
if (!addressRecord.isHidden) { if (!addressRecord.isHidden) {
return acc + 1; return acc + 1;
} }
@ -78,8 +98,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}); });
@computed @computed
int get totalCountOfChangeAddresses => int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) {
addresses.fold(0, (acc, addressRecord) {
if (addressRecord.isHidden) { if (addressRecord.isHidden) {
return acc + 1; return acc + 1;
} }
@ -115,9 +134,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if (changeAddresses.isEmpty) { if (changeAddresses.isEmpty) {
final newAddresses = await _createNewAddresses(gap, final newAddresses = await _createNewAddresses(gap,
hd: sideHd, hd: sideHd,
startIndex: totalCountOfChangeAddresses > 0 startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0,
? totalCountOfChangeAddresses - 1
: 0,
isHidden: true); isHidden: true);
_addAddresses(newAddresses); _addAddresses(newAddresses);
} }
@ -133,8 +150,24 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
} }
BitcoinAddressRecord generateNewAddress( BitcoinAddressRecord generateNewAddress(
{bitcoin.HDWallet? hd, bool isHidden = false}) { {bitcoin.HDWallet? hd, bool isHidden = false, String? label}) {
currentReceiveAddressIndex += 1; if (label != null && silentAddress != null) {
final address = BitcoinAddressRecord(
bitcoin.SilentPaymentAddress.createLabeledSilentPaymentAddress(
silentAddress!.scanPubkey,
silentAddress!.spendPubkey,
'0000000000000000000000000000000000000000000000000000000000000002'.fromHex,
hrp: silentAddress!.hrp,
version: silentAddress!.version)
.toString(),
index: currentReceiveAddressIndex,
isHidden: isHidden,
silentAddressLabel: label);
silentAddresses.add(address);
return address;
}
// FIX-ME: Check logic for whichi HD should be used here ??? // FIX-ME: Check logic for whichi HD should be used here ???
final address = BitcoinAddressRecord( final address = BitcoinAddressRecord(
getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd), getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd),
@ -142,6 +175,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
isHidden: isHidden); isHidden: isHidden);
addresses.add(address); addresses.add(address);
return address; return address;
currentReceiveAddressIndex += 1;
} }
String getAddress({required int index, required bitcoin.HDWallet hd}) => ''; String getAddress({required int index, required bitcoin.HDWallet hd}) => '';
@ -160,16 +195,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
@action @action
void updateReceiveAddresses() { void updateReceiveAddresses() {
receiveAddresses.removeRange(0, receiveAddresses.length); receiveAddresses.removeRange(0, receiveAddresses.length);
final newAdresses = addresses final newAdresses =
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
receiveAddresses.addAll(newAdresses); receiveAddresses.addAll(newAdresses);
} }
@action @action
void updateChangeAddresses() { void updateChangeAddresses() {
changeAddresses.removeRange(0, changeAddresses.length); changeAddresses.removeRange(0, changeAddresses.length);
final newAdresses = addresses final newAdresses =
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed);
changeAddresses.addAll(newAdresses); changeAddresses.addAll(newAdresses);
} }
@ -178,20 +213,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
List<BitcoinAddressRecord> addrs; List<BitcoinAddressRecord> addrs;
if (addresses.isNotEmpty) { if (addresses.isNotEmpty) {
addrs = addresses addrs = addresses.where((addr) => addr.isHidden == isHidden).toList();
.where((addr) => addr.isHidden == isHidden)
.toList();
} else { } else {
addrs = await _createNewAddresses( addrs = await _createNewAddresses(
isHidden isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount,
? defaultChangeAddressesCount
: defaultReceiveAddressesCount,
startIndex: 0, startIndex: 0,
hd: hd, hd: hd,
isHidden: isHidden); isHidden: isHidden);
} }
while(hasAddrUse) { while (hasAddrUse) {
final addr = addrs.last.address; final addr = addrs.last.address;
hasAddrUse = await _hasAddressUsed(addr); hasAddrUse = await _hasAddressUsed(addr);
@ -201,11 +232,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final start = addrs.length; final start = addrs.length;
final count = start + gap; final count = start + gap;
final batch = await _createNewAddresses( final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden);
count,
startIndex: start,
hd: hd,
isHidden: isHidden);
addrs.addAll(batch); addrs.addAll(batch);
} }
@ -229,21 +256,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if (countOfReceiveAddresses < defaultReceiveAddressesCount) { if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
final newAddresses = await _createNewAddresses( final newAddresses = await _createNewAddresses(addressesCount,
addressesCount, startIndex: countOfReceiveAddresses, hd: mainHd, isHidden: false);
startIndex: countOfReceiveAddresses,
hd: mainHd,
isHidden: false);
addresses.addAll(newAddresses); addresses.addAll(newAddresses);
} }
if (countOfHiddenAddresses < defaultChangeAddressesCount) { if (countOfHiddenAddresses < defaultChangeAddressesCount) {
final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
final newAddresses = await _createNewAddresses( final newAddresses = await _createNewAddresses(addressesCount,
addressesCount, startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true);
startIndex: countOfHiddenAddresses,
hd: sideHd,
isHidden: true);
addresses.addAll(newAddresses); addresses.addAll(newAddresses);
} }
} }
@ -253,10 +274,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final list = <BitcoinAddressRecord>[]; final list = <BitcoinAddressRecord>[];
for (var i = startIndex; i < count + startIndex; i++) { for (var i = startIndex; i < count + startIndex; i++) {
final address = BitcoinAddressRecord( final address =
getAddress(index: i, hd: hd), BitcoinAddressRecord(getAddress(index: i, hd: hd), index: i, isHidden: isHidden);
index: i,
isHidden: isHidden);
list.add(address); list.add(address);
} }

View file

@ -4,6 +4,7 @@ import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_core/encryption_file_utils.dart'; import 'package:cw_core/encryption_file_utils.dart';
import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
class ElectrumWallletSnapshot { class ElectrumWallletSnapshot {
ElectrumWallletSnapshot({ ElectrumWallletSnapshot({
@ -13,6 +14,7 @@ class ElectrumWallletSnapshot {
required this.mnemonic, required this.mnemonic,
required this.addresses, required this.addresses,
required this.balance, required this.balance,
required this.networkType,
required this.regularAddressIndex, required this.regularAddressIndex,
required this.changeAddressIndex}); required this.changeAddressIndex});
@ -23,6 +25,7 @@ class ElectrumWallletSnapshot {
String mnemonic; String mnemonic;
List<BitcoinAddressRecord> addresses; List<BitcoinAddressRecord> addresses;
ElectrumBalance balance; ElectrumBalance balance;
bitcoin.NetworkType networkType;
int regularAddressIndex; int regularAddressIndex;
int changeAddressIndex; int changeAddressIndex;
@ -38,6 +41,7 @@ class ElectrumWallletSnapshot {
.toList(); .toList();
final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? final balance = ElectrumBalance.fromJSON(data['balance'] as String) ??
ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0);
final networkType = bitcoin.testnet;
var regularAddressIndex = 0; var regularAddressIndex = 0;
var changeAddressIndex = 0; var changeAddressIndex = 0;
@ -53,6 +57,7 @@ class ElectrumWallletSnapshot {
mnemonic: mnemonic, mnemonic: mnemonic,
addresses: addresses, addresses: addresses,
balance: balance, balance: balance,
networkType: networkType,
regularAddressIndex: regularAddressIndex, regularAddressIndex: regularAddressIndex,
changeAddressIndex: changeAddressIndex); changeAddressIndex: changeAddressIndex);
} }

View file

@ -27,7 +27,7 @@ class LitecoinWalletService extends WalletService<
WalletType getType() => WalletType.litecoin; WalletType getType() => WalletType.litecoin;
@override @override
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async { Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
final wallet = await LitecoinWalletBase.create( final wallet = await LitecoinWalletBase.create(
mnemonic: await generateMnemonic(), mnemonic: await generateMnemonic(),
password: credentials.password!, password: credentials.password!,

View file

@ -21,18 +21,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.2"
asn1lib: asn1lib:
dependency: transitive dependency: transitive
description: description:
name: asn1lib name: asn1lib
sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -78,11 +78,9 @@ packages:
bitcoin_flutter: bitcoin_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "/home/rafael/Storage/Repositories/bitcoin_flutter"
ref: cake-update-v3 relative: false
resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d source: path
url: "https://github.com/cake-tech/bitcoin_flutter.git"
source: git
version: "2.0.2" version: "2.0.2"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
@ -104,10 +102,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.4.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
@ -120,10 +118,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "4.0.0"
build_resolvers: build_resolvers:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -136,18 +134,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.6"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.7" version: "7.2.10"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -160,10 +158,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0" sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.4.4" version: "8.6.3"
cake_backup: cake_backup:
dependency: transitive dependency: transitive
description: description:
@ -185,10 +183,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.0.3"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -201,10 +199,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: code_builder name: code_builder
sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.0" version: "4.7.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@ -225,10 +223,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.3"
cryptography: cryptography:
dependency: "direct main" dependency: "direct main"
description: description:
@ -241,10 +239,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cupertino_icons name: cupertino_icons
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.0.6"
cw_core: cw_core:
dependency: "direct main" dependency: "direct main"
description: description:
@ -252,6 +250,14 @@ packages:
relative: true relative: true
source: path source: path
version: "0.0.1" version: "0.0.1"
dart_bech32:
dependency: transitive
description:
name: dart_bech32
sha256: "0e1dc1ff39c9669c9ffeafd5d675104918f7b50799692491badfea7e1fb40888"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
@ -260,14 +266,23 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.4" version: "2.2.4"
elliptic:
dependency: transitive
description:
path: "."
ref: silent-payments
resolved-ref: ad7b1cccb54b5feba8ead4a0f67cb98a5a01a88b
url: "https://github.com/cake-tech/dart-elliptic"
source: git
version: "0.3.10"
encrypt: encrypt:
dependency: "direct main" dependency: "direct main"
description: description:
name: encrypt name: encrypt
sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.1" version: "5.0.3"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -280,10 +295,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.1.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -296,10 +311,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "1.1.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -309,10 +324,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_mobx name: flutter_mobx
sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" sha256: "2ba0aa5a42811eaaeff2e35626689cf2b8a3869907d0e8889c914f2c95d8fd76"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.6+5" version: "2.1.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -330,18 +345,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.1"
hex: hex:
dependency: transitive dependency: transitive
description: description:
@ -418,18 +433,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.0" version: "4.8.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -466,18 +481,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: mobx name: mobx
sha256: "6738620307a424d2c9ad8b873f4dce391c44e9135eb4e75668ac8202fec7a9b8" sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.1"
mobx_codegen: mobx_codegen:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mobx_codegen name: mobx_codegen
sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.3.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -498,74 +521,74 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.13" version: "2.1.1"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.24" version: "2.2.1"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "026b97a6c29da75181a37aae2eba9227f5fe13cb2838c6b975ce209328b8ab4e" sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.3.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.10" version: "2.2.1"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.6" version: "2.1.1"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.5" version: "2.2.1"
platform: platform:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "3.1.3"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: plugin_platform_interface name: plugin_platform_interface
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.6"
pointycastle: pointycastle:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.6.2" version: "3.7.3"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -574,30 +597,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
process: provider:
dependency: transitive dependency: transitive
description: description:
name: process name: provider
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.4" version: "6.0.5"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.4"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.3"
rxdart: rxdart:
dependency: "direct main" dependency: "direct main"
description: description:
@ -610,18 +633,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.1"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.3" version: "1.0.4"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -711,18 +734,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: tuple name: tuple
sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.0.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.2"
unorm_dart: unorm_dart:
dependency: "direct main" dependency: "direct main"
description: description:
@ -743,42 +766,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.1.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.4.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "5.0.9"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.3"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0" flutter: ">=3.7.0"

View file

@ -20,9 +20,7 @@ dependencies:
cw_core: cw_core:
path: ../cw_core path: ../cw_core
bitcoin_flutter: bitcoin_flutter:
git: path: /home/rafael/Storage/Repositories/bitcoin_flutter
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake-update-v3
bitbox: bitbox:
git: git:
url: https://github.com/cake-tech/bitbox-flutter.git url: https://github.com/cake-tech/bitbox-flutter.git

View file

@ -29,8 +29,7 @@ class BitcoinCashWalletService extends WalletService<BitcoinCashNewWalletCredent
File(await pathForWallet(name: name, type: getType())).existsSync(); File(await pathForWallet(name: name, type: getType())).existsSync();
@override @override
Future<BitcoinCashWallet> create( Future<BitcoinCashWallet> create(credentials, {bool? isTestnet}) async {
credentials) async {
final wallet = await BitcoinCashWalletBase.create( final wallet = await BitcoinCashWalletBase.create(
mnemonic: await Mnemonic.generate(), mnemonic: await Mnemonic.generate(),
password: credentials.password!, password: credentials.password!,

View file

@ -1 +1 @@
/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ /home/rafael/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/

View file

@ -1,6 +1,6 @@
// This is a generated file; do not edit or check into version control. // This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=C:\Users\borod\flutter FLUTTER_ROOT=/home/rafael/Storage/Repositories/Build Sources/flutter
FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash FLUTTER_APPLICATION_PATH=/opt/android/cake_wallet/cw_bitcoin_cash
COCOAPODS_PARALLEL_CODE_SIGN=true COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_BUILD_DIR=build FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=0.0.1 FLUTTER_BUILD_NAME=0.0.1

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=C:\Users\borod\flutter" export "FLUTTER_ROOT=/home/rafael/Storage/Repositories/Build Sources/flutter"
export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash" export "FLUTTER_APPLICATION_PATH=/opt/android/cake_wallet/cw_bitcoin_cash"
export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=0.0.1" export "FLUTTER_BUILD_NAME=0.0.1"

View file

@ -22,9 +22,7 @@ dependencies:
cw_bitcoin: cw_bitcoin:
path: ../cw_bitcoin path: ../cw_bitcoin
bitcoin_flutter: bitcoin_flutter:
git: path: /home/rafael/Storage/Repositories/bitcoin_flutter
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake-update-v3
bitbox: bitbox:
git: git:
url: https://github.com/cake-tech/bitbox-flutter.git url: https://github.com/cake-tech/bitbox-flutter.git

View file

@ -14,5 +14,9 @@ class Unspent {
bool isFrozen; bool isFrozen;
String note; String note;
bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); bool get isP2wpkh =>
address.startsWith('bc') ||
// testnet
address.startsWith('tb') ||
address.startsWith('ltc');
} }

View file

@ -8,7 +8,7 @@ abstract class WalletService<N extends WalletCredentials, RFS extends WalletCred
RFK extends WalletCredentials> { RFK extends WalletCredentials> {
WalletType getType(); WalletType getType();
Future<WalletBase> create(N credentials); Future<WalletBase> create(N credentials, {bool? isTestnet});
Future<WalletBase> restoreFromSeed(RFS credentials); Future<WalletBase> restoreFromSeed(RFS credentials);

View file

@ -21,7 +21,7 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
final bool isDirect; final bool isDirect;
@override @override
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async { Future<EthereumWallet> create(EthereumNewWalletCredentials credentials, {bool? isTestnet}) async {
final mnemonic = bip39.generateMnemonic(); final mnemonic = bip39.generateMnemonic();
final wallet = EthereumWallet( final wallet = EthereumWallet(
walletInfo: credentials.walletInfo!, walletInfo: credentials.walletInfo!,

View file

@ -68,7 +68,7 @@ class HavenWalletService extends WalletService<
WalletType getType() => WalletType.haven; WalletType getType() => WalletType.haven;
@override @override
Future<HavenWallet> create(HavenNewWalletCredentials credentials) async { Future<HavenWallet> create(HavenNewWalletCredentials credentials, {bool? isTestnet}) async {
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await haven_wallet_manager.createWallet( await haven_wallet_manager.createWallet(

View file

@ -69,10 +69,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "4.0.0"
build_resolvers: build_resolvers:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -85,10 +85,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.6"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
@ -407,18 +407,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: mobx name: mobx
sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3+1" version: "2.2.1"
mobx_codegen: mobx_codegen:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mobx_codegen name: mobx_codegen
sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.3.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:

View file

@ -4,8 +4,8 @@
# This file should be version controlled. # This file should be version controlled.
version: version:
revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: stable channel: unknown
project_type: plugin project_type: plugin
@ -13,14 +13,20 @@ project_type: plugin
migration: migration:
platforms: platforms:
- platform: root - platform: root
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos - platform: android
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: ios
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: linux - platform: linux
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
# User provided section # User provided section

View file

@ -425,4 +425,4 @@ packages:
version: "0.2.0+3" version: "0.2.0+3"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0" flutter: ">=3.0.6"

View file

@ -40,9 +40,10 @@ const moneroBlockSize = 1000;
class MoneroWallet = MoneroWalletBase with _$MoneroWallet; class MoneroWallet = MoneroWalletBase with _$MoneroWallet;
abstract class MoneroWalletBase extends WalletBase<MoneroBalance, abstract class MoneroWalletBase
MoneroTransactionHistory, MoneroTransactionInfo> with Store { extends WalletBase<MoneroBalance, MoneroTransactionHistory, MoneroTransactionInfo> with Store {
MoneroWalletBase({required WalletInfo walletInfo, MoneroWalletBase(
{required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password}) required String password})
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({ : balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
@ -160,8 +161,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
login: node.login, login: node.login,
password: node.password, password: node.password,
useSSL: node.isSSL, useSSL: node.isSSL,
isLightWallet: false,
// FIXME: hardcoded value // FIXME: hardcoded value
isLightWallet: false,
socksProxyAddress: node.socksProxyAddress); socksProxyAddress: node.socksProxyAddress);
monero_wallet.setTrustedDaemon(node.trusted); monero_wallet.setTrustedDaemon(node.trusted);

View file

@ -65,7 +65,7 @@ class MoneroWalletService extends WalletService<
WalletType getType() => WalletType.monero; WalletType getType() => WalletType.monero;
@override @override
Future<MoneroWallet> create(MoneroNewWalletCredentials credentials) async { Future<MoneroWallet> create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async {
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await monero_wallet_manager.createWallet( await monero_wallet_manager.createWallet(

View file

@ -0,0 +1,10 @@
#include <flutter_linux/flutter_linux.h>
#include "include/cw_monero/cw_monero_plugin.h"
// This file exposes some plugin internals for unit testing. See
// https://github.com/flutter/flutter/issues/88724 for current limitations
// in the unit-testable API.
// Handles the getPlatformVersion method call.
FlMethodResponse *get_platform_version();

View file

@ -0,0 +1,31 @@
#include <flutter_linux/flutter_linux.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "include/cw_monero/cw_monero_plugin.h"
#include "cw_monero_plugin_private.h"
// This demonstrates a simple unit test of the C portion of this plugin's
// implementation.
//
// Once you have built the plugin's example app, you can run these tests
// from the command line. For instance, for a plugin called my_plugin
// built for x64 debug, run:
// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test
namespace cw_monero {
namespace test {
TEST(CwMoneroPlugin, GetPlatformVersion) {
g_autoptr(FlMethodResponse) response = get_platform_version();
ASSERT_NE(response, nullptr);
ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
FlValue* result = fl_method_success_response_get_result(
FL_METHOD_SUCCESS_RESPONSE(response));
ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
// The full string varies, so just validate that it has the right format.
EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux "));
}
} // namespace test
} // namespace cw_monero

View file

@ -21,18 +21,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.2"
asn1lib: asn1lib:
dependency: transitive dependency: transitive
description: description:
name: asn1lib name: asn1lib
sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -53,10 +53,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.4.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
@ -69,10 +69,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "4.0.0"
build_resolvers: build_resolvers:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -85,18 +85,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.6"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.7" version: "7.2.10"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -109,10 +109,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.4.3" version: "8.6.3"
cake_backup: cake_backup:
dependency: transitive dependency: transitive
description: description:
@ -134,10 +134,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.0.3"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -150,10 +150,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: code_builder name: code_builder
sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.0" version: "4.7.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@ -174,10 +174,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.3"
cryptography: cryptography:
dependency: transitive dependency: transitive
description: description:
@ -213,10 +213,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: encrypt name: encrypt
sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.1" version: "5.0.3"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -229,10 +229,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: ffi name: ffi
sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.1.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -258,10 +258,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_mobx name: flutter_mobx
sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" sha256: "2ba0aa5a42811eaaeff2e35626689cf2b8a3869907d0e8889c914f2c95d8fd76"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.6+5" version: "2.1.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -279,18 +279,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.3.1"
hive: hive:
dependency: transitive dependency: transitive
description: description:
@ -359,18 +359,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.0" version: "4.8.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -407,18 +407,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: mobx name: mobx
sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3+1" version: "2.2.1"
mobx_codegen: mobx_codegen:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: mobx_codegen name: mobx_codegen
sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.3.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -439,74 +447,74 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.12" version: "2.1.1"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.22" version: "2.2.1"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.3.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.7" version: "2.2.1"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.5" version: "2.1.1"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.5" version: "2.2.1"
platform: platform:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "3.1.3"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: plugin_platform_interface name: plugin_platform_interface
sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.6"
pointycastle: pointycastle:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.6.2" version: "3.7.3"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -515,46 +523,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
process: provider:
dependency: transitive dependency: transitive
description: description:
name: process name: provider
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.4" version: "6.0.5"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.4"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.3"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.1"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.3" version: "1.0.4"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -652,10 +660,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.2"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -668,42 +676,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.1.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.4.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "5.0.9"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0+3" version: "1.0.3"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0" flutter: ">=3.7.0"

View file

@ -7,7 +7,7 @@ homepage: https://cakewallet.com
environment: environment:
sdk: ">=2.17.5 <3.0.0" sdk: ">=2.17.5 <3.0.0"
flutter: ">=1.20.0" flutter: ">=3.0.6"
dependencies: dependencies:
flutter: flutter:

View file

@ -28,7 +28,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
WalletType getType() => WalletType.nano; WalletType getType() => WalletType.nano;
@override @override
Future<WalletBase> create(NanoNewWalletCredentials credentials) async { Future<WalletBase> create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async {
// nano standard: // nano standard:
DerivationType derivationType = DerivationType.nano; DerivationType derivationType = DerivationType.nano;
String seedKey = NanoSeeds.generateSeed(); String seedKey = NanoSeeds.generateSeed();

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,12 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View file

@ -64,9 +64,9 @@ class CWBitcoin extends Bitcoin {
} }
@override @override
Future<void> generateNewAddress(Object wallet) async { Future<void> generateNewAddress(Object wallet, {String? label}) async {
final bitcoinWallet = wallet as ElectrumWallet; final bitcoinWallet = wallet as ElectrumWallet;
await bitcoinWallet.walletAddresses.generateNewAddress(); await bitcoinWallet.walletAddresses.generateNewAddress(label: label);
} }
@override @override
@ -106,6 +106,21 @@ class CWBitcoin extends Bitcoin {
return bitcoinWallet.walletAddresses.address; return bitcoinWallet.walletAddresses.address;
} }
String getReceiveAddress(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
return bitcoinWallet.walletAddresses.receiveAddress;
}
btc.SilentPaymentAddress? getSilentAddress(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
return bitcoinWallet.walletAddresses.silentAddress;
}
List<BitcoinAddressRecord> getSilentAddresses(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
return bitcoinWallet.walletAddresses.silentAddresses;
}
@override @override
String formatterBitcoinAmountToString({required int amount}) String formatterBitcoinAmountToString({required int amount})
=> bitcoinAmountToString(amount: amount); => bitcoinAmountToString(amount: amount);

View file

@ -25,7 +25,10 @@ class AddressValidator extends TextValidator {
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$' return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$'; '|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
case CryptoCurrency.btc: case CryptoCurrency.btc:
return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$'; final p2sh = '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$';
final testnet = '^tb1[0-9a-zA-Z]{59}\$|^tb1[0-9a-zA-Z]{39}\$';
final silentpayments = '^tsp1[0-9a-zA-Z]{113}\$';
return '^bc1[0-9a-zA-Z]{59}\$|$p2sh|$testnet|$silentpayments';
case CryptoCurrency.nano: case CryptoCurrency.nano:
return '[0-9a-zA-Z_]'; return '[0-9a-zA-Z_]';
case CryptoCurrency.banano: case CryptoCurrency.banano:

View file

@ -49,7 +49,7 @@ class WalletCreationService {
} }
} }
Future<WalletBase> create(WalletCredentials credentials) async { Future<WalletBase> create(WalletCredentials credentials, {bool? isTestnet}) async {
checkIfExists(credentials.name); checkIfExists(credentials.name);
if (credentials.password == null) { if (credentials.password == null) {
@ -58,7 +58,7 @@ class WalletCreationService {
password: credentials.password!, walletName: credentials.name); password: credentials.password!, walletName: credentials.name);
} }
final wallet = await _service!.create(credentials); final wallet = await _service!.create(credentials, isTestnet: isTestnet);
if (wallet.type == WalletType.monero) { if (wallet.type == WalletType.monero) {
await sharedPreferences.setBool( await sharedPreferences.setBool(

View file

@ -532,8 +532,7 @@ Future<void> setup({
getIt.registerFactory<Modify2FAPage>( getIt.registerFactory<Modify2FAPage>(
() => Modify2FAPage(setup2FAViewModel: getIt.get<Setup2FAViewModel>())); () => Modify2FAPage(setup2FAViewModel: getIt.get<Setup2FAViewModel>()));
getIt.registerFactory<DesktopSettingsPage>( getIt.registerFactory<DesktopSettingsPage>(() => DesktopSettingsPage());
() => DesktopSettingsPage());
getIt.registerFactoryParam<ReceiveOptionViewModel, ReceivePageOption?, void>( getIt.registerFactoryParam<ReceiveOptionViewModel, ReceivePageOption?, void>(
(pageOption, _) => ReceiveOptionViewModel(getIt.get<AppStore>().wallet!, pageOption)); (pageOption, _) => ReceiveOptionViewModel(getIt.get<AppStore>().wallet!, pageOption));
@ -653,7 +652,7 @@ Future<void> setup({
getIt.registerFactory<MoneroAccountListViewModel>(() { getIt.registerFactory<MoneroAccountListViewModel>(() {
final wallet = getIt.get<AppStore>().wallet!; final wallet = getIt.get<AppStore>().wallet!;
if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) { if (true) {
return MoneroAccountListViewModel(wallet); return MoneroAccountListViewModel(wallet);
} }
throw Exception( throw Exception(
@ -848,8 +847,8 @@ Future<void> setup({
return ethereum!.createEthereumWalletService( return ethereum!.createEthereumWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput); _walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.bitcoinCash: case WalletType.bitcoinCash:
return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource, return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource,
SettingsStoreBase.walletPasswordDirectInput); _unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.nano: case WalletType.nano:
return nano!.createNanoWalletService( return nano!.createNanoWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput); _walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
@ -1155,8 +1154,8 @@ Future<void> setup({
IoniaPaymentStatusPage( IoniaPaymentStatusPage(
getIt.get<IoniaPaymentStatusViewModel>(param1: paymentInfo, param2: committedInfo))); getIt.get<IoniaPaymentStatusViewModel>(param1: paymentInfo, param2: committedInfo)));
getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, WalletType, void>( getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, void, void>(
(type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get<SettingsStore>())); (type, _) => AdvancedPrivacySettingsViewModel(getIt.get<SettingsStore>()));
getIt.registerFactoryParam<WalletUnlockLoadableViewModel, WalletUnlockArguments, void>((args, _) { getIt.registerFactoryParam<WalletUnlockLoadableViewModel, WalletUnlockArguments, void>((args, _) {
final currentWalletName = final currentWalletName =

View file

@ -1,37 +1,37 @@
import 'dart:async'; // import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart'; // import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/sync_status.dart'; // import 'package:cw_core/sync_status.dart';
import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/settings_store.dart';
Timer? _checkConnectionTimer; // Timer? _checkConnectionTimer;
void startCheckConnectionReaction( void startCheckConnectionReaction(
WalletBase wallet, SettingsStore settingsStore, WalletBase wallet, SettingsStore settingsStore,
{int timeInterval = 5}) { {int timeInterval = 5}) {
_checkConnectionTimer?.cancel(); // _checkConnectionTimer?.cancel();
_checkConnectionTimer = // _checkConnectionTimer =
Timer.periodic(Duration(seconds: timeInterval), (_) async { // Timer.periodic(Duration(seconds: timeInterval), (_) async {
try { // try {
final connectivityResult = await (Connectivity().checkConnectivity()); // final connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) { // if (connectivityResult == ConnectivityResult.none) {
wallet.syncStatus = FailedSyncStatus(); // wallet.syncStatus = FailedSyncStatus();
return; // return;
} // }
if (wallet.syncStatus is LostConnectionSyncStatus || // if (wallet.syncStatus is LostConnectionSyncStatus ||
wallet.syncStatus is FailedSyncStatus) { // wallet.syncStatus is FailedSyncStatus) {
final alive = // final alive =
await settingsStore.getCurrentNode(wallet.type).requestNode(); // await settingsStore.getCurrentNode(wallet.type).requestNode();
if (alive) { // if (alive) {
await wallet.connectToNode( // await wallet.connectToNode(
node: settingsStore.getCurrentNode(wallet.type)); // node: settingsStore.getCurrentNode(wallet.type));
} // }
} // }
} catch (e) { // } catch (e) {
print(e.toString()); // print(e.toString());
} // }
}); // });
} }

View file

@ -124,7 +124,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.newWalletFromWelcome: case Routes.newWalletFromWelcome:
if (SettingsStoreBase.walletPasswordDirectInput) { if (SettingsStoreBase.walletPasswordDirectInput) {
if (availableWalletTypes.length == 1) { if (availableWalletTypes.length == 1) {
return createRoute(RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first)); return createRoute(
RouteSettings(name: Routes.newWallet, arguments: availableWalletTypes.first));
} else { } else {
return createRoute(RouteSettings(name: Routes.newWalletType)); return createRoute(RouteSettings(name: Routes.newWalletType));
} }
@ -295,16 +296,14 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.auth: case Routes.auth:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true,
builder: (_) builder: (_) => SettingsStoreBase.walletPasswordDirectInput
=> SettingsStoreBase.walletPasswordDirectInput
? getIt.get<WalletUnlockPage>( ? getIt.get<WalletUnlockPage>(
param1: WalletUnlockArguments( param1: WalletUnlockArguments(
callback: settings.arguments as OnAuthenticationFinished), callback: settings.arguments as OnAuthenticationFinished),
instanceName: 'wallet_unlock_verifiable', instanceName: 'wallet_unlock_verifiable',
param2: true) param2: true)
: getIt.get<AuthPage>( : getIt.get<AuthPage>(
param1: settings.arguments as OnAuthenticationFinished, param1: settings.arguments as OnAuthenticationFinished, param2: true));
param2: true));
case Routes.totpAuthCodePage: case Routes.totpAuthCodePage:
final args = settings.arguments as TotpAuthArgumentsModel; final args = settings.arguments as TotpAuthArgumentsModel;
@ -318,8 +317,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.walletUnlockLoadable: case Routes.walletUnlockLoadable:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true,
builder: (_) builder: (_) => getIt.get<WalletUnlockPage>(
=> getIt.get<WalletUnlockPage>(
param1: settings.arguments as WalletUnlockArguments, param1: settings.arguments as WalletUnlockArguments,
instanceName: 'wallet_unlock_loadable', instanceName: 'wallet_unlock_loadable',
param2: true)); param2: true));
@ -327,8 +325,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.unlock: case Routes.unlock:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true,
builder: (_) builder: (_) => SettingsStoreBase.walletPasswordDirectInput
=> SettingsStoreBase.walletPasswordDirectInput
? WillPopScope( ? WillPopScope(
child: getIt.get<WalletUnlockPage>( child: getIt.get<WalletUnlockPage>(
param1: WalletUnlockArguments( param1: WalletUnlockArguments(
@ -338,8 +335,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
onWillPop: () async => false) onWillPop: () async => false)
: WillPopScope( : WillPopScope(
child: getIt.get<AuthPage>( child: getIt.get<AuthPage>(
param1: settings.arguments as OnAuthenticationFinished, param1: settings.arguments as OnAuthenticationFinished, param2: false),
param2: false),
onWillPop: () async => false)); onWillPop: () async => false));
case Routes.connectionSync: case Routes.connectionSync:
@ -380,7 +376,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
: getIt.get<AuthPage>(instanceName: 'login'), : getIt.get<AuthPage>(instanceName: 'login'),
onWillPop: () async => onWillPop: () async =>
// FIX-ME: Additional check does it works correctly // FIX-ME: Additional check does it works correctly
(await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ?? false)), (await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ??
false)),
fullscreenDialog: true); fullscreenDialog: true);
case Routes.newPowNode: case Routes.newPowNode:
@ -470,8 +467,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.support: case Routes.support:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
fullscreenDialog: true, fullscreenDialog: true, builder: (_) => getIt.get<SupportPage>());
builder: (_) => getIt.get<SupportPage>());
case Routes.supportLiveChat: case Routes.supportLiveChat:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<SupportChatPage>()); return CupertinoPageRoute<void>(builder: (_) => getIt.get<SupportChatPage>());
@ -575,7 +571,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
builder: (_) => AdvancedPrivacySettingsPage( builder: (_) => AdvancedPrivacySettingsPage(
getIt.get<AdvancedPrivacySettingsViewModel>(param1: type), getIt.get<AdvancedPrivacySettingsViewModel>(),
getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false), getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
)); ));

View file

@ -161,10 +161,10 @@ class AddressPage extends BasePage {
Observer(builder: (_) { Observer(builder: (_) {
if (addressListViewModel.hasAddressList) { if (addressListViewModel.hasAddressList) {
return GestureDetector( return GestureDetector(
onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled onTap: () async => !addressListViewModel.hasSilentAddresses &&
dashboardViewModel.isAutoGenerateSubaddressesEnabled
? await showPopUp<void>( ? await showPopUp<void>(
context: context, context: context, builder: (_) => getIt.get<MoneroAccountListPage>())
builder: (_) => getIt.get<MoneroAccountListPage>())
: Navigator.of(context).pushNamed(Routes.receive), : Navigator.of(context).pushNamed(Routes.receive),
child: Container( child: Container(
height: 50, height: 50,
@ -185,11 +185,14 @@ class AddressPage extends BasePage {
children: <Widget>[ children: <Widget>[
Observer( Observer(
builder: (_) { builder: (_) {
String label = addressListViewModel.hasAccounts String label = addressListViewModel.hasSilentAddresses
? S.of(context).address_and_silent_addresses
: addressListViewModel.hasAccounts
? S.of(context).accounts_subaddresses ? S.of(context).accounts_subaddresses
: S.of(context).addresses; : S.of(context).addresses;
if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { if (!addressListViewModel.hasSilentAddresses &&
dashboardViewModel.isAutoGenerateSubaddressesEnabled) {
label = addressListViewModel.hasAccounts label = addressListViewModel.hasAccounts
? S.of(context).accounts ? S.of(context).accounts
: S.of(context).account; : S.of(context).account;
@ -203,7 +206,8 @@ class AddressPage extends BasePage {
.extension<SyncIndicatorTheme>()! .extension<SyncIndicatorTheme>()!
.textColor), .textColor),
); );
},), },
),
Icon( Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
size: 14, size: 14,
@ -213,7 +217,8 @@ class AddressPage extends BasePage {
), ),
), ),
); );
} else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || addressListViewModel.showElectrumAddressDisclaimer) { } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled ||
addressListViewModel.showElectrumAddressDisclaimer) {
return Text(S.of(context).electrum_address_disclaimer, return Text(S.of(context).electrum_address_disclaimer,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/entities/generate_name.dart'; import 'package:cake_wallet/entities/generate_name.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/main.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
@ -253,6 +254,12 @@ class _WalletNameFormState extends State<WalletNameForm> {
), ),
), ),
], ],
Observer(builder: (context) {
return SettingsSwitcherCell(
title: S.current.use_testnet,
value: widget._walletNewVM.useTestnet,
onValueChange: (_, __) => widget._walletNewVM.toggleUseTestnet());
}),
], ],
), ),
), ),

View file

@ -67,8 +67,7 @@ class ReceivePage extends BasePage {
@override @override
Widget Function(BuildContext, Widget) get rootWrapper => Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
GradientBackground(scaffold: scaffold);
@override @override
Widget trailing(BuildContext context) { Widget trailing(BuildContext context) {
@ -99,7 +98,8 @@ class ReceivePage extends BasePage {
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
return (addressListViewModel.type == WalletType.monero || return (addressListViewModel.type == WalletType.bitcoin ||
addressListViewModel.type == WalletType.monero ||
addressListViewModel.type == WalletType.haven || addressListViewModel.type == WalletType.haven ||
addressListViewModel.type == WalletType.nano || addressListViewModel.type == WalletType.nano ||
addressListViewModel.type == WalletType.banano) addressListViewModel.type == WalletType.banano)
@ -156,7 +156,8 @@ class ReceivePage extends BasePage {
icon: Icon( icon: Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
size: 14, size: 14,
color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor, color:
Theme.of(context).extension<ReceivePageTheme>()!.iconsColor,
)); ));
} }
@ -164,11 +165,12 @@ class ReceivePage extends BasePage {
cell = HeaderTile( cell = HeaderTile(
onTap: () => onTap: () =>
Navigator.of(context).pushNamed(Routes.newSubaddress), Navigator.of(context).pushNamed(Routes.newSubaddress),
title: S.of(context).addresses, title: S.of(context).silent_addresses,
icon: Icon( icon: Icon(
Icons.add, Icons.add,
size: 20, size: 20,
color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor, color:
Theme.of(context).extension<ReceivePageTheme>()!.iconsColor,
)); ));
} }
@ -177,11 +179,19 @@ class ReceivePage extends BasePage {
final isCurrent = final isCurrent =
item.address == addressListViewModel.address.address; item.address == addressListViewModel.address.address;
final backgroundColor = isCurrent final backgroundColor = isCurrent
? Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor ? Theme.of(context)
: Theme.of(context).extension<ReceivePageTheme>()!.tilesBackgroundColor; .extension<ReceivePageTheme>()!
.currentTileBackgroundColor
: Theme.of(context)
.extension<ReceivePageTheme>()!
.tilesBackgroundColor;
final textColor = isCurrent final textColor = isCurrent
? Theme.of(context).extension<ReceivePageTheme>()!.currentTileTextColor ? Theme.of(context)
: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor; .extension<ReceivePageTheme>()!
.currentTileTextColor
: Theme.of(context)
.extension<ReceivePageTheme>()!
.tilesTextColor;
return AddressCell.fromItem(item, return AddressCell.fromItem(item,
isCurrent: isCurrent, isCurrent: isCurrent,
@ -202,6 +212,15 @@ class ReceivePage extends BasePage {
child: cell, child: cell,
); );
})), })),
Padding(
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
child: Text(S.of(context).electrum_address_disclaimer,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
color:
Theme.of(context).extension<BalancePageTheme>()!.labelTextColor)),
),
], ],
), ),
)) ))

View file

@ -2,7 +2,7 @@ import 'package:cake_wallet/core/seed_validator.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Annotation extends Comparable<Annotation> { class Annotation implements Comparable<Annotation> {
Annotation({required this.range, required this.style}); Annotation({required this.range, required this.style});
final TextRange range; final TextRange range;

View file

@ -1,7 +1,6 @@
import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/settings_store.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
part 'advanced_privacy_settings_view_model.g.dart'; part 'advanced_privacy_settings_view_model.g.dart';
@ -10,7 +9,7 @@ class AdvancedPrivacySettingsViewModel = AdvancedPrivacySettingsViewModelBase
with _$AdvancedPrivacySettingsViewModel; with _$AdvancedPrivacySettingsViewModel;
abstract class AdvancedPrivacySettingsViewModelBase with Store { abstract class AdvancedPrivacySettingsViewModelBase with Store {
AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) : _addCustomNode = false; AdvancedPrivacySettingsViewModelBase(this._settingsStore) : _addCustomNode = false;
@computed @computed
ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus; ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus;
@ -21,8 +20,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
@observable @observable
bool _addCustomNode = false; bool _addCustomNode = false;
final WalletType type;
final SettingsStore _settingsStore; final SettingsStore _settingsStore;
@computed @computed

View file

@ -65,6 +65,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
bool get hasAuthCredentials => bool get hasAuthCredentials =>
_walletType == WalletType.monero || _walletType == WalletType.haven; _walletType == WalletType.monero || _walletType == WalletType.haven;
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
String get uri { String get uri {
var uri = address; var uri = address;

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
@ -27,8 +28,7 @@ class AddressEditOrCreateStateFailure extends AddressEditOrCreateState {
} }
abstract class WalletAddressEditOrCreateViewModelBase with Store { abstract class WalletAddressEditOrCreateViewModelBase with Store {
WalletAddressEditOrCreateViewModelBase( WalletAddressEditOrCreateViewModelBase({required WalletBase wallet, WalletAddressListItem? item})
{required WalletBase wallet, WalletAddressListItem? item})
: isEdit = item != null, : isEdit = item != null,
state = AddressEditOrCreateStateInitial(), state = AddressEditOrCreateStateInitial(),
label = item?.name ?? '', label = item?.name ?? '',
@ -68,27 +68,21 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
if (wallet.type == WalletType.bitcoin if (wallet.type == WalletType.bitcoin
|| wallet.type == WalletType.litecoin || wallet.type == WalletType.litecoin
|| wallet.type == WalletType.bitcoinCash) { || wallet.type == WalletType.bitcoinCash) {
await bitcoin!.generateNewAddress(wallet); await bitcoin!.generateNewAddress(wallet, label: label);
await wallet.save(); await wallet.save();
} }
if (wallet.type == WalletType.monero) { if (wallet.type == WalletType.monero) {
await monero await monero!
!.getSubaddressList(wallet) .getSubaddressList(wallet)
.addSubaddress( .addSubaddress(wallet, accountIndex: monero!.getCurrentAccount(wallet).id, label: label);
wallet,
accountIndex: monero!.getCurrentAccount(wallet).id,
label: label);
await wallet.save(); await wallet.save();
} }
if (wallet.type == WalletType.haven) { if (wallet.type == WalletType.haven) {
await haven await haven!
!.getSubaddressList(wallet) .getSubaddressList(wallet)
.addSubaddress( .addSubaddress(wallet, accountIndex: haven!.getCurrentAccount(wallet).id, label: label);
wallet,
accountIndex: haven!.getCurrentAccount(wallet).id,
label: label);
await wallet.save(); await wallet.save();
} }
} }
@ -109,9 +103,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
} }
if (wallet.type == WalletType.haven) { if (wallet.type == WalletType.haven) {
await haven!.getSubaddressList(wallet).setLabelSubaddress(wallet, await haven!.getSubaddressList(wallet).setLabelSubaddress(wallet,
accountIndex: haven!.getCurrentAccount(wallet).id, accountIndex: haven!.getCurrentAccount(wallet).id, addressIndex: index, label: label);
addressIndex: index,
label: label);
await wallet.save(); await wallet.save();
} }
} }

View file

@ -120,9 +120,7 @@ class BitcoinCashURI extends PaymentURI {
return base; return base;
} }
} }
class NanoURI extends PaymentURI { class NanoURI extends PaymentURI {
NanoURI({required String amount, required String address}) NanoURI({required String amount, required String address})
@ -147,8 +145,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
}) : _baseItems = <ListItem>[], }) : _baseItems = <ListItem>[],
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type), selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern), _cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
hasAccounts = hasAccounts = appStore.wallet!.type == WalletType.bitcoin ||
appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven, appStore.wallet!.type == WalletType.monero ||
appStore.wallet!.type == WalletType.haven,
amount = '', amount = '',
super(appStore: appStore) { super(appStore: appStore) {
_init(); _init();
@ -159,7 +158,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
_init(); _init();
selectedCurrency = walletTypeToCryptoCurrency(wallet.type); selectedCurrency = walletTypeToCryptoCurrency(wallet.type);
hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven; hasAccounts = wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.monero ||
wallet.type == WalletType.haven;
} }
static const String _cryptoNumberPattern = '0.00000000'; static const String _cryptoNumberPattern = '0.00000000';
@ -257,13 +258,19 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
} }
if (wallet.type == WalletType.bitcoin) { if (wallet.type == WalletType.bitcoin) {
final primaryAddress = bitcoin!.getAddress(wallet); final receiveAddress = bitcoin!.getReceiveAddress(wallet);
final bitcoinAddresses = bitcoin!.getAddresses(wallet).map((addr) { addressList.add(
final isPrimary = addr == primaryAddress; WalletAddressListItem(isPrimary: true, name: 'Primary address', address: receiveAddress));
return WalletAddressListItem(isPrimary: isPrimary, name: null, address: addr); final silentAddress = bitcoin!.getSilentAddress(wallet).toString();
addressList.add(
WalletAddressListItem(isPrimary: false, name: silentAddress, address: silentAddress));
final silentAddresses = bitcoin!.getSilentAddresses(wallet);
silentAddresses.forEach((addr) {
addressList.add(WalletAddressListItem(
isPrimary: false, name: addr.silentAddressLabel, address: addr.address));
}); });
addressList.addAll(bitcoinAddresses);
} }
if (wallet.type == WalletType.ethereum) { if (wallet.type == WalletType.ethereum) {
@ -291,12 +298,18 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
return ''; return '';
} }
@computed
bool get hasSilentAddresses => wallet.type == WalletType.bitcoin;
@computed @computed
bool get hasAddressList => bool get hasAddressList =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.monero || wallet.type == WalletType.monero ||
wallet.type == WalletType.haven;/* || wallet.type ==
WalletType
.haven; /* ||
wallet.type == WalletType.nano || wallet.type == WalletType.nano ||
wallet.type == WalletType.banano;*/// TODO: nano accounts are disabled for now wallet.type == WalletType.banano;*/ // TODO: nano accounts are disabled for now
@computed @computed
bool get showElectrumAddressDisclaimer => bool get showElectrumAddressDisclaimer =>
@ -316,9 +329,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
_baseItems = []; _baseItems = [];
if (wallet.type == WalletType.monero || if (wallet.type == WalletType.monero ||
wallet.type == WalletType.haven /*|| wallet.type ==
WalletType
.haven /*||
wallet.type == WalletType.nano || wallet.type == WalletType.nano ||
wallet.type == WalletType.banano*/) { wallet.type == WalletType.banano*/
) {
_baseItems.add(WalletAccountListHeader()); _baseItems.add(WalletAccountListHeader());
} }

View file

@ -49,7 +49,7 @@ abstract class WalletCreationVMBase with Store {
bool typeExists(WalletType type) => walletCreationService.typeExists(type); bool typeExists(WalletType type) => walletCreationService.typeExists(type);
Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async { Future<void> create({dynamic options, RestoredWallet? restoreWallet, bool? isTestnet}) async {
final type = restoreWallet?.type ?? this.type; final type = restoreWallet?.type ?? this.type;
try { try {
state = IsExecutingState(); state = IsExecutingState();

View file

@ -26,6 +26,12 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
: selectedMnemonicLanguage = '', : selectedMnemonicLanguage = '',
super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false); super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false);
@observable
bool _useTestnet = false;
@computed
bool get useTestnet => _useTestnet;
@observable @observable
String selectedMnemonicLanguage; String selectedMnemonicLanguage;
@ -58,6 +64,10 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
@override @override
Future<WalletBase> process(WalletCredentials credentials) async { Future<WalletBase> process(WalletCredentials credentials) async {
walletCreationService.changeWalletType(type: type); walletCreationService.changeWalletType(type: type);
return walletCreationService.create(credentials); return walletCreationService.create(credentials, isTestnet: useTestnet);
} }
// TODO: set electrum's node as default for testnet
@action
void toggleUseTestnet() => _useTestnet = !_useTestnet;
} }

View file

@ -8,7 +8,6 @@
#include <cw_monero/cw_monero_plugin.h> #include <cw_monero/cw_monero_plugin.h>
#include <devicelocale/devicelocale_plugin.h> #include <devicelocale/devicelocale_plugin.h>
#include <platform_device_id_linux/platform_device_id_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
@ -18,9 +17,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) devicelocale_registrar = g_autoptr(FlPluginRegistrar) devicelocale_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DevicelocalePlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "DevicelocalePlugin");
devicelocale_plugin_register_with_registrar(devicelocale_registrar); devicelocale_plugin_register_with_registrar(devicelocale_registrar);
g_autoptr(FlPluginRegistrar) platform_device_id_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PlatformDeviceIdLinuxPlugin");
platform_device_id_linux_plugin_register_with_registrar(platform_device_id_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View file

@ -5,7 +5,6 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
cw_monero cw_monero
devicelocale devicelocale
platform_device_id_linux
url_launcher_linux url_launcher_linux
) )

View file

@ -5,30 +5,24 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import connectivity_plus_macos
import cw_monero import cw_monero
import device_info_plus import device_info_plus
import devicelocale import devicelocale
import in_app_review import in_app_review
import package_info_plus import package_info_plus
import path_provider_foundation import path_provider_foundation
import platform_device_id
import platform_device_id_macos
import share_plus_macos import share_plus_macos
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
import wakelock_plus import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin")) CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

View file

@ -0,0 +1,12 @@
import FlutterMacOS
import Cocoa
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View file

@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
cd cw_core; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_core; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_monero; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_monero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_bitcoin; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_bitcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_haven; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_haven; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_ethereum; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_ethereum; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_nano; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_nano; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
cd cw_bitcoin_cash; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd .. cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
flutter packages pub run build_runner build --delete-conflicting-outputs dart run build_runner build --delete-conflicting-outputs

View file

@ -48,7 +48,7 @@ dependencies:
basic_utils: ^5.6.1 basic_utils: ^5.6.1
get_it: ^7.2.0 get_it: ^7.2.0
# connectivity: ^3.0.3 # connectivity: ^3.0.3
connectivity_plus: ^2.3.5 # connectivity_plus: ^2.3.5
keyboard_actions: ^4.0.1 keyboard_actions: ^4.0.1
another_flushbar: ^1.12.29 another_flushbar: ^1.12.29
archive: ^3.3.0 archive: ^3.3.0
@ -85,9 +85,7 @@ dependencies:
url: https://github.com/cake-tech/ens_dart.git url: https://github.com/cake-tech/ens_dart.git
ref: main ref: main
bitcoin_flutter: bitcoin_flutter:
git: path: /home/rafael/Storage/Repositories/bitcoin_flutter
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake-update-v3
fluttertoast: 8.1.4 fluttertoast: 8.1.4
dev_dependencies: dev_dependencies:

View file

@ -435,7 +435,7 @@
"search_language": "ابحث عن لغة", "search_language": "ابحث عن لغة",
"search_currency": "ابحث عن عملة", "search_currency": "ابحث عن عملة",
"new_template": "قالب جديد", "new_template": "قالب جديد",
"electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", "electrum_address_disclaimer": "نقوم بإنشاء عناوين أساسية جديدة في كل مرة تستخدم فيها واحدة ، لكن العناوين السابقة تستمر في العمل",
"wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.", "wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.",
"market_place": "منصة التجارة", "market_place": "منصة التجارة",
"cake_pay_title": "بطاقات هدايا Cake Pay", "cake_pay_title": "بطاقات هدايا Cake Pay",
@ -732,5 +732,8 @@
"domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ",
"require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ",
"camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ",
"switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ",
"use_testnet": "استخدم testnet",
"address_and_silent_addresses": "العنوان والعناوين الصامتة",
"silent_addresses": "عناوين صامتة"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Търсене на език", "search_language": "Търсене на език",
"search_currency": "Търсене на валута", "search_currency": "Търсене на валута",
"new_template": "Нов шаблон", "new_template": "Нов шаблон",
"electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", "electrum_address_disclaimer": "Ние генерираме нови първични адреси всеки път, когато използвате един, но предишните адреси продължават да работят",
"wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.", "wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.",
"market_place": "Магазин", "market_place": "Магазин",
"cake_pay_title": "Cake Pay Gift Карти", "cake_pay_title": "Cake Pay Gift Карти",
@ -728,5 +728,8 @@
"domain_looks_up": "Търсене на домейни", "domain_looks_up": "Търсене на домейни",
"require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли",
"camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.",
"switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново",
"use_testnet": "Използвайте TestNet",
"address_and_silent_addresses": "Адрес и мълчаливи адреси",
"silent_addresses": "Безшумни адреси"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Hledat jazyk", "search_language": "Hledat jazyk",
"search_currency": "Hledat měnu", "search_currency": "Hledat měnu",
"new_template": "Nová šablona", "new_template": "Nová šablona",
"electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", "electrum_address_disclaimer": "Pokaždé, když jednu použijete, generujeme nové primární adresy, ale předchozí adresy nadále fungují",
"wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.", "wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.",
"market_place": "Obchod", "market_place": "Obchod",
"cake_pay_title": "Cake Pay dárkové karty", "cake_pay_title": "Cake Pay dárkové karty",
@ -728,5 +728,8 @@
"domain_looks_up": "Vyhledávání domén", "domain_looks_up": "Vyhledávání domén",
"require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek",
"camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.",
"switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu",
"use_testnet": "Použijte testNet",
"address_and_silent_addresses": "Adresa a tiché adresy",
"silent_addresses": "Tiché adresy"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Sprache suchen", "search_language": "Sprache suchen",
"search_currency": "Währung suchen", "search_currency": "Währung suchen",
"new_template": "neue Vorlage", "new_template": "neue Vorlage",
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", "electrum_address_disclaimer": "Wir generieren jedes Mal neue primäre Adressen, wenn Sie eine verwenden, aber frühere Adressen funktionieren weiterhin",
"wallet_name_exists": "Wallet mit diesem Namen existiert bereits", "wallet_name_exists": "Wallet mit diesem Namen existiert bereits",
"market_place": "Marktplatz", "market_place": "Marktplatz",
"cake_pay_title": "Cake Pay-Geschenkkarten", "cake_pay_title": "Cake Pay-Geschenkkarten",
@ -736,5 +736,11 @@
"domain_looks_up": "Domain-Suchen", "domain_looks_up": "Domain-Suchen",
"require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets",
"camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.",
"switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut",
"seed_key": "Samenschlüssel",
"enter_seed_phrase": "Geben Sie Ihre Samenphrase ein",
"add_contact": "Kontakt hinzufügen",
"use_testnet": "TESTNET verwenden",
"address_and_silent_addresses": "Adresse und stille Adressen",
"silent_addresses": "Stille Adressen"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Search language", "search_language": "Search language",
"search_currency": "Search currency", "search_currency": "Search currency",
"new_template": "New Template", "new_template": "New Template",
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", "electrum_address_disclaimer": "We generate new primary addresses each time you use one, but previous addresses continue to work",
"wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.", "wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.",
"market_place": "Marketplace", "market_place": "Marketplace",
"cake_pay_title": "Cake Pay Gift Cards", "cake_pay_title": "Cake Pay Gift Cards",
@ -737,5 +737,8 @@
"domain_looks_up": "Domain lookups", "domain_looks_up": "Domain lookups",
"require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets",
"camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.",
"switchToETHWallet": "Please switch to an Ethereum wallet and try again" "switchToETHWallet": "Please switch to an Ethereum wallet and try again",
"use_testnet": "Use testnet",
"address_and_silent_addresses": "Address and Silent Addresses",
"silent_addresses": "Silent Addresses"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Idioma de búsqueda", "search_language": "Idioma de búsqueda",
"search_currency": "Moneda de búsqueda", "search_currency": "Moneda de búsqueda",
"new_template": "Nueva plantilla", "new_template": "Nueva plantilla",
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", "electrum_address_disclaimer": "Generamos nuevas direcciones primarias cada vez que usa una, pero las direcciones anteriores continúan funcionando",
"wallet_name_exists": "Wallet con ese nombre ya ha existido", "wallet_name_exists": "Wallet con ese nombre ya ha existido",
"market_place": "Mercado", "market_place": "Mercado",
"cake_pay_title": "Tarjetas de regalo Cake Pay", "cake_pay_title": "Tarjetas de regalo Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Búsquedas de dominio", "domain_looks_up": "Búsquedas de dominio",
"require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas",
"camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.",
"switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.",
"use_testnet": "Use TestNet",
"address_and_silent_addresses": "Dirección y direcciones silenciosas",
"silent_addresses": "Direcciones silenciosas"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Rechercher une langue", "search_language": "Rechercher une langue",
"search_currency": "Rechercher une devise", "search_currency": "Rechercher une devise",
"new_template": "Nouveau Modèle", "new_template": "Nouveau Modèle",
"electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", "electrum_address_disclaimer": "Nous générons de nouvelles adresses primaires chaque fois que vous en utilisez une, mais les adresses précédentes continuent de fonctionner",
"wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà", "wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà",
"market_place": "Place de marché", "market_place": "Place de marché",
"cake_pay_title": "Cartes cadeaux Cake Pay", "cake_pay_title": "Cartes cadeaux Cake Pay",
@ -702,7 +702,7 @@
"select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.",
"onramper_option_description": "Achetez rapidement des cryptomonnaies avec de nombreuses méthodes de paiement. Disponible dans la plupart des pays. Les spreads et les frais peuvent varier.", "onramper_option_description": "Achetez rapidement des cryptomonnaies avec de nombreuses méthodes de paiement. Disponible dans la plupart des pays. Les spreads et les frais peuvent varier.",
"default_buy_provider": "Fournisseur d'achat par défaut", "default_buy_provider": "Fournisseur d'achat par défaut",
"ask_each_time": "Demander à chaque fois", "ask_each_time": "Demandez à chaque fois",
"buy_provider_unavailable": "Fournisseur actuellement indisponible.", "buy_provider_unavailable": "Fournisseur actuellement indisponible.",
"signTransaction": "Signer une transaction", "signTransaction": "Signer une transaction",
"errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification",
@ -736,5 +736,8 @@
"domain_looks_up": "Recherches de domaine", "domain_looks_up": "Recherches de domaine",
"require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes",
"camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.",
"switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer",
"use_testnet": "Utiliser TestNet",
"address_and_silent_addresses": "Adresse et adresses silencieuses",
"silent_addresses": "Adresses silencieuses"
} }

View file

@ -436,7 +436,7 @@
"search_language": "Bincika harshe", "search_language": "Bincika harshe",
"search_currency": "Neman kudin waje", "search_currency": "Neman kudin waje",
"new_template": "Sabon Samfura", "new_template": "Sabon Samfura",
"electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", "electrum_address_disclaimer": "Muna samar da sabbin adiresoshin farko a duk lokacin da kake amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki",
"wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.", "wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.",
"market_place": "Kasuwa", "market_place": "Kasuwa",
"cake_pay_title": "Cake Pay Gift Cards", "cake_pay_title": "Cake Pay Gift Cards",
@ -714,5 +714,8 @@
"domain_looks_up": "Binciken yanki", "domain_looks_up": "Binciken yanki",
"require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje",
"camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.",
"switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa",
"use_testnet": "Amfani da gwaji",
"address_and_silent_addresses": "Adireshin da adreshin shiru",
"silent_addresses": "Adireshin Shiru"
} }

View file

@ -435,7 +435,7 @@
"search_language": "भाषा खोजें", "search_language": "भाषा खोजें",
"search_currency": "मुद्रा खोजें", "search_currency": "मुद्रा खोजें",
"new_template": "नया टेम्पलेट", "new_template": "नया टेम्पलेट",
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", "electrum_address_disclaimer": "हम हर बार जब आप एक का उपयोग करते हैं, तो हम नए प्राथमिक पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं",
"wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है", "wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है",
"market_place": "मार्केटप्लेस", "market_place": "मार्केटप्लेस",
"cake_pay_title": "केक पे गिफ्ट कार्ड्स", "cake_pay_title": "केक पे गिफ्ट कार्ड्स",
@ -736,5 +736,8 @@
"domain_looks_up": "डोमेन लुकअप", "domain_looks_up": "डोमेन लुकअप",
"require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है",
"camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।",
"switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें",
"use_testnet": "टेस्टनेट का उपयोग करें",
"address_and_silent_addresses": "पता और मूक पते",
"silent_addresses": "मूक पते"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Jezik pretraživanja", "search_language": "Jezik pretraživanja",
"search_currency": "Traži valutu", "search_currency": "Traži valutu",
"new_template": "novi predložak", "new_template": "novi predložak",
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", "electrum_address_disclaimer": "Generiramo nove primarne adrese svaki put kada ih koristite, ali prethodne adrese i dalje rade",
"wallet_name_exists": "Novčanik s tim nazivom već postoji", "wallet_name_exists": "Novčanik s tim nazivom već postoji",
"market_place": "Tržnica", "market_place": "Tržnica",
"cake_pay_title": "Cake Pay poklon kartice", "cake_pay_title": "Cake Pay poklon kartice",
@ -734,5 +734,8 @@
"domain_looks_up": "Pretraga domena", "domain_looks_up": "Pretraga domena",
"require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike",
"camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.",
"switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno",
"use_testnet": "Koristite TestNet",
"address_and_silent_addresses": "Adresa i tihe adrese",
"silent_addresses": "Tihe adrese"
} }

View file

@ -436,7 +436,7 @@
"search_language": "Cari bahasa", "search_language": "Cari bahasa",
"search_currency": "Cari mata uang", "search_currency": "Cari mata uang",
"new_template": "Template Baru", "new_template": "Template Baru",
"electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", "electrum_address_disclaimer": "Kami menghasilkan alamat utama baru setiap kali Anda menggunakannya, tetapi alamat sebelumnya terus berfungsi",
"wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.", "wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.",
"market_place": "Pasar", "market_place": "Pasar",
"cake_pay_title": "Kartu Hadiah Cake Pay", "cake_pay_title": "Kartu Hadiah Cake Pay",
@ -724,5 +724,8 @@
"domain_looks_up": "Pencarian domain", "domain_looks_up": "Pencarian domain",
"require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal",
"camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.",
"switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi",
"use_testnet": "Gunakan TestNet",
"address_and_silent_addresses": "Alamat dan alamat diam",
"silent_addresses": "Alamat diam"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Cerca lingua", "search_language": "Cerca lingua",
"search_currency": "Cerca valuta", "search_currency": "Cerca valuta",
"new_template": "Nuovo modello", "new_template": "Nuovo modello",
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", "electrum_address_disclaimer": "Generiamo nuovi indirizzi primari ogni volta che ne usi uno, ma gli indirizzi precedenti continuano a funzionare",
"wallet_name_exists": "Il portafoglio con quel nome è già esistito", "wallet_name_exists": "Il portafoglio con quel nome è già esistito",
"market_place": "Mercato", "market_place": "Mercato",
"cake_pay_title": "Carte regalo Cake Pay", "cake_pay_title": "Carte regalo Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Ricerche di domini", "domain_looks_up": "Ricerche di domini",
"require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni",
"camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.",
"switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova",
"use_testnet": "Usa TestNet",
"address_and_silent_addresses": "Indirizzo e indirizzi silenziosi",
"silent_addresses": "Indirizzi silenziosi"
} }

View file

@ -435,7 +435,7 @@
"search_language": "検索言語", "search_language": "検索言語",
"search_currency": "検索通貨", "search_currency": "検索通貨",
"new_template": "新しいテンプレート", "new_template": "新しいテンプレート",
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", "electrum_address_disclaimer": "使用するたびに新しいプライマリアドレスを生成しますが、以前のアドレスは機能し続けます",
"wallet_name_exists": "その名前のウォレットはすでに存在しています", "wallet_name_exists": "その名前のウォレットはすでに存在しています",
"market_place": "Marketplace", "market_place": "Marketplace",
"cake_pay_title": "ケーキペイギフトカード", "cake_pay_title": "ケーキペイギフトカード",
@ -736,5 +736,8 @@
"domain_looks_up": "ドメイン検索", "domain_looks_up": "ドメイン検索",
"require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要",
"camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。",
"switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください",
"use_testnet": "TestNetを使用します",
"address_and_silent_addresses": "住所とサイレントアドレス",
"silent_addresses": "サイレントアドレス"
} }

View file

@ -435,7 +435,7 @@
"search_language": "검색 언어", "search_language": "검색 언어",
"search_currency": "통화 검색", "search_currency": "통화 검색",
"new_template": "새 템플릿", "new_template": "새 템플릿",
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", "electrum_address_disclaimer": "우리는 당신이 하나를 사용할 때마다 새로운 기본 주소를 생성하지만 이전 주소는 계속 작동합니다.",
"wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.", "wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.",
"market_place": "마켓플레이스", "market_place": "마켓플레이스",
"cake_pay_title": "케이크 페이 기프트 카드", "cake_pay_title": "케이크 페이 기프트 카드",
@ -734,5 +734,8 @@
"domain_looks_up": "도메인 조회", "domain_looks_up": "도메인 조회",
"require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요",
"camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.",
"switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.",
"use_testnet": "TestNet을 사용하십시오",
"address_and_silent_addresses": "주소 및 조용한 주소",
"silent_addresses": "조용한 주소"
} }

View file

@ -435,7 +435,7 @@
"search_language": "ဘာသာစကားရှာပါ။", "search_language": "ဘာသာစကားရှာပါ။",
"search_currency": "ငွေကြေးကိုရှာပါ။", "search_currency": "ငွေကြေးကိုရှာပါ။",
"new_template": "ပုံစံအသစ်", "new_template": "ပုံစံအသစ်",
"electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", "electrum_address_disclaimer": "သင်အသုံးပြုသောအခါတိုင်းကျွန်ုပ်တို့သည်အဓိကလိပ်စာအသစ်များကိုထုတ်လုပ်သည်, သို့သော်ယခင်လိပ်စာများဆက်လက်အလုပ်လုပ်သည်",
"wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။", "wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။",
"market_place": "ဈေး", "market_place": "ဈေး",
"cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ", "cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ",
@ -734,5 +734,8 @@
"domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ",
"require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။",
"camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။",
"switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။",
"use_testnet": "testnet ကိုသုံးပါ",
"address_and_silent_addresses": "လိပ်စာနှင့်အသံတိတ်လိပ်စာများ",
"silent_addresses": "အသံတိတ်လိပ်စာများ"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Zoektaal", "search_language": "Zoektaal",
"search_currency": "Zoek valuta", "search_currency": "Zoek valuta",
"new_template": "Nieuwe sjabloon", "new_template": "Nieuwe sjabloon",
"electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", "electrum_address_disclaimer": "We genereren nieuwe primaire adressen telkens wanneer u er een gebruikt, maar eerdere adressen blijven werken",
"wallet_name_exists": "Portemonnee met die naam bestaat al", "wallet_name_exists": "Portemonnee met die naam bestaat al",
"market_place": "Marktplaats", "market_place": "Marktplaats",
"cake_pay_title": "Cake Pay-cadeaubonnen", "cake_pay_title": "Cake Pay-cadeaubonnen",
@ -736,5 +736,8 @@
"domain_looks_up": "Domein opzoeken", "domain_looks_up": "Domein opzoeken",
"require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees",
"camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.",
"switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw",
"use_testnet": "Gebruik testnet",
"address_and_silent_addresses": "Adres en stille adressen",
"silent_addresses": "Stille adressen"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Wyszukaj język", "search_language": "Wyszukaj język",
"search_currency": "Wyszukaj walutę", "search_currency": "Wyszukaj walutę",
"new_template": "Nowy szablon", "new_template": "Nowy szablon",
"electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", "electrum_address_disclaimer": "Generujemy nowe podstawowe adresy za każdym razem, gdy je używasz, ale poprzednie adresy nadal działają",
"wallet_name_exists": "Portfel o tej nazwie już istnieje", "wallet_name_exists": "Portfel o tej nazwie już istnieje",
"market_place": "Rynek", "market_place": "Rynek",
"cake_pay_title": "Karty podarunkowe Cake Pay", "cake_pay_title": "Karty podarunkowe Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Wyszukiwanie domen", "domain_looks_up": "Wyszukiwanie domen",
"require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne",
"camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.",
"switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie",
"use_testnet": "Użyj testne",
"address_and_silent_addresses": "Adres i ciche adresy",
"silent_addresses": "Ciche adresy"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Idioma de pesquisa", "search_language": "Idioma de pesquisa",
"search_currency": "Pesquisar moeda", "search_currency": "Pesquisar moeda",
"new_template": "Novo modelo", "new_template": "Novo modelo",
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", "electrum_address_disclaimer": "Geramos novos endereços primários cada vez que você usa um, mas os endereços anteriores continuam funcionando",
"wallet_name_exists": "A carteira com esse nome já existe", "wallet_name_exists": "A carteira com esse nome já existe",
"market_place": "Mercado", "market_place": "Mercado",
"cake_pay_title": "Cartões de presente de CakePay", "cake_pay_title": "Cartões de presente de CakePay",
@ -735,5 +735,8 @@
"domain_looks_up": "Pesquisas de domínio", "domain_looks_up": "Pesquisas de domínio",
"require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas",
"camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.",
"switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente",
"use_testnet": "Use testNet",
"address_and_silent_addresses": "Endereço e endereços silenciosos",
"silent_addresses": "Endereços silenciosos"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Язык поиска", "search_language": "Язык поиска",
"search_currency": "Валюта поиска", "search_currency": "Валюта поиска",
"new_template": "Новый шаблон", "new_template": "Новый шаблон",
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", "electrum_address_disclaimer": "Мы генерируем новые основные адреса каждый раз, когда вы используете его, но предыдущие адреса продолжают работать",
"wallet_name_exists": "Кошелек с таким именем уже существует", "wallet_name_exists": "Кошелек с таким именем уже существует",
"market_place": "Торговая площадка", "market_place": "Торговая площадка",
"cake_pay_title": "Подарочные карты Cake Pay", "cake_pay_title": "Подарочные карты Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Поиск доменов", "domain_looks_up": "Поиск доменов",
"require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки",
"camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.",
"switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.",
"use_testnet": "Используйте Testnet",
"address_and_silent_addresses": "Адрес и молчаливые адреса",
"silent_addresses": "Молчаливые адреса"
} }

View file

@ -435,7 +435,7 @@
"search_language": "ค้นหาภาษา", "search_language": "ค้นหาภาษา",
"search_currency": "ค้นหาสกุลเงิน", "search_currency": "ค้นหาสกุลเงิน",
"new_template": "แม่แบบใหม่", "new_template": "แม่แบบใหม่",
"electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", "electrum_address_disclaimer": "เราสร้างที่อยู่หลักใหม่ทุกครั้งที่คุณใช้ แต่ที่อยู่ก่อนหน้านี้ยังคงทำงานต่อไป",
"wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน", "wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน",
"market_place": "ตลาดพื้นที่", "market_place": "ตลาดพื้นที่",
"cake_pay_title": "บัตรของขวัญ Cake Pay", "cake_pay_title": "บัตรของขวัญ Cake Pay",
@ -734,5 +734,8 @@
"domain_looks_up": "การค้นหาโดเมน", "domain_looks_up": "การค้นหาโดเมน",
"require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก",
"camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป",
"switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง",
"use_testnet": "ใช้ testnet",
"address_and_silent_addresses": "ที่อยู่และที่อยู่เงียบ",
"silent_addresses": "ที่อยู่เงียบ"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Maghanap ng wika", "search_language": "Maghanap ng wika",
"search_currency": "Maghanap ng pera", "search_currency": "Maghanap ng pera",
"new_template": "Bagong template", "new_template": "Bagong template",
"electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", "electrum_address_disclaimer": "Bumubuo kami ng mga bagong pangunahing address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana",
"wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.", "wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.",
"market_place": "Marketplace", "market_place": "Marketplace",
"cake_pay_title": "Cake pay card card", "cake_pay_title": "Cake pay card card",
@ -731,5 +731,8 @@
"domain_looks_up": "Mga paghahanap ng domain", "domain_looks_up": "Mga paghahanap ng domain",
"require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet",
"camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.",
"switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli",
"use_testnet": "Gumamit ng testnet",
"address_and_silent_addresses": "Address at tahimik na mga address",
"silent_addresses": "Tahimik na mga address"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Dil arat", "search_language": "Dil arat",
"search_currency": "Para birimi ara", "search_currency": "Para birimi ara",
"new_template": "Yeni Şablon", "new_template": "Yeni Şablon",
"electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", "electrum_address_disclaimer": "Her kullandığınızda yeni birincil adresler oluşturuyoruz, ancak önceki adresler çalışmaya devam ediyor",
"wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.", "wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.",
"market_place": "Pazar Alanı", "market_place": "Pazar Alanı",
"cake_pay_title": "Cake Pay Hediye Kartları", "cake_pay_title": "Cake Pay Hediye Kartları",
@ -734,5 +734,8 @@
"domain_looks_up": "Etki alanı aramaları", "domain_looks_up": "Etki alanı aramaları",
"require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın",
"camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.",
"switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin",
"use_testnet": "TestNet kullanın",
"address_and_silent_addresses": "Adres ve sessiz adresler",
"silent_addresses": "Sessiz adresler"
} }

View file

@ -435,7 +435,7 @@
"search_language": "Мова пошуку", "search_language": "Мова пошуку",
"search_currency": "Шукати валюту", "search_currency": "Шукати валюту",
"new_template": "Новий шаблон", "new_template": "Новий шаблон",
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", "electrum_address_disclaimer": "Ми генеруємо нові первинні адреси кожного разу, коли ви використовуєте його, але попередні адреси продовжують працювати",
"wallet_name_exists": "Гаманець з такою назвою вже існує", "wallet_name_exists": "Гаманець з такою назвою вже існує",
"market_place": "Ринок", "market_place": "Ринок",
"cake_pay_title": "Подарункові картки Cake Pay", "cake_pay_title": "Подарункові картки Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Пошук доменів", "domain_looks_up": "Пошук доменів",
"require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці",
"camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.",
"switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу",
"use_testnet": "Використовуйте тестову мережу",
"address_and_silent_addresses": "Адреса та мовчазні адреси",
"silent_addresses": "Мовчазні адреси"
} }

View file

@ -436,7 +436,7 @@
"search_language": "زبان تلاش کریں۔", "search_language": "زبان تلاش کریں۔",
"search_currency": "کرنسی تلاش کریں۔", "search_currency": "کرنسی تلاش کریں۔",
"new_template": "نیا سانچہ", "new_template": "نیا سانچہ",
"electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", "electrum_address_disclaimer": "ہم ہر بار جب آپ کسی کو استعمال کرتے ہیں تو نئے پرائمری پتے تیار کرتے ہیں ، لیکن پچھلے پتے کام کرتے رہتے ہیں",
"wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔", "wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔",
"market_place": "بازار", "market_place": "بازار",
"cake_pay_title": "Cake پے گفٹ کارڈز", "cake_pay_title": "Cake پے گفٹ کارڈز",
@ -728,5 +728,8 @@
"domain_looks_up": "ڈومین تلاش کرنا", "domain_looks_up": "ڈومین تلاش کرنا",
"require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ",
"camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ",
"switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ",
"use_testnet": "ٹیسٹ نیٹ استعمال کریں",
"address_and_silent_addresses": "پتہ اور خاموش پتے",
"silent_addresses": "خاموش پتے"
} }

View file

@ -433,7 +433,7 @@
"search_language": "Wá èdè", "search_language": "Wá èdè",
"search_currency": "Wá irú owó", "search_currency": "Wá irú owó",
"new_template": "Àwòṣe títun", "new_template": "Àwòṣe títun",
"electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", "electrum_address_disclaimer": "A ṣe ina awọn adirẹsi akọkọ akọkọ ni igba kọọkan ti o lo ọkan, ṣugbọn awọn adirẹsi iṣaaju tẹsiwaju lati ṣiṣẹ",
"wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.", "wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.",
"market_place": "Ọjà", "market_place": "Ọjà",
"cake_pay_title": "Àwọn káàdì ìrajà t'á lò nínú ìtajà kan ti Cake Pay", "cake_pay_title": "Àwọn káàdì ìrajà t'á lò nínú ìtajà kan ti Cake Pay",
@ -730,5 +730,8 @@
"domain_looks_up": "Awọn wiwa agbegbe", "domain_looks_up": "Awọn wiwa agbegbe",
"require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita",
"camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.",
"switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi",
"use_testnet": "Lo tele",
"address_and_silent_addresses": "Adirẹsi ati awọn adirẹsi ipalọlọ",
"silent_addresses": "Awọn adirẹsi ipalọlọ"
} }

View file

@ -434,7 +434,7 @@
"search_language": "搜索语言", "search_language": "搜索语言",
"search_currency": "搜索货币", "search_currency": "搜索货币",
"new_template": "新模板", "new_template": "新模板",
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", "electrum_address_disclaimer": "每次使用一个时,我们都会生成新的主地址,但是以前的地址继续工作",
"wallet_name_exists": "同名的钱包已经存在", "wallet_name_exists": "同名的钱包已经存在",
"market_place": "市场", "market_place": "市场",
"cake_pay_title": "Cake Pay 礼品卡", "cake_pay_title": "Cake Pay 礼品卡",
@ -735,5 +735,8 @@
"domain_looks_up": "域名查找", "domain_looks_up": "域名查找",
"require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包",
"camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。",
"switchToETHWallet": "请切换到以太坊钱包并重试" "switchToETHWallet": "请切换到以太坊钱包并重试",
"use_testnet": "使用TestNet",
"address_and_silent_addresses": "地址和无声地址",
"silent_addresses": "无声地址"
} }

View file

@ -30,8 +30,12 @@ case $APP_ANDROID_TYPE in
;; ;;
esac esac
rm $APP_LOGO_DEST_PATH if [ ! -z "$APP_LOGO_DEST_PATH" ]; then
rm $ANDROID_ICON_DEST_PATH rm $APP_LOGO_DEST_PATH
fi
if [ ! -z "$ANDROID_ICON_DEST_PATH" ]; then
rm $ANDROID_ICON_DEST_PATH
fi
ln -s $APP_LOGO $APP_LOGO_DEST_PATH ln -s $APP_LOGO $APP_LOGO_DEST_PATH
ln -s $ANDROID_ICON $ANDROID_ICON_DEST_PATH ln -s $ANDROID_ICON $ANDROID_ICON_DEST_PATH
cp -a $ANDROID_ICON_SET/. $ANDROID_ICON_SET_DEST_PATH/ cp -a $ANDROID_ICON_SET/. $ANDROID_ICON_SET_DEST_PATH/

View file

@ -8,6 +8,11 @@ if [ -z "$APP_LINUX_TYPE" ]; then
exit 1 exit 1
fi fi
../android/app_properties.sh
../android/app_icon.sh
../android/manifest.sh
../android/inject_app_details.sh
cd ../.. # go to root cd ../.. # go to root
CONFIG_ARGS="" CONFIG_ARGS=""
@ -18,8 +23,8 @@ esac
cp -rf pubspec_description.yaml pubspec.yaml cp -rf pubspec_description.yaml pubspec.yaml
flutter pub get flutter pub get
flutter pub run tool/generate_pubspec.dart dart run tool/generate_pubspec.dart
flutter pub get flutter pub get
flutter packages pub run tool/configure.dart $CONFIG_ARGS dart run tool/configure.dart $CONFIG_ARGS
sed -i '0,/version: 0.0.0/s//version: '"${APP_LINUX_VERSION}"'+'"${APP_LINUX_BUILD_NUMBER}"'/' pubspec.yaml sed -i '0,/version: 0.0.0/s//version: '"${APP_LINUX_VERSION}"'+'"${APP_LINUX_BUILD_NUMBER}"'/' pubspec.yaml
cd $DIR cd $DIR

View file

@ -1,11 +1,11 @@
#!/bin/sh #!/bin/sh
source ../android/app_env.sh cakewallet
APP_LINUX_NAME="" APP_LINUX_NAME=""
APP_LINUX_VERSION="" APP_LINUX_VERSION=""
APP_LINUX_BUILD_VERSION="" APP_LINUX_BUILD_VERSION=""
CAKEWALLET="cakewallet"
TYPES=($CAKEWALLET) TYPES=($CAKEWALLET)
APP_LINUX_TYPE=$CAKEWALLET APP_LINUX_TYPE=$CAKEWALLET

View file

@ -3,7 +3,8 @@ gcc10Stdenv.mkDerivation {
name="gcc10-stdenv"; name="gcc10-stdenv";
buildInputs = [ buildInputs = [
pkgs.cmake pkgs.cmake
pkgs.pkgconfig pkgs.boost182
pkgs.pkgconf
pkgs.autoconf pkgs.autoconf
pkgs.libtool pkgs.libtool
pkgs.expat pkgs.expat

View file

@ -75,6 +75,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/litecoin_wallet_service.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as btc;
"""; """;
const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinCwPart = "part 'cw_bitcoin.dart';";
const bitcoinContent = """ const bitcoinContent = """
@ -91,12 +92,15 @@ abstract class Bitcoin {
TransactionPriority deserializeBitcoinTransactionPriority(int raw); TransactionPriority deserializeBitcoinTransactionPriority(int raw);
TransactionPriority deserializeLitecoinTransactionPriority(int raw); TransactionPriority deserializeLitecoinTransactionPriority(int raw);
int getFeeRate(Object wallet, TransactionPriority priority); int getFeeRate(Object wallet, TransactionPriority priority);
Future<void> generateNewAddress(Object wallet); Future<void> generateNewAddress(Object wallet, {String? label});
Object createBitcoinTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate}); Object createBitcoinTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate});
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate}); Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate});
List<String> getAddresses(Object wallet); List<String> getAddresses(Object wallet);
String getAddress(Object wallet); String getAddress(Object wallet);
String getReceiveAddress(Object wallet);
btc.SilentPaymentAddress? getSilentAddress(Object wallet);
List<BitcoinAddressRecord> getSilentAddresses(Object wallet);
String formatterBitcoinAmountToString({required int amount}); String formatterBitcoinAmountToString({required int amount});
double formatterBitcoinAmountToDouble({required int amount}); double formatterBitcoinAmountToDouble({required int amount});