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.
version:
revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
channel: stable
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: unknown
project_type: app
@ -13,14 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
- platform: macos
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: android
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: ios
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: linux
create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
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

View file

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

View file

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

View file

@ -23,77 +23,84 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
bitcoin.NetworkType? networkType,
required Uint8List seedBytes,
required EncryptionFileUtils encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0})
int initialChangeAddressIndex = 0,
bitcoin.SilentPaymentReceiver? silentAddress})
: super(
mnemonic: mnemonic,
password: password,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo,
networkType: bitcoin.bitcoin,
networkType: networkType ?? bitcoin.bitcoin,
initialAddresses: initialAddresses,
initialBalance: initialBalance,
seedBytes: seedBytes,
currency: CryptoCurrency.btc,
encryptionFileUtils: encryptionFileUtils) {
walletAddresses = BitcoinWalletAddresses(
walletInfo,
walletAddresses = BitcoinWalletAddresses(walletInfo,
electrumClient: electrumClient,
initialAddresses: initialAddresses,
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd,
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
.derivePath("m/0'/1"),
networkType: networkType);
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"),
networkType: networkType ?? bitcoin.bitcoin,
silentAddress: silentAddress);
}
static Future<BitcoinWallet> create({
required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required EncryptionFileUtils encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0
}) async {
static Future<BitcoinWallet> create(
{required String mnemonic,
required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
bitcoin.NetworkType? networkType,
required EncryptionFileUtils encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumBalance? initialBalance,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0}) async {
return BitcoinWallet(
mnemonic: mnemonic,
password: password,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo,
networkType: networkType,
initialAddresses: initialAddresses,
initialBalance: initialBalance,
encryptionFileUtils: encryptionFileUtils,
seedBytes: await mnemonicToSeedBytes(mnemonic),
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex);
initialChangeAddressIndex: initialChangeAddressIndex,
silentAddress: await bitcoin.SilentPaymentReceiver.fromMnemonic(mnemonic,
hrp: networkType == bitcoin.bitcoin ? 'sp' : 'tsp'));
}
static Future<BitcoinWallet> open({
required String name,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password,
required EncryptionFileUtils encryptionFileUtils,
}) async {
final snp = await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password);
static Future<BitcoinWallet> open(
{required String name,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password,
required EncryptionFileUtils encryptionFileUtils}) async {
final snp =
await ElectrumWallletSnapshot.load(encryptionFileUtils, name, walletInfo.type, password);
return BitcoinWallet(
mnemonic: snp.mnemonic,
password: password,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo,
networkType: snp.networkType,
initialAddresses: snp.addresses,
initialBalance: snp.balance,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
encryptionFileUtils: encryptionFileUtils,
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,
List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0})
int initialChangeAddressIndex = 0,
bitcoin.SilentPaymentReceiver? silentAddress})
: super(walletInfo,
initialAddresses: initialAddresses,
initialRegularAddressIndex: initialRegularAddressIndex,
@ -26,9 +27,11 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
mainHd: mainHd,
sideHd: sideHd,
electrumClient: electrumClient,
networkType: networkType);
networkType: networkType,
silentAddress: silentAddress);
@override
String getAddress({required int index, required bitcoin.HDWallet hd}) =>
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:hive/hive.dart';
import 'package:collection/collection.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
class BitcoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials> {
class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> {
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
final Box<WalletInfo> walletInfoSource;
@ -27,12 +26,13 @@ class BitcoinWalletService extends WalletService<
WalletType getType() => WalletType.bitcoin;
@override
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
final wallet = await BitcoinWalletBase.create(
mnemonic: await generateMnemonic(),
password: credentials.password!,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource,
networkType: isTestnet == true ? bitcoin.testnet : bitcoin.bitcoin,
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
await wallet.save();
await wallet.init();
@ -45,8 +45,8 @@ class BitcoinWalletService extends WalletService<
@override
Future<BitcoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await BitcoinWalletBase.open(
password: password,
name: name,
@ -59,17 +59,16 @@ class BitcoinWalletService extends WalletService<
@override
Future<void> remove(String wallet) async {
File(await pathForWalletDir(name: wallet, type: getType()))
.delete(recursive: true);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
await walletInfoSource.delete(walletInfo.key);
}
@override
Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWalletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await BitcoinWalletBase.open(
password: password,
name: currentName,
@ -87,13 +86,11 @@ class BitcoinWalletService extends WalletService<
}
@override
Future<BitcoinWallet> restoreFromKeys(
BitcoinRestoreWalletFromWIFCredentials credentials) async =>
Future<BitcoinWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async =>
throw UnimplementedError();
@override
Future<BitcoinWallet> restoreFromSeed(
BitcoinRestoreWalletFromSeedCredentials credentials) async {
Future<BitcoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async {
if (!validateMnemonic(credentials.mnemonic)) {
throw BitcoinMnemonicIsIncorrectException();
}

View file

@ -8,6 +8,7 @@ import 'package:cw_bitcoin/script_hash.dart';
import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart';
import 'package:collection/collection.dart';
import 'package:http/http.dart' as http;
String jsonrpcparams(List<Object> params) {
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';
class SocketTask {
SocketTask({
required this.isSubscription,
this.completer,
this.subject});
SocketTask({required this.isSubscription, this.completer, this.subject});
final Completer<dynamic>? completer;
final BehaviorSubject<dynamic>? subject;
@ -51,8 +49,7 @@ class ElectrumClient {
Timer? _aliveTimer;
String unterminatedString;
Future<void> connectToUri(Uri uri) async =>
await connect(host: uri.host, port: uri.port);
Future<void> connectToUri(Uri uri) async => await connect(host: uri.host, port: uri.port);
Future<void> connect({required String host, required int port}) async {
try {
@ -104,21 +101,20 @@ class ElectrumClient {
}
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
final response = json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} 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;
}
unterminatedString += message;
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
final response = json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
// unterminatedString = null;
unterminatedString = '';
@ -142,8 +138,7 @@ class ElectrumClient {
}
}
Future<List<String>> version() =>
call(method: 'server.version').then((dynamic result) {
Future<List<String>> version() => call(method: 'server.version').then((dynamic result) {
if (result is List) {
return result.map((dynamic val) => val.toString()).toList();
}
@ -180,9 +175,8 @@ class ElectrumClient {
Future<List<Map<String, dynamic>>> getListUnspentWithAddress(
String address, NetworkType networkType) =>
call(
method: 'blockchain.scripthash.listunspent',
params: [scriptHash(address, networkType: networkType)])
.then((dynamic result) {
method: 'blockchain.scripthash.listunspent',
params: [scriptHash(address, networkType: networkType)]).then((dynamic result) {
if (result is List) {
return result.map((dynamic val) {
if (val is Map<String, dynamic>) {
@ -229,19 +223,25 @@ class ElectrumClient {
return [];
});
Future<Map<String, dynamic>> getTransactionRaw(
{required String hash}) async =>
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000)
Future<dynamic> getTransactionRaw(
{required String hash, required NetworkType networkType}) async =>
callWithTimeout(
method: 'blockchain.transaction.get',
params: networkType == bitcoin ? [hash, true] : [hash],
timeout: 10000)
.then((dynamic result) {
if (result is Map<String, dynamic>) {
return result;
}
if (networkType == testnet && result is String) {
return result;
}
return <String, dynamic>{};
});
Future<String> getTransactionHex(
{required String hash}) async =>
Future<String> getTransactionHex({required String hash}) async =>
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000)
.then((dynamic result) {
if (result is String) {
@ -251,30 +251,37 @@ class ElectrumClient {
return '';
});
Future<String> broadcastTransaction(
{required String transactionRaw}) async =>
call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) {
if (result is String) {
return result;
}
Future<String> broadcastTransaction({required String transactionRaw}) async {
return http
.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 '';
});
return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw])
.then((dynamic result) {
if (result is String) {
return result;
}
Future<Map<String, dynamic>> getMerkle(
{required String hash, required int height}) async =>
await call(
method: 'blockchain.transaction.get_merkle',
params: [hash, height]) as Map<String, dynamic>;
return '';
});
}
Future<Map<String, dynamic>> getHeader({required int height}) async =>
await call(method: 'blockchain.block.get_header', params: [height])
Future<Map<String, dynamic>> getMerkle({required String hash, required int height}) async =>
await call(method: 'blockchain.transaction.get_merkle', params: [hash, height])
as Map<String, dynamic>;
Future<Map<String, dynamic>> getHeader({required int height}) async =>
await call(method: 'blockchain.block.get_header', params: [height]) as Map<String, dynamic>;
Future<double> estimatefee({required int p}) =>
call(method: 'blockchain.estimatefee', params: [p])
.then((dynamic result) {
call(method: 'blockchain.estimatefee', params: [p]).then((dynamic result) {
if (result is double) {
return result;
}
@ -319,15 +326,9 @@ class ElectrumClient {
final topDoubleString = await estimatefee(p: 1);
final middleDoubleString = await estimatefee(p: 5);
final bottomDoubleString = await estimatefee(p: 100);
final top =
(stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000)
.round();
final middle =
(stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000)
.round();
final bottom =
(stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000)
.round();
final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000).round();
final middle = (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000).round();
final bottom = (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000).round();
return [bottom, middle, top];
} 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) {
_id += 1;
return subscribe<Object>(
@ -344,16 +360,14 @@ class ElectrumClient {
}
BehaviorSubject<T>? subscribe<T>(
{required String id,
required String method,
List<Object> params = const []}) {
{required String id, required String method, List<Object> params = const []}) {
try {
final subscription = BehaviorSubject<T>();
_regisrySubscription(id, subscription);
socket!.write(jsonrpc(method: method, id: _id, params: params));
return subscription;
} catch(e) {
} catch (e) {
print(e.toString());
return null;
}
@ -370,9 +384,7 @@ class ElectrumClient {
}
Future<dynamic> callWithTimeout(
{required String method,
List<Object> params = const [],
int timeout = 4000}) async {
{required String method, List<Object> params = const [], int timeout = 4000}) async {
try {
final completer = Completer<dynamic>();
_id += 1;
@ -386,7 +398,7 @@ class ElectrumClient {
});
return completer.future;
} catch(e) {
} catch (e) {
print(e.toString());
}
}
@ -397,8 +409,8 @@ class ElectrumClient {
onConnectionStatusChange = null;
}
void _registryTask(int id, Completer<dynamic> completer) => _tasks[id.toString()] =
SocketTask(completer: completer, isSubscription: false);
void _registryTask(int id, Completer<dynamic> completer) =>
_tasks[id.toString()] = SocketTask(completer: completer, isSubscription: false);
void _regisrySubscription(String id, BehaviorSubject<dynamic> subject) =>
_tasks[id] = SocketTask(subject: subject, isSubscription: true);
@ -419,8 +431,7 @@ class ElectrumClient {
}
}
void _methodHandler(
{required String method, required Map<String, dynamic> request}) {
void _methodHandler({required String method, required Map<String, dynamic> request}) {
switch (method) {
case 'blockchain.scripthash.subscribe':
final params = request['params'] as List<dynamic>;
@ -451,8 +462,8 @@ class ElectrumClient {
_methodHandler(method: method, request: response);
return;
}
if (id != null){
if (id != null) {
_finish(id, result);
}
}

View file

@ -36,7 +36,8 @@ import 'package:cw_bitcoin/electrum.dart';
import 'package:hex/hex.dart';
import 'package:cw_core/crypto_currency.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';
@ -47,19 +48,19 @@ abstract class ElectrumWalletBase
with Store {
ElectrumWalletBase(
{required String password,
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required this.networkType,
required this.mnemonic,
required Uint8List seedBytes,
required this.encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumClient? electrumClient,
ElectrumBalance? initialBalance,
CryptoCurrency? currency})
required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo,
required this.networkType,
required this.mnemonic,
required Uint8List seedBytes,
required this.encryptionFileUtils,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumClient? electrumClient,
ElectrumBalance? initialBalance,
CryptoCurrency? currency})
: hd = currency == CryptoCurrency.bch
? bitcoinCashHDWallet(seedBytes)
: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"),
? bitcoinCashHDWallet(seedBytes)
: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"),
syncStatus = NotConnectedSyncStatus(),
_password = password,
_feeRates = <int>[],
@ -68,24 +69,20 @@ abstract class ElectrumWalletBase
_scripthashesUpdateSubject = {},
balance = ObservableMap<CryptoCurrency, ElectrumBalance>.of(currency != null
? {
currency:
initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0)
}
currency:
initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0)
}
: {}),
this.unspentCoinsInfo = unspentCoinsInfo,
super(walletInfo) {
this.electrumClient = electrumClient ?? ElectrumClient();
this.walletInfo = walletInfo;
transactionHistory =
ElectrumTransactionHistory(
walletInfo: walletInfo,
password: password,
encryptionFileUtils: encryptionFileUtils);
transactionHistory = ElectrumTransactionHistory(
walletInfo: walletInfo, password: password, encryptionFileUtils: encryptionFileUtils);
}
static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) =>
bitcoin.HDWallet.fromSeed(seedBytes)
.derivePath("m/44'/145'/0'/0");
bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0");
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
inputsCount * 146 + outputsCounts * 33 + 8;
@ -210,9 +207,7 @@ abstract class ElectrumWalletBase
throw BitcoinTransactionNoInputsException();
}
final allAmountFee = transactionCredentials.feeRate != null
? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length)
: feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length);
final allAmountFee = 222;
final allAmount = allInputsAmount - allAmountFee;
@ -261,14 +256,14 @@ abstract class ElectrumWalletBase
}
}
if (fee == 0) {
throw BitcoinTransactionWrongBalanceException(currency);
if (fee == 0 && networkType == bitcoin.bitcoin) {
// throw BitcoinTransactionWrongBalanceException(currency);
}
final totalAmount = amount + fee;
if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
// throw BitcoinTransactionWrongBalanceException(currency);
}
final txb = bitcoin.TransactionBuilder(network: networkType);
@ -295,18 +290,35 @@ abstract class ElectrumWalletBase
}
if (amount <= 0 || totalInputAmount < totalAmount) {
throw BitcoinTransactionWrongBalanceException(currency);
// throw BitcoinTransactionWrongBalanceException(currency);
}
txb.setVersion(1);
List<bitcoin.PrivateKeyInfo> inputPrivKeys = [];
List<bitcoin.Outpoint> outpoints = [];
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) {
final p2wpkh = bitcoin
.P2WPKH(
data: generatePaymentData(
hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
index: input.bitcoinAddressRecord.index),
network: networkType)
data: generatePaymentData(
hd: input.bitcoinAddressRecord.isHidden
? walletAddresses.sideHd
: walletAddresses.mainHd,
index: input.bitcoinAddressRecord.index),
network: networkType)
.data;
txb.addInput(input.hash, input.vout, null, p2wpkh.output);
@ -315,21 +327,48 @@ abstract class ElectrumWalletBase
}
});
List<bitcoin.SilentPaymentDestination> silentAddresses = [];
outputs.forEach((item) {
final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount;
final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address;
txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!);
if (outputAddress.startsWith('tsp1')) {
silentAddresses
.add(bitcoin.SilentPaymentDestination.fromAddress(outputAddress, outputAmount!));
} else {
txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!);
}
});
final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1);
var feeAmount = 0;
if (silentAddresses.isNotEmpty) {
final outpointsHash = bitcoin.SilentPayment.hashOutpoints(outpoints);
if (transactionCredentials.feeRate != null) {
feeAmount = transactionCredentials.feeRate! * estimatedSize;
} else {
feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize;
final aSum = bitcoin.SilentPayment.getSumInputPrivKeys(inputPrivKeys);
final generatedOutputs = bitcoin.SilentPayment.generateMultipleRecipientPubkeys(
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;
if (changeValue > minAmount) {
@ -356,12 +395,13 @@ abstract class ElectrumWalletBase
}
String toJSON() => json.encode({
'mnemonic': mnemonic,
'account_index': walletAddresses.currentReceiveAddressIndex.toString(),
'change_address_index': walletAddresses.currentChangeAddressIndex.toString(),
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
'balance': balance[currency]?.toJSON()
});
'mnemonic': mnemonic,
'account_index': walletAddresses.currentReceiveAddressIndex.toString(),
'change_address_index': walletAddresses.currentChangeAddressIndex.toString(),
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
'balance': balance[currency]?.toJSON(),
'network_type': networkType.toString()
});
int feeRate(TransactionPriority priority) {
try {
@ -376,7 +416,7 @@ abstract class ElectrumWalletBase
}
int feeAmountForPriority(
BitcoinTransactionPriority priority, int inputsCount, int outputsCount) =>
BitcoinTransactionPriority priority, int inputsCount, int outputsCount) =>
feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount);
int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) =>
@ -476,17 +516,78 @@ abstract class ElectrumWalletBase
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
Future<void> updateUnspent() async {
final unspent = await Future.wait(walletAddresses
.addresses.map((address) => electrumClient
final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient
.getListUnspentWithAddress(address.address, networkType)
.then((unspent) => unspent
.map((unspent) {
try {
return BitcoinUnspent.fromJSON(address, unspent);
} catch(_) {
return null;
}
}).whereNotNull())));
.then((unspent) => unspent.map((unspent) {
try {
return BitcoinUnspent.fromJSON(address, unspent);
} catch (_) {
return null;
}
}).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();
if (unspentCoinsInfo.isEmpty) {
@ -533,7 +634,7 @@ abstract class ElectrumWalletBase
try {
final List<dynamic> keys = <dynamic>[];
final currentWalletUnspentCoins =
unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
if (currentWalletUnspentCoins.isNotEmpty) {
currentWalletUnspentCoins.forEach((element) {
@ -555,12 +656,23 @@ abstract class ElectrumWalletBase
Future<ElectrumTransactionBundle> getTransactionExpanded(
{required String hash, required int height}) async {
final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash);
final transactionHex = verboseTransaction['hex'] as String;
final verboseTransaction =
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 ins = <bitcoin.Transaction>[];
final time = verboseTransaction['time'] as int?;
final confirmations = verboseTransaction['confirmations'] as int? ?? 0;
for (final vin in original.ins) {
final id = HEX.encode(vin.hash!.reversed.toList());
@ -666,7 +778,7 @@ abstract class ElectrumWalletBase
final addresses = walletAddresses.addresses.toList();
final balanceFutures = <Future<Map<String, dynamic>>>[];
for (var i = 0; i < addresses.length; i++) {
final addressRecord = addresses[i] ;
final addressRecord = addresses[i];
final sh = scriptHash(addressRecord.address, networkType: networkType);
final balanceFuture = electrumClient.getBalance(sh);
balanceFutures.add(balanceFuture);
@ -734,4 +846,32 @@ abstract class ElectrumWalletBase
? base64Encode(hd.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';
class ElectrumWalletAddresses = ElectrumWalletAddressesBase
with _$ElectrumWalletAddresses;
class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
ElectrumWalletAddressesBase(WalletInfo walletInfo,
@ -21,20 +20,22 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
required this.networkType,
List<BitcoinAddressRecord>? initialAddresses,
int initialRegularAddressIndex = 0,
int initialChangeAddressIndex = 0})
: addresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? []).toSet()),
receiveAddresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? [])
int initialChangeAddressIndex = 0,
bitcoin.SilentPaymentReceiver? silentAddress})
: addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
silentAddress = silentAddress,
receiveAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed)
.toSet()),
changeAddresses = ObservableList<BitcoinAddressRecord>.of(
(initialAddresses ?? [])
.toSet()),
changeAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed)
.toSet()),
.toSet()),
silentAddresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? [])
.where((addressRecord) => addressRecord.silentAddressLabel != null)
.toSet()),
currentReceiveAddressIndex = initialRegularAddressIndex,
currentChangeAddressIndex = initialChangeAddressIndex,
super(walletInfo);
super(walletInfo);
static const defaultReceiveAddressesCount = 22;
static const defaultChangeAddressesCount = 17;
@ -45,14 +46,20 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final ObservableList<BitcoinAddressRecord> addresses;
final ObservableList<BitcoinAddressRecord> receiveAddresses;
final ObservableList<BitcoinAddressRecord> changeAddresses;
final ObservableList<BitcoinAddressRecord> silentAddresses;
final ElectrumClient electrumClient;
final bitcoin.NetworkType networkType;
final bitcoin.HDWallet mainHd;
final bitcoin.HDWallet sideHd;
@override
// TODO: labels -> disable edit on receive page
final bitcoin.SilentPaymentReceiver? silentAddress;
@observable
String? activeAddress;
@computed
String get address {
String get receiveAddress {
if (receiveAddresses.isEmpty) {
final address = generateNewAddress().address;
return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address;
@ -63,28 +70,40 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
@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 currentChangeAddressIndex;
@computed
int get totalCountOfReceiveAddresses =>
addresses.fold(0, (acc, addressRecord) {
if (!addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) {
if (!addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
@computed
int get totalCountOfChangeAddresses =>
addresses.fold(0, (acc, addressRecord) {
if (addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) {
if (addressRecord.isHidden) {
return acc + 1;
}
return acc;
});
Future<void> discoverAddresses() async {
await _discoverAddresses(mainHd, false);
@ -114,11 +133,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if (changeAddresses.isEmpty) {
final newAddresses = await _createNewAddresses(gap,
hd: sideHd,
startIndex: totalCountOfChangeAddresses > 0
? totalCountOfChangeAddresses - 1
: 0,
isHidden: true);
hd: sideHd,
startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0,
isHidden: true);
_addAddresses(newAddresses);
}
@ -133,8 +150,24 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
BitcoinAddressRecord generateNewAddress(
{bitcoin.HDWallet? hd, bool isHidden = false}) {
currentReceiveAddressIndex += 1;
{bitcoin.HDWallet? hd, bool isHidden = false, String? label}) {
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 ???
final address = BitcoinAddressRecord(
getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd),
@ -142,6 +175,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
isHidden: isHidden);
addresses.add(address);
return address;
currentReceiveAddressIndex += 1;
}
String getAddress({required int index, required bitcoin.HDWallet hd}) => '';
@ -160,16 +195,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
@action
void updateReceiveAddresses() {
receiveAddresses.removeRange(0, receiveAddresses.length);
final newAdresses = addresses
.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
final newAdresses =
addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
receiveAddresses.addAll(newAdresses);
}
@action
void updateChangeAddresses() {
changeAddresses.removeRange(0, changeAddresses.length);
final newAdresses = addresses
.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed);
final newAdresses =
addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed);
changeAddresses.addAll(newAdresses);
}
@ -178,20 +213,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
List<BitcoinAddressRecord> addrs;
if (addresses.isNotEmpty) {
addrs = addresses
.where((addr) => addr.isHidden == isHidden)
.toList();
addrs = addresses.where((addr) => addr.isHidden == isHidden).toList();
} else {
addrs = await _createNewAddresses(
isHidden
? defaultChangeAddressesCount
: defaultReceiveAddressesCount,
isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount,
startIndex: 0,
hd: hd,
isHidden: isHidden);
}
while(hasAddrUse) {
while (hasAddrUse) {
final addr = addrs.last.address;
hasAddrUse = await _hasAddressUsed(addr);
@ -201,11 +232,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final start = addrs.length;
final count = start + gap;
final batch = await _createNewAddresses(
count,
startIndex: start,
hd: hd,
isHidden: isHidden);
final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden);
addrs.addAll(batch);
}
@ -229,21 +256,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
final newAddresses = await _createNewAddresses(
addressesCount,
startIndex: countOfReceiveAddresses,
hd: mainHd,
isHidden: false);
final newAddresses = await _createNewAddresses(addressesCount,
startIndex: countOfReceiveAddresses, hd: mainHd, isHidden: false);
addresses.addAll(newAddresses);
}
if (countOfHiddenAddresses < defaultChangeAddressesCount) {
final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
final newAddresses = await _createNewAddresses(
addressesCount,
startIndex: countOfHiddenAddresses,
hd: sideHd,
isHidden: true);
final newAddresses = await _createNewAddresses(addressesCount,
startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true);
addresses.addAll(newAddresses);
}
}
@ -253,10 +274,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final list = <BitcoinAddressRecord>[];
for (var i = startIndex; i < count + startIndex; i++) {
final address = BitcoinAddressRecord(
getAddress(index: i, hd: hd),
index: i,
isHidden: isHidden);
final address =
BitcoinAddressRecord(getAddress(index: i, hd: hd), index: i, isHidden: isHidden);
list.add(address);
}
@ -275,4 +294,4 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
final transactionHistory = await electrumClient.getHistory(sh);
return transactionHistory.isNotEmpty;
}
}
}

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

View file

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

View file

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

View file

@ -20,9 +20,7 @@ dependencies:
cw_core:
path: ../cw_core
bitcoin_flutter:
git:
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake-update-v3
path: /home/rafael/Storage/Repositories/bitcoin_flutter
bitbox:
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();
@override
Future<BitcoinCashWallet> create(
credentials) async {
Future<BitcoinCashWallet> create(credentials, {bool? isTestnet}) async {
final wallet = await BitcoinCashWalletBase.create(
mnemonic: await Mnemonic.generate(),
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.
FLUTTER_ROOT=C:\Users\borod\flutter
FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash
FLUTTER_ROOT=/home/rafael/Storage/Repositories/Build Sources/flutter
FLUTTER_APPLICATION_PATH=/opt/android/cake_wallet/cw_bitcoin_cash
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=0.0.1

View file

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

View file

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

View file

@ -14,5 +14,9 @@ class Unspent {
bool isFrozen;
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> {
WalletType getType();
Future<WalletBase> create(N credentials);
Future<WalletBase> create(N credentials, {bool? isTestnet});
Future<WalletBase> restoreFromSeed(RFS credentials);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -28,7 +28,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
WalletType getType() => WalletType.nano;
@override
Future<WalletBase> create(NanoNewWalletCredentials credentials) async {
Future<WalletBase> create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async {
// nano standard:
DerivationType derivationType = DerivationType.nano;
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
Future<void> generateNewAddress(Object wallet) async {
Future<void> generateNewAddress(Object wallet, {String? label}) async {
final bitcoinWallet = wallet as ElectrumWallet;
await bitcoinWallet.walletAddresses.generateNewAddress();
await bitcoinWallet.walletAddresses.generateNewAddress(label: label);
}
@override
@ -106,6 +106,21 @@ class CWBitcoin extends Bitcoin {
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
String formatterBitcoinAmountToString({required int amount})
=> bitcoinAmountToString(amount: amount);
@ -156,4 +171,4 @@ class CWBitcoin extends Bitcoin {
@override
TransactionPriority getLitecoinTransactionPrioritySlow()
=> LitecoinTransactionPriority.slow;
}
}

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}\$'
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
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:
return '[0-9a-zA-Z_]';
case CryptoCurrency.banano:
@ -284,4 +287,4 @@ class AddressValidator extends TextValidator {
return null;
}
}
}
}

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);
if (credentials.password == null) {
@ -58,7 +58,7 @@ class WalletCreationService {
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) {
await sharedPreferences.setBool(

View file

@ -532,8 +532,7 @@ Future<void> setup({
getIt.registerFactory<Modify2FAPage>(
() => Modify2FAPage(setup2FAViewModel: getIt.get<Setup2FAViewModel>()));
getIt.registerFactory<DesktopSettingsPage>(
() => DesktopSettingsPage());
getIt.registerFactory<DesktopSettingsPage>(() => DesktopSettingsPage());
getIt.registerFactoryParam<ReceiveOptionViewModel, ReceivePageOption?, void>(
(pageOption, _) => ReceiveOptionViewModel(getIt.get<AppStore>().wallet!, pageOption));
@ -653,7 +652,7 @@ Future<void> setup({
getIt.registerFactory<MoneroAccountListViewModel>(() {
final wallet = getIt.get<AppStore>().wallet!;
if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) {
if (true) {
return MoneroAccountListViewModel(wallet);
}
throw Exception(
@ -848,8 +847,8 @@ Future<void> setup({
return ethereum!.createEthereumWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.bitcoinCash:
return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource,
SettingsStoreBase.walletPasswordDirectInput);
return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource,
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.nano:
return nano!.createNanoWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
@ -1155,8 +1154,8 @@ Future<void> setup({
IoniaPaymentStatusPage(
getIt.get<IoniaPaymentStatusViewModel>(param1: paymentInfo, param2: committedInfo)));
getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, WalletType, void>(
(type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get<SettingsStore>()));
getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, void, void>(
(type, _) => AdvancedPrivacySettingsViewModel(getIt.get<SettingsStore>()));
getIt.registerFactoryParam<WalletUnlockLoadableViewModel, WalletUnlockArguments, void>((args, _) {
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/sync_status.dart';
// import 'package:cw_core/sync_status.dart';
import 'package:cake_wallet/store/settings_store.dart';
Timer? _checkConnectionTimer;
// Timer? _checkConnectionTimer;
void startCheckConnectionReaction(
WalletBase wallet, SettingsStore settingsStore,
{int timeInterval = 5}) {
_checkConnectionTimer?.cancel();
_checkConnectionTimer =
Timer.periodic(Duration(seconds: timeInterval), (_) async {
try {
final connectivityResult = await (Connectivity().checkConnectivity());
// _checkConnectionTimer?.cancel();
// _checkConnectionTimer =
// Timer.periodic(Duration(seconds: timeInterval), (_) async {
// try {
// final connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
wallet.syncStatus = FailedSyncStatus();
return;
}
// if (connectivityResult == ConnectivityResult.none) {
// wallet.syncStatus = FailedSyncStatus();
// return;
// }
if (wallet.syncStatus is LostConnectionSyncStatus ||
wallet.syncStatus is FailedSyncStatus) {
final alive =
await settingsStore.getCurrentNode(wallet.type).requestNode();
// if (wallet.syncStatus is LostConnectionSyncStatus ||
// wallet.syncStatus is FailedSyncStatus) {
// final alive =
// await settingsStore.getCurrentNode(wallet.type).requestNode();
if (alive) {
await wallet.connectToNode(
node: settingsStore.getCurrentNode(wallet.type));
}
}
} catch (e) {
print(e.toString());
}
});
// if (alive) {
// await wallet.connectToNode(
// node: settingsStore.getCurrentNode(wallet.type));
// }
// }
// } catch (e) {
// print(e.toString());
// }
// });
}

View file

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

View file

@ -161,10 +161,10 @@ class AddressPage extends BasePage {
Observer(builder: (_) {
if (addressListViewModel.hasAddressList) {
return GestureDetector(
onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled
onTap: () async => !addressListViewModel.hasSilentAddresses &&
dashboardViewModel.isAutoGenerateSubaddressesEnabled
? await showPopUp<void>(
context: context,
builder: (_) => getIt.get<MoneroAccountListPage>())
context: context, builder: (_) => getIt.get<MoneroAccountListPage>())
: Navigator.of(context).pushNamed(Routes.receive),
child: Container(
height: 50,
@ -184,26 +184,30 @@ class AddressPage extends BasePage {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Observer(
builder: (_) {
String label = addressListViewModel.hasAccounts
? S.of(context).accounts_subaddresses
: S.of(context).addresses;
builder: (_) {
String label = addressListViewModel.hasSilentAddresses
? S.of(context).address_and_silent_addresses
: addressListViewModel.hasAccounts
? S.of(context).accounts_subaddresses
: S.of(context).addresses;
if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) {
label = addressListViewModel.hasAccounts
? S.of(context).accounts
: S.of(context).account;
}
return Text(
label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.extension<SyncIndicatorTheme>()!
.textColor),
);
},),
if (!addressListViewModel.hasSilentAddresses &&
dashboardViewModel.isAutoGenerateSubaddressesEnabled) {
label = addressListViewModel.hasAccounts
? S.of(context).accounts
: S.of(context).account;
}
return Text(
label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.extension<SyncIndicatorTheme>()!
.textColor),
);
},
),
Icon(
Icons.arrow_forward_ios,
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,
textAlign: TextAlign.center,
style: TextStyle(

View file

@ -1,4 +1,5 @@
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/main.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
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) =>
GradientBackground(scaffold: scaffold);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
Widget trailing(BuildContext context) {
@ -99,7 +98,8 @@ class ReceivePage extends BasePage {
@override
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.nano ||
addressListViewModel.type == WalletType.banano)
@ -156,7 +156,8 @@ class ReceivePage extends BasePage {
icon: Icon(
Icons.arrow_forward_ios,
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(
onTap: () =>
Navigator.of(context).pushNamed(Routes.newSubaddress),
title: S.of(context).addresses,
title: S.of(context).silent_addresses,
icon: Icon(
Icons.add,
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 =
item.address == addressListViewModel.address.address;
final backgroundColor = isCurrent
? Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor
: Theme.of(context).extension<ReceivePageTheme>()!.tilesBackgroundColor;
? Theme.of(context)
.extension<ReceivePageTheme>()!
.currentTileBackgroundColor
: Theme.of(context)
.extension<ReceivePageTheme>()!
.tilesBackgroundColor;
final textColor = isCurrent
? Theme.of(context).extension<ReceivePageTheme>()!.currentTileTextColor
: Theme.of(context).extension<ReceivePageTheme>()!.tilesTextColor;
? Theme.of(context)
.extension<ReceivePageTheme>()!
.currentTileTextColor
: Theme.of(context)
.extension<ReceivePageTheme>()!
.tilesTextColor;
return AddressCell.fromItem(item,
isCurrent: isCurrent,
@ -202,6 +212,15 @@ class ReceivePage extends BasePage {
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:flutter/material.dart';
class Annotation extends Comparable<Annotation> {
class Annotation implements Comparable<Annotation> {
Annotation({required this.range, required this.style});
final TextRange range;

View file

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

View file

@ -65,6 +65,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
bool get hasAuthCredentials =>
_walletType == WalletType.monero || _walletType == WalletType.haven;
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
String get uri {
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:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:mobx/mobx.dart';
import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_base.dart';
@ -27,8 +28,7 @@ class AddressEditOrCreateStateFailure extends AddressEditOrCreateState {
}
abstract class WalletAddressEditOrCreateViewModelBase with Store {
WalletAddressEditOrCreateViewModelBase(
{required WalletBase wallet, WalletAddressListItem? item})
WalletAddressEditOrCreateViewModelBase({required WalletBase wallet, WalletAddressListItem? item})
: isEdit = item != null,
state = AddressEditOrCreateStateInitial(),
label = item?.name ?? '',
@ -68,27 +68,21 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
if (wallet.type == WalletType.bitcoin
|| wallet.type == WalletType.litecoin
|| wallet.type == WalletType.bitcoinCash) {
await bitcoin!.generateNewAddress(wallet);
await bitcoin!.generateNewAddress(wallet, label: label);
await wallet.save();
}
if (wallet.type == WalletType.monero) {
await monero
!.getSubaddressList(wallet)
.addSubaddress(
wallet,
accountIndex: monero!.getCurrentAccount(wallet).id,
label: label);
await monero!
.getSubaddressList(wallet)
.addSubaddress(wallet, accountIndex: monero!.getCurrentAccount(wallet).id, label: label);
await wallet.save();
}
if (wallet.type == WalletType.haven) {
await haven
!.getSubaddressList(wallet)
.addSubaddress(
wallet,
accountIndex: haven!.getCurrentAccount(wallet).id,
label: label);
await haven!
.getSubaddressList(wallet)
.addSubaddress(wallet, accountIndex: haven!.getCurrentAccount(wallet).id, label: label);
await wallet.save();
}
}
@ -109,9 +103,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
}
if (wallet.type == WalletType.haven) {
await haven!.getSubaddressList(wallet).setLabelSubaddress(wallet,
accountIndex: haven!.getCurrentAccount(wallet).id,
addressIndex: index,
label: label);
accountIndex: haven!.getCurrentAccount(wallet).id, addressIndex: index, label: label);
await wallet.save();
}
}

View file

@ -109,7 +109,7 @@ class EthereumURI extends PaymentURI {
class BitcoinCashURI extends PaymentURI {
BitcoinCashURI({required String amount, required String address})
: super(amount: amount, address: address);
: super(amount: amount, address: address);
@override
String toString() {
var base = address;
@ -120,9 +120,7 @@ class BitcoinCashURI extends PaymentURI {
return base;
}
}
}
class NanoURI extends PaymentURI {
NanoURI({required String amount, required String address})
@ -147,8 +145,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
}) : _baseItems = <ListItem>[],
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
hasAccounts =
appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven,
hasAccounts = appStore.wallet!.type == WalletType.bitcoin ||
appStore.wallet!.type == WalletType.monero ||
appStore.wallet!.type == WalletType.haven,
amount = '',
super(appStore: appStore) {
_init();
@ -159,7 +158,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
_init();
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';
@ -257,13 +258,19 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
}
if (wallet.type == WalletType.bitcoin) {
final primaryAddress = bitcoin!.getAddress(wallet);
final bitcoinAddresses = bitcoin!.getAddresses(wallet).map((addr) {
final isPrimary = addr == primaryAddress;
final receiveAddress = bitcoin!.getReceiveAddress(wallet);
addressList.add(
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) {
@ -291,18 +298,24 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
return '';
}
@computed
bool get hasSilentAddresses => wallet.type == WalletType.bitcoin;
@computed
bool get hasAddressList =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.monero ||
wallet.type == WalletType.haven;/* ||
wallet.type ==
WalletType
.haven; /* ||
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
bool get showElectrumAddressDisclaimer =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash;
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash;
List<ListItem> _baseItems;
@ -316,9 +329,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
_baseItems = [];
if (wallet.type == WalletType.monero ||
wallet.type == WalletType.haven /*||
wallet.type ==
WalletType
.haven /*||
wallet.type == WalletType.nano ||
wallet.type == WalletType.banano*/) {
wallet.type == WalletType.banano*/
) {
_baseItems.add(WalletAccountListHeader());
}

View file

@ -49,7 +49,7 @@ abstract class WalletCreationVMBase with Store {
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;
try {
state = IsExecutingState();

View file

@ -26,6 +26,12 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
: selectedMnemonicLanguage = '',
super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false);
@observable
bool _useTestnet = false;
@computed
bool get useTestnet => _useTestnet;
@observable
String selectedMnemonicLanguage;
@ -58,6 +64,10 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
@override
Future<WalletBase> process(WalletCredentials credentials) async {
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 <devicelocale/devicelocale_plugin.h>
#include <platform_device_id_linux/platform_device_id_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
@ -18,9 +17,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) devicelocale_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DevicelocalePlugin");
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 =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View file

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

View file

@ -5,30 +5,24 @@
import FlutterMacOS
import Foundation
import connectivity_plus_macos
import cw_monero
import device_info_plus
import devicelocale
import in_app_review
import package_info_plus
import path_provider_foundation
import platform_device_id
import platform_device_id_macos
import share_plus_macos
import shared_preferences_foundation
import url_launcher_macos
import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
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"))
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
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
cd cw_core; flutter pub get; flutter packages pub 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_bitcoin; flutter pub get; flutter packages pub 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_ethereum; flutter pub get; flutter packages pub 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_bitcoin_cash; flutter pub get; flutter packages pub run build_runner build --delete-conflicting-outputs; cd ..
flutter packages pub run build_runner build --delete-conflicting-outputs
cd cw_core; flutter pub get; dart 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; dart 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; dart 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; dart run build_runner build --delete-conflicting-outputs; cd ..
dart run build_runner build --delete-conflicting-outputs

View file

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

View file

@ -435,7 +435,7 @@
"search_language": "ابحث عن لغة",
"search_currency": "ابحث عن عملة",
"new_template": "قالب جديد",
"electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل",
"electrum_address_disclaimer": "نقوم بإنشاء عناوين أساسية جديدة في كل مرة تستخدم فيها واحدة ، لكن العناوين السابقة تستمر في العمل",
"wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.",
"market_place": "منصة التجارة",
"cake_pay_title": "بطاقات هدايا Cake Pay",
@ -732,5 +732,8 @@
"domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ",
"require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ",
"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_currency": "Търсене на валута",
"new_template": "Нов шаблон",
"electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят",
"electrum_address_disclaimer": "Ние генерираме нови първични адреси всеки път, когато използвате един, но предишните адреси продължават да работят",
"wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.",
"market_place": "Магазин",
"cake_pay_title": "Cake Pay Gift Карти",
@ -728,5 +728,8 @@
"domain_looks_up": "Търсене на домейни",
"require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли",
"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_currency": "Hledat měnu",
"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.",
"market_place": "Obchod",
"cake_pay_title": "Cake Pay dárkové karty",
@ -728,5 +728,8 @@
"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",
"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_currency": "Währung suchen",
"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",
"market_place": "Marktplatz",
"cake_pay_title": "Cake Pay-Geschenkkarten",
@ -736,5 +736,11 @@
"domain_looks_up": "Domain-Suchen",
"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.",
"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_currency": "Search currency",
"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.",
"market_place": "Marketplace",
"cake_pay_title": "Cake Pay Gift Cards",
@ -737,5 +737,8 @@
"domain_looks_up": "Domain lookups",
"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.",
"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_currency": "Moneda de búsqueda",
"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",
"market_place": "Mercado",
"cake_pay_title": "Tarjetas de regalo Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Búsquedas de dominio",
"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.",
"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_currency": "Rechercher une devise",
"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à",
"market_place": "Place de marché",
"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.",
"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",
"ask_each_time": "Demander à chaque fois",
"ask_each_time": "Demandez à chaque fois",
"buy_provider_unavailable": "Fournisseur actuellement indisponible.",
"signTransaction": "Signer une transaction",
"errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification",
@ -736,5 +736,8 @@
"domain_looks_up": "Recherches de domaine",
"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.",
"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_currency": "Neman kudin waje",
"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.",
"market_place": "Kasuwa",
"cake_pay_title": "Cake Pay Gift Cards",
@ -714,5 +714,8 @@
"domain_looks_up": "Binciken yanki",
"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.",
"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_currency": "मुद्रा खोजें",
"new_template": "नया टेम्पलेट",
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं",
"electrum_address_disclaimer": "हम हर बार जब आप एक का उपयोग करते हैं, तो हम नए प्राथमिक पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं",
"wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है",
"market_place": "मार्केटप्लेस",
"cake_pay_title": "केक पे गिफ्ट कार्ड्स",
@ -736,5 +736,8 @@
"domain_looks_up": "डोमेन लुकअप",
"require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है",
"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_currency": "Traži valutu",
"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",
"market_place": "Tržnica",
"cake_pay_title": "Cake Pay poklon kartice",
@ -734,5 +734,8 @@
"domain_looks_up": "Pretraga domena",
"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.",
"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_currency": "Cari mata uang",
"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.",
"market_place": "Pasar",
"cake_pay_title": "Kartu Hadiah Cake Pay",
@ -724,5 +724,8 @@
"domain_looks_up": "Pencarian domain",
"require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal",
"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_currency": "Cerca valuta",
"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",
"market_place": "Mercato",
"cake_pay_title": "Carte regalo Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Ricerche di domini",
"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.",
"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_currency": "検索通貨",
"new_template": "新しいテンプレート",
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します",
"electrum_address_disclaimer": "使用するたびに新しいプライマリアドレスを生成しますが、以前のアドレスは機能し続けます",
"wallet_name_exists": "その名前のウォレットはすでに存在しています",
"market_place": "Marketplace",
"cake_pay_title": "ケーキペイギフトカード",
@ -736,5 +736,8 @@
"domain_looks_up": "ドメイン検索",
"require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要",
"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_currency": "통화 검색",
"new_template": "새 템플릿",
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.",
"electrum_address_disclaimer": "우리는 당신이 하나를 사용할 때마다 새로운 기본 주소를 생성하지만 이전 주소는 계속 작동합니다.",
"wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.",
"market_place": "마켓플레이스",
"cake_pay_title": "케이크 페이 기프트 카드",
@ -734,5 +734,8 @@
"domain_looks_up": "도메인 조회",
"require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요",
"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_currency": "ငွေကြေးကိုရှာပါ။",
"new_template": "ပုံစံအသစ်",
"electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။",
"electrum_address_disclaimer": "သင်အသုံးပြုသောအခါတိုင်းကျွန်ုပ်တို့သည်အဓိကလိပ်စာအသစ်များကိုထုတ်လုပ်သည်, သို့သော်ယခင်လိပ်စာများဆက်လက်အလုပ်လုပ်သည်",
"wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။",
"market_place": "ဈေး",
"cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ",
@ -734,5 +734,8 @@
"domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ",
"require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။",
"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_currency": "Zoek valuta",
"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",
"market_place": "Marktplaats",
"cake_pay_title": "Cake Pay-cadeaubonnen",
@ -736,5 +736,8 @@
"domain_looks_up": "Domein opzoeken",
"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.",
"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_currency": "Wyszukaj walutę",
"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",
"market_place": "Rynek",
"cake_pay_title": "Karty podarunkowe Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Wyszukiwanie domen",
"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.",
"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_currency": "Pesquisar moeda",
"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",
"market_place": "Mercado",
"cake_pay_title": "Cartões de presente de CakePay",
@ -735,5 +735,8 @@
"domain_looks_up": "Pesquisas de domínio",
"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.",
"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_currency": "Валюта поиска",
"new_template": "Новый шаблон",
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.",
"electrum_address_disclaimer": "Мы генерируем новые основные адреса каждый раз, когда вы используете его, но предыдущие адреса продолжают работать",
"wallet_name_exists": "Кошелек с таким именем уже существует",
"market_place": "Торговая площадка",
"cake_pay_title": "Подарочные карты Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Поиск доменов",
"require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки",
"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_currency": "ค้นหาสกุลเงิน",
"new_template": "แม่แบบใหม่",
"electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป",
"electrum_address_disclaimer": "เราสร้างที่อยู่หลักใหม่ทุกครั้งที่คุณใช้ แต่ที่อยู่ก่อนหน้านี้ยังคงทำงานต่อไป",
"wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน",
"market_place": "ตลาดพื้นที่",
"cake_pay_title": "บัตรของขวัญ Cake Pay",
@ -734,5 +734,8 @@
"domain_looks_up": "การค้นหาโดเมน",
"require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก",
"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_currency": "Maghanap ng pera",
"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.",
"market_place": "Marketplace",
"cake_pay_title": "Cake pay card card",
@ -731,5 +731,8 @@
"domain_looks_up": "Mga paghahanap ng domain",
"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.",
"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_currency": "Para birimi ara",
"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.",
"market_place": "Pazar Alanı",
"cake_pay_title": "Cake Pay Hediye Kartları",
@ -734,5 +734,8 @@
"domain_looks_up": "Etki alanı aramaları",
"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.",
"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_currency": "Шукати валюту",
"new_template": "Новий шаблон",
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати",
"electrum_address_disclaimer": "Ми генеруємо нові первинні адреси кожного разу, коли ви використовуєте його, але попередні адреси продовжують працювати",
"wallet_name_exists": "Гаманець з такою назвою вже існує",
"market_place": "Ринок",
"cake_pay_title": "Подарункові картки Cake Pay",
@ -736,5 +736,8 @@
"domain_looks_up": "Пошук доменів",
"require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці",
"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_currency": "کرنسی تلاش کریں۔",
"new_template": "نیا سانچہ",
"electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔",
"electrum_address_disclaimer": "ہم ہر بار جب آپ کسی کو استعمال کرتے ہیں تو نئے پرائمری پتے تیار کرتے ہیں ، لیکن پچھلے پتے کام کرتے رہتے ہیں",
"wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔",
"market_place": "بازار",
"cake_pay_title": "Cake پے گفٹ کارڈز",
@ -728,5 +728,8 @@
"domain_looks_up": "ڈومین تلاش کرنا",
"require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ",
"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_currency": "Wá irú owó",
"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ẹ̀.",
"market_place": "Ọjà",
"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",
"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.",
"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_currency": "搜索货币",
"new_template": "新模板",
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效",
"electrum_address_disclaimer": "每次使用一个时,我们都会生成新的主地址,但是以前的地址继续工作",
"wallet_name_exists": "同名的钱包已经存在",
"market_place": "市场",
"cake_pay_title": "Cake Pay 礼品卡",
@ -735,5 +735,8 @@
"domain_looks_up": "域名查找",
"require_for_exchanges_to_external_wallets": "需要兑换到外部钱包",
"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
rm $APP_LOGO_DEST_PATH
rm $ANDROID_ICON_DEST_PATH
if [ ! -z "$APP_LOGO_DEST_PATH" ]; then
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 $ANDROID_ICON $ANDROID_ICON_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
fi
../android/app_properties.sh
../android/app_icon.sh
../android/manifest.sh
../android/inject_app_details.sh
cd ../.. # go to root
CONFIG_ARGS=""
@ -18,8 +23,8 @@ esac
cp -rf pubspec_description.yaml pubspec.yaml
flutter pub get
flutter pub run tool/generate_pubspec.dart
dart run tool/generate_pubspec.dart
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
cd $DIR

View file

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

View file

@ -3,7 +3,8 @@ gcc10Stdenv.mkDerivation {
name="gcc10-stdenv";
buildInputs = [
pkgs.cmake
pkgs.pkgconfig
pkgs.boost182
pkgs.pkgconf
pkgs.autoconf
pkgs.libtool
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_transaction_credentials.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 bitcoinContent = """
@ -91,12 +92,15 @@ abstract class Bitcoin {
TransactionPriority deserializeBitcoinTransactionPriority(int raw);
TransactionPriority deserializeLitecoinTransactionPriority(int raw);
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 createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate});
List<String> getAddresses(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});
double formatterBitcoinAmountToDouble({required int amount});
@ -1009,4 +1013,4 @@ class FakeSecureStorage extends SecureStorage {
}
await outputFile.writeAsString(output);
}
}