mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-519-tor
This commit is contained in:
commit
584af5d5ca
60 changed files with 641 additions and 468 deletions
|
@ -1,5 +1 @@
|
||||||
Monero enhancements
|
|
||||||
Bitcoin support different address types (Taproot, Segwit P2WPKH/P2WSH, Legacy)
|
|
||||||
In-App live status page for the app services
|
|
||||||
Add Exolix exchange provider
|
|
||||||
Bug fixes and enhancements
|
Bug fixes and enhancements
|
|
@ -3,6 +3,9 @@ import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin;
|
||||||
|
|
||||||
List<int> addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) {
|
List<int> addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) {
|
||||||
try {
|
try {
|
||||||
|
if (network == bitcoin.BitcoinCashNetwork.mainnet) {
|
||||||
|
return bitcoin.BitcoinCashAddress(address).baseAddress.toScriptPubKey().toBytes();
|
||||||
|
}
|
||||||
return bitcoin.addressToOutputScript(address: address, network: network);
|
return bitcoin.addressToOutputScript(address: address, network: network);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
print(err);
|
print(err);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cw_bitcoin/script_hash.dart' as sh;
|
import 'package:cw_bitcoin/script_hash.dart' as sh;
|
||||||
|
@ -20,10 +19,9 @@ class BitcoinAddressRecord {
|
||||||
_balance = balance,
|
_balance = balance,
|
||||||
_name = name,
|
_name = name,
|
||||||
_isUsed = isUsed,
|
_isUsed = isUsed,
|
||||||
scriptHash =
|
scriptHash = scriptHash ?? sh.scriptHash(address, network: network);
|
||||||
scriptHash ?? (network != null ? sh.scriptHash(address, network: network) : null);
|
|
||||||
|
|
||||||
factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork? network) {
|
factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork network) {
|
||||||
final decoded = json.decode(jsonSource) as Map;
|
final decoded = json.decode(jsonSource) as Map;
|
||||||
|
|
||||||
return BitcoinAddressRecord(
|
return BitcoinAddressRecord(
|
||||||
|
@ -39,9 +37,7 @@ class BitcoinAddressRecord {
|
||||||
.firstWhere((type) => type.toString() == decoded['type'] as String)
|
.firstWhere((type) => type.toString() == decoded['type'] as String)
|
||||||
: SegwitAddresType.p2wpkh,
|
: SegwitAddresType.p2wpkh,
|
||||||
scriptHash: decoded['scriptHash'] as String?,
|
scriptHash: decoded['scriptHash'] as String?,
|
||||||
network: (decoded['network'] as String?) == null
|
network: network,
|
||||||
? network
|
|
||||||
: BasedUtxoNetwork.fromName(decoded['network'] as String),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +52,7 @@ class BitcoinAddressRecord {
|
||||||
String _name;
|
String _name;
|
||||||
bool _isUsed;
|
bool _isUsed;
|
||||||
String? scriptHash;
|
String? scriptHash;
|
||||||
BasedUtxoNetwork? network;
|
BasedUtxoNetwork network;
|
||||||
|
|
||||||
int get txCount => _txCount;
|
int get txCount => _txCount;
|
||||||
|
|
||||||
|
@ -76,8 +72,6 @@ class BitcoinAddressRecord {
|
||||||
@override
|
@override
|
||||||
int get hashCode => address.hashCode;
|
int get hashCode => address.hashCode;
|
||||||
|
|
||||||
String get cashAddr => bitbox.Address.toCashAddress(address);
|
|
||||||
|
|
||||||
BitcoinAddressType type;
|
BitcoinAddressType type;
|
||||||
|
|
||||||
String updateScriptHash(BasedUtxoNetwork network) {
|
String updateScriptHash(BasedUtxoNetwork network) {
|
||||||
|
@ -95,6 +89,5 @@ class BitcoinAddressRecord {
|
||||||
'balance': balance,
|
'balance': balance,
|
||||||
'type': type.toString(),
|
'type': type.toString(),
|
||||||
'scriptHash': scriptHash,
|
'scriptHash': scriptHash,
|
||||||
'network': network?.value,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,8 +92,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required String password,
|
required String password,
|
||||||
}) async {
|
}) async {
|
||||||
final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password,
|
final network = walletInfo.network != null
|
||||||
walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null);
|
? BasedUtxoNetwork.fromName(walletInfo.network!)
|
||||||
|
: BitcoinNetwork.mainnet;
|
||||||
|
final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, network);
|
||||||
|
|
||||||
return BitcoinWallet(
|
return BitcoinWallet(
|
||||||
mnemonic: snp.mnemonic,
|
mnemonic: snp.mnemonic,
|
||||||
|
@ -106,7 +108,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialRegularAddressIndex: snp.regularAddressIndex,
|
initialRegularAddressIndex: snp.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp.changeAddressIndex,
|
initialChangeAddressIndex: snp.changeAddressIndex,
|
||||||
addressPageType: snp.addressPageType,
|
addressPageType: snp.addressPageType,
|
||||||
networkParam: snp.network,
|
networkParam: network,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,11 +75,7 @@ abstract class ElectrumWalletBase
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
this.unspentCoinsInfo = unspentCoinsInfo,
|
this.unspentCoinsInfo = unspentCoinsInfo,
|
||||||
this.network = networkType == bitcoin.bitcoin
|
this.network = _getNetwork(networkType, currency),
|
||||||
? BitcoinNetwork.mainnet
|
|
||||||
: networkType == litecoinNetwork
|
|
||||||
? LitecoinNetwork.mainnet
|
|
||||||
: BitcoinNetwork.testnet,
|
|
||||||
this.isTestnet = networkType == bitcoin.testnet,
|
this.isTestnet = networkType == bitcoin.testnet,
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.electrumClient = electrumClient ?? ElectrumClient();
|
this.electrumClient = electrumClient ?? ElectrumClient();
|
||||||
|
@ -204,12 +200,13 @@ abstract class ElectrumWalletBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<EstimatedTxResult> _estimateTxFeeAndInputsToUse(
|
Future<EstimatedTxResult> estimateTxFeeAndInputsToUse(
|
||||||
int credentialsAmount,
|
int credentialsAmount,
|
||||||
bool sendAll,
|
bool sendAll,
|
||||||
List<BitcoinBaseAddress> outputAddresses,
|
List<BitcoinBaseAddress> outputAddresses,
|
||||||
List<BitcoinOutput> outputs,
|
List<BitcoinOutput> outputs,
|
||||||
BitcoinTransactionCredentials transactionCredentials,
|
int? feeRate,
|
||||||
|
BitcoinTransactionPriority? priority,
|
||||||
{int? inputsCount}) async {
|
{int? inputsCount}) async {
|
||||||
final utxos = <UtxoWithAddress>[];
|
final utxos = <UtxoWithAddress>[];
|
||||||
List<ECPrivate> privateKeys = [];
|
List<ECPrivate> privateKeys = [];
|
||||||
|
@ -224,7 +221,7 @@ abstract class ElectrumWalletBase
|
||||||
allInputsAmount += utx.value;
|
allInputsAmount += utx.value;
|
||||||
leftAmount = leftAmount - utx.value;
|
leftAmount = leftAmount - utx.value;
|
||||||
|
|
||||||
final address = _addressTypeFromStr(utx.address, network);
|
final address = addressTypeFromStr(utx.address, network);
|
||||||
final privkey = generateECPrivate(
|
final privkey = generateECPrivate(
|
||||||
hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
|
hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
|
||||||
index: utx.bitcoinAddressRecord.index,
|
index: utx.bitcoinAddressRecord.index,
|
||||||
|
@ -261,7 +258,7 @@ abstract class ElectrumWalletBase
|
||||||
if (!sendAll) {
|
if (!sendAll) {
|
||||||
if (changeValue > 0) {
|
if (changeValue > 0) {
|
||||||
final changeAddress = await walletAddresses.getChangeAddress();
|
final changeAddress = await walletAddresses.getChangeAddress();
|
||||||
final address = _addressTypeFromStr(changeAddress, network);
|
final address = addressTypeFromStr(changeAddress, network);
|
||||||
outputAddresses.add(address);
|
outputAddresses.add(address);
|
||||||
outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue)));
|
outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue)));
|
||||||
}
|
}
|
||||||
|
@ -270,9 +267,9 @@ abstract class ElectrumWalletBase
|
||||||
final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
|
final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
|
||||||
utxos: utxos, outputs: outputs, network: network);
|
utxos: utxos, outputs: outputs, network: network);
|
||||||
|
|
||||||
final fee = transactionCredentials.feeRate != null
|
int fee = feeRate != null
|
||||||
? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize)
|
? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize)
|
||||||
: feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize);
|
: feeAmountForPriority(priority!, 0, 0, size: estimatedSize);
|
||||||
|
|
||||||
if (fee == 0) {
|
if (fee == 0) {
|
||||||
throw BitcoinTransactionWrongBalanceException(currency);
|
throw BitcoinTransactionWrongBalanceException(currency);
|
||||||
|
@ -309,8 +306,8 @@ abstract class ElectrumWalletBase
|
||||||
outputs.removeLast();
|
outputs.removeLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _estimateTxFeeAndInputsToUse(
|
return estimateTxFeeAndInputsToUse(
|
||||||
credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials,
|
credentialsAmount, sendAll, outputAddresses, outputs, feeRate, priority,
|
||||||
inputsCount: utxos.length + 1);
|
inputsCount: utxos.length + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,7 +328,7 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
for (final out in transactionCredentials.outputs) {
|
for (final out in transactionCredentials.outputs) {
|
||||||
final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address;
|
final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address;
|
||||||
final address = _addressTypeFromStr(outputAddress, network);
|
final address = addressTypeFromStr(outputAddress, network);
|
||||||
|
|
||||||
outputAddresses.add(address);
|
outputAddresses.add(address);
|
||||||
|
|
||||||
|
@ -356,8 +353,14 @@ abstract class ElectrumWalletBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final estimatedTx = await _estimateTxFeeAndInputsToUse(
|
final estimatedTx = await estimateTxFeeAndInputsToUse(
|
||||||
credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials);
|
credentialsAmount,
|
||||||
|
sendAll,
|
||||||
|
outputAddresses,
|
||||||
|
outputs,
|
||||||
|
transactionCredentials.feeRate,
|
||||||
|
transactionCredentials.priority,
|
||||||
|
);
|
||||||
|
|
||||||
final txb = BitcoinTransactionBuilder(
|
final txb = BitcoinTransactionBuilder(
|
||||||
utxos: estimatedTx.utxos,
|
utxos: estimatedTx.utxos,
|
||||||
|
@ -403,7 +406,6 @@ abstract class ElectrumWalletBase
|
||||||
? SegwitAddresType.p2wpkh.toString()
|
? SegwitAddresType.p2wpkh.toString()
|
||||||
: walletInfo.addressPageType.toString(),
|
: walletInfo.addressPageType.toString(),
|
||||||
'balance': balance[currency]?.toJSON(),
|
'balance': balance[currency]?.toJSON(),
|
||||||
'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
int feeRate(TransactionPriority priority) {
|
int feeRate(TransactionPriority priority) {
|
||||||
|
@ -864,6 +866,22 @@ abstract class ElectrumWalletBase
|
||||||
final HD = index == null ? hd : hd.derive(index);
|
final HD = index == null ? hd : hd.derive(index);
|
||||||
return base64Encode(HD.signMessage(message));
|
return base64Encode(HD.signMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BasedUtxoNetwork _getNetwork(bitcoin.NetworkType networkType, CryptoCurrency? currency) {
|
||||||
|
if (networkType == bitcoin.bitcoin && currency == CryptoCurrency.bch) {
|
||||||
|
return BitcoinCashNetwork.mainnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkType == litecoinNetwork) {
|
||||||
|
return LitecoinNetwork.mainnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkType == bitcoin.testnet) {
|
||||||
|
return BitcoinNetwork.testnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BitcoinNetwork.mainnet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EstimateTxParams {
|
class EstimateTxParams {
|
||||||
|
@ -891,7 +909,7 @@ class EstimatedTxResult {
|
||||||
final int amount;
|
final int amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) {
|
BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
|
||||||
if (P2pkhAddress.regex.hasMatch(address)) {
|
if (P2pkhAddress.regex.hasMatch(address)) {
|
||||||
return P2pkhAddress.fromAddress(address: address, network: network);
|
return P2pkhAddress.fromAddress(address: address, network: network);
|
||||||
} else if (P2shAddress.regex.hasMatch(address)) {
|
} else if (P2shAddress.regex.hasMatch(address)) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/electrum.dart';
|
import 'package:cw_bitcoin/electrum.dart';
|
||||||
import 'package:cw_core/wallet_addresses.dart';
|
import 'package:cw_core/wallet_addresses.dart';
|
||||||
|
@ -30,6 +29,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
Map<String, int>? initialRegularAddressIndex,
|
Map<String, int>? initialRegularAddressIndex,
|
||||||
Map<String, int>? initialChangeAddressIndex,
|
Map<String, int>? initialChangeAddressIndex,
|
||||||
|
BitcoinAddressType? initialAddressPageType,
|
||||||
}) : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
|
}) : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
|
||||||
addressesByReceiveType =
|
addressesByReceiveType =
|
||||||
ObservableList<BitcoinAddressRecord>.of((<BitcoinAddressRecord>[]).toSet()),
|
ObservableList<BitcoinAddressRecord>.of((<BitcoinAddressRecord>[]).toSet()),
|
||||||
|
@ -41,9 +41,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
.toSet()),
|
.toSet()),
|
||||||
currentReceiveAddressIndexByType = initialRegularAddressIndex ?? {},
|
currentReceiveAddressIndexByType = initialRegularAddressIndex ?? {},
|
||||||
currentChangeAddressIndexByType = initialChangeAddressIndex ?? {},
|
currentChangeAddressIndexByType = initialChangeAddressIndex ?? {},
|
||||||
_addressPageType = walletInfo.addressPageType != null
|
_addressPageType = initialAddressPageType ??
|
||||||
? BitcoinAddressType.fromValue(walletInfo.addressPageType!)
|
(walletInfo.addressPageType != null
|
||||||
: SegwitAddresType.p2wpkh,
|
? BitcoinAddressType.fromValue(walletInfo.addressPageType!)
|
||||||
|
: SegwitAddresType.p2wpkh),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
updateAddressesByMatch();
|
updateAddressesByMatch();
|
||||||
}
|
}
|
||||||
|
@ -52,10 +53,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
static const defaultChangeAddressesCount = 17;
|
static const defaultChangeAddressesCount = 17;
|
||||||
static const gap = 20;
|
static const gap = 20;
|
||||||
|
|
||||||
static String toCashAddr(String address) => bitbox.Address.toCashAddress(address);
|
|
||||||
|
|
||||||
static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address);
|
|
||||||
|
|
||||||
final ObservableList<BitcoinAddressRecord> _addresses;
|
final ObservableList<BitcoinAddressRecord> _addresses;
|
||||||
// Matched by addressPageType
|
// Matched by addressPageType
|
||||||
late ObservableList<BitcoinAddressRecord> addressesByReceiveType;
|
late ObservableList<BitcoinAddressRecord> addressesByReceiveType;
|
||||||
|
@ -67,7 +64,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
final bitcoin.HDWallet sideHd;
|
final bitcoin.HDWallet sideHd;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
BitcoinAddressType _addressPageType = SegwitAddresType.p2wpkh;
|
late BitcoinAddressType _addressPageType;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
BitcoinAddressType get addressPageType => _addressPageType;
|
BitcoinAddressType get addressPageType => _addressPageType;
|
||||||
|
@ -97,7 +94,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress;
|
return receiveAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
|
@ -105,9 +102,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set address(String addr) {
|
set address(String addr) {
|
||||||
if (addr.startsWith('bitcoincash:')) {
|
|
||||||
addr = toLegacy(addr);
|
|
||||||
}
|
|
||||||
final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == addr);
|
final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == addr);
|
||||||
|
|
||||||
previousAddressRecord = addressRecord;
|
previousAddressRecord = addressRecord;
|
||||||
|
@ -155,11 +149,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
await _generateInitialAddresses();
|
if (walletInfo.type == WalletType.bitcoinCash) {
|
||||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
} else if (walletInfo.type == WalletType.litecoin) {
|
||||||
await _generateInitialAddresses(type: SegwitAddresType.p2tr);
|
await _generateInitialAddresses();
|
||||||
await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
|
} else if (walletInfo.type == WalletType.bitcoin) {
|
||||||
|
await _generateInitialAddresses();
|
||||||
|
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||||
|
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
||||||
|
await _generateInitialAddresses(type: SegwitAddresType.p2tr);
|
||||||
|
await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
|
||||||
|
}
|
||||||
updateAddressesByMatch();
|
updateAddressesByMatch();
|
||||||
updateReceiveAddresses();
|
updateReceiveAddresses();
|
||||||
updateChangeAddresses();
|
updateChangeAddresses();
|
||||||
|
@ -220,7 +220,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
Future<void> updateAddressesInBox() async {
|
Future<void> updateAddressesInBox() async {
|
||||||
try {
|
try {
|
||||||
addressesMap.clear();
|
addressesMap.clear();
|
||||||
addressesMap[address] = '';
|
_addresses.forEach((addressRecord) {
|
||||||
|
addressesMap[addressRecord.address] = addressRecord.name;
|
||||||
|
});
|
||||||
await saveAddressesInBox();
|
await saveAddressesInBox();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
|
@ -229,9 +231,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void updateAddress(String address, String label) {
|
void updateAddress(String address, String label) {
|
||||||
if (address.startsWith('bitcoincash:')) {
|
|
||||||
address = toLegacy(address);
|
|
||||||
}
|
|
||||||
final addressRecord =
|
final addressRecord =
|
||||||
_addresses.firstWhere((addressRecord) => addressRecord.address == address);
|
_addresses.firstWhere((addressRecord) => addressRecord.address == address);
|
||||||
addressRecord.setNewName(label);
|
addressRecord.setNewName(label);
|
||||||
|
@ -261,7 +260,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
addressRecord.isHidden &&
|
addressRecord.isHidden &&
|
||||||
!addressRecord.isUsed &&
|
!addressRecord.isUsed &&
|
||||||
// TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type
|
// TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type
|
||||||
addressRecord.type == SegwitAddresType.p2wpkh);
|
(walletInfo.type != WalletType.bitcoin || addressRecord.type == SegwitAddresType.p2wpkh));
|
||||||
changeAddresses.addAll(newAddresses);
|
changeAddresses.addAll(newAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,12 @@ class ElectrumWalletSnapshot {
|
||||||
required this.regularAddressIndex,
|
required this.regularAddressIndex,
|
||||||
required this.changeAddressIndex,
|
required this.changeAddressIndex,
|
||||||
required this.addressPageType,
|
required this.addressPageType,
|
||||||
required this.network,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final String password;
|
final String password;
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
final String addressPageType;
|
final String? addressPageType;
|
||||||
final BasedUtxoNetwork network;
|
|
||||||
|
|
||||||
String mnemonic;
|
String mnemonic;
|
||||||
List<BitcoinAddressRecord> addresses;
|
List<BitcoinAddressRecord> addresses;
|
||||||
|
@ -32,7 +30,8 @@ class ElectrumWalletSnapshot {
|
||||||
Map<String, int> regularAddressIndex;
|
Map<String, int> regularAddressIndex;
|
||||||
Map<String, int> changeAddressIndex;
|
Map<String, int> changeAddressIndex;
|
||||||
|
|
||||||
static Future<ElectrumWalletSnapshot> load(String name, WalletType type, String password, BasedUtxoNetwork? network) async {
|
static Future<ElectrumWalletSnapshot> load(
|
||||||
|
String name, WalletType type, String password, BasedUtxoNetwork network) async {
|
||||||
final path = await pathForWallet(name: name, type: type);
|
final path = await pathForWallet(name: name, type: type);
|
||||||
final jsonSource = await read(path: path, password: password);
|
final jsonSource = await read(path: path, password: password);
|
||||||
final data = json.decode(jsonSource) as Map;
|
final data = json.decode(jsonSource) as Map;
|
||||||
|
@ -71,8 +70,7 @@ class ElectrumWalletSnapshot {
|
||||||
balance: balance,
|
balance: balance,
|
||||||
regularAddressIndex: regularAddressIndexByType,
|
regularAddressIndex: regularAddressIndexByType,
|
||||||
changeAddressIndex: changeAddressIndexByType,
|
changeAddressIndex: changeAddressIndexByType,
|
||||||
addressPageType: data['address_page_type'] as String? ?? SegwitAddresType.p2wpkh.toString(),
|
addressPageType: data['address_page_type'] as String?,
|
||||||
network: data['network_type'] == 'testnet' ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
|
import 'package:cw_bitcoin/address_to_output_script.dart';
|
||||||
|
import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin;
|
||||||
|
|
||||||
String scriptHash(String address, {required BasedUtxoNetwork network}) {
|
String scriptHash(String address, {required bitcoin.BasedUtxoNetwork network}) {
|
||||||
final outputScript = addressToOutputScript(address: address, network: network);
|
final outputScript = addressToOutputScript(address, network);
|
||||||
final parts = sha256.convert(outputScript).toString().split('');
|
final parts = sha256.convert(outputScript).toString().split('');
|
||||||
var res = '';
|
var res = '';
|
||||||
|
|
||||||
|
|
|
@ -79,11 +79,11 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: cake-update-v1
|
ref: cake-update-v2
|
||||||
resolved-ref: "9611e9db77e92a8434e918cdfb620068f6fcb1aa"
|
resolved-ref: "3fd81d238b990bb767fc7a4fdd5053a22a142e2e"
|
||||||
url: "https://github.com/cake-tech/bitcoin_base.git"
|
url: "https://github.com/cake-tech/bitcoin_base.git"
|
||||||
source: git
|
source: git
|
||||||
version: "4.0.0"
|
version: "4.2.0"
|
||||||
bitcoin_flutter:
|
bitcoin_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -97,10 +97,10 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: blockchain_utils
|
name: blockchain_utils
|
||||||
sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9"
|
sha256: "38ef5f4a22441ac4370aed9071dc71c460acffc37c79b344533f67d15f24c13c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.0"
|
version: "2.1.1"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -33,8 +33,8 @@ dependencies:
|
||||||
bitcoin_base:
|
bitcoin_base:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/bitcoin_base.git
|
url: https://github.com/cake-tech/bitcoin_base.git
|
||||||
ref: cake-update-v1
|
ref: cake-update-v2
|
||||||
blockchain_utils: ^1.6.0
|
blockchain_utils: ^2.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
@ -34,7 +34,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
required Uint8List seedBytes,
|
required Uint8List seedBytes,
|
||||||
String? addressPageType,
|
BitcoinAddressType? addressPageType,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
ElectrumBalance? initialBalance,
|
ElectrumBalance? initialBalance,
|
||||||
Map<String, int>? initialRegularAddressIndex,
|
Map<String, int>? initialRegularAddressIndex,
|
||||||
|
@ -58,6 +58,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
mainHd: hd,
|
mainHd: hd,
|
||||||
sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"),
|
sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"),
|
||||||
network: network,
|
network: network,
|
||||||
|
initialAddressPageType: addressPageType,
|
||||||
);
|
);
|
||||||
autorun((_) {
|
autorun((_) {
|
||||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||||
|
@ -84,7 +85,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
seedBytes: await Mnemonic.toSeed(mnemonic),
|
seedBytes: await Mnemonic.toSeed(mnemonic),
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||||
addressPageType: addressPageType,
|
addressPageType: P2pkhAddressType.p2pkh,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +102,31 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
||||||
password: password,
|
password: password,
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
unspentCoinsInfo: unspentCoinsInfo,
|
unspentCoinsInfo: unspentCoinsInfo,
|
||||||
initialAddresses: snp.addresses,
|
initialAddresses: snp.addresses.map((addr) {
|
||||||
|
try {
|
||||||
|
BitcoinCashAddress(addr.address);
|
||||||
|
return BitcoinAddressRecord(
|
||||||
|
addr.address,
|
||||||
|
index: addr.index,
|
||||||
|
isHidden: addr.isHidden,
|
||||||
|
type: P2pkhAddressType.p2pkh,
|
||||||
|
network: BitcoinCashNetwork.mainnet,
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
return BitcoinAddressRecord(
|
||||||
|
AddressUtils.getCashAddrFormat(addr.address),
|
||||||
|
index: addr.index,
|
||||||
|
isHidden: addr.isHidden,
|
||||||
|
type: P2pkhAddressType.p2pkh,
|
||||||
|
network: BitcoinCashNetwork.mainnet,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).toList(),
|
||||||
initialBalance: snp.balance,
|
initialBalance: snp.balance,
|
||||||
seedBytes: await Mnemonic.toSeed(snp.mnemonic),
|
seedBytes: await Mnemonic.toSeed(snp.mnemonic),
|
||||||
initialRegularAddressIndex: snp.regularAddressIndex,
|
initialRegularAddressIndex: snp.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp.changeAddressIndex,
|
initialChangeAddressIndex: snp.changeAddressIndex,
|
||||||
addressPageType: snp.addressPageType,
|
addressPageType: P2pkhAddressType.p2pkh,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi
|
||||||
super.initialAddresses,
|
super.initialAddresses,
|
||||||
super.initialRegularAddressIndex,
|
super.initialRegularAddressIndex,
|
||||||
super.initialChangeAddressIndex,
|
super.initialChangeAddressIndex,
|
||||||
|
super.initialAddressPageType,
|
||||||
}) : super(walletInfo);
|
}) : super(walletInfo);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -32,7 +32,7 @@ dependencies:
|
||||||
bitcoin_base:
|
bitcoin_base:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/bitcoin_base.git
|
url: https://github.com/cake-tech/bitcoin_base.git
|
||||||
ref: cake-update-v1
|
ref: cake-update-v2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ SPEC CHECKSUMS:
|
||||||
flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
|
flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
|
||||||
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
||||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||||
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
|
fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c
|
||||||
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
||||||
local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac
|
local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||||
|
@ -302,4 +302,4 @@ SPEC CHECKSUMS:
|
||||||
|
|
||||||
PODFILE CHECKSUM: fcb1b8418441a35b438585c9dd8374e722e6c6ca
|
PODFILE CHECKSUM: fcb1b8418441a35b438585c9dd8374e722e6c6ca
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
COCOAPODS: 1.15.2
|
||||||
|
|
|
@ -113,13 +113,39 @@ class CWBitcoin extends Bitcoin {
|
||||||
.map((BitcoinAddressRecord addr) => ElectrumSubAddress(
|
.map((BitcoinAddressRecord addr) => ElectrumSubAddress(
|
||||||
id: addr.index,
|
id: addr.index,
|
||||||
name: addr.name,
|
name: addr.name,
|
||||||
address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address,
|
address: addr.address,
|
||||||
txCount: addr.txCount,
|
txCount: addr.txCount,
|
||||||
balance: addr.balance,
|
balance: addr.balance,
|
||||||
isChange: addr.isHidden))
|
isChange: addr.isHidden))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async {
|
||||||
|
final electrumWallet = wallet as ElectrumWallet;
|
||||||
|
final sk = ECPrivate.random();
|
||||||
|
|
||||||
|
final p2shAddr = sk.getPublic().toP2pkhInP2sh();
|
||||||
|
final p2wpkhAddr = sk.getPublic().toP2wpkhAddress();
|
||||||
|
try {
|
||||||
|
final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse(
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
// Deposit address + change address
|
||||||
|
[p2shAddr, p2wpkhAddr],
|
||||||
|
[
|
||||||
|
BitcoinOutput(address: p2shAddr, value: BigInt.zero),
|
||||||
|
BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero)
|
||||||
|
],
|
||||||
|
null,
|
||||||
|
priority as BitcoinTransactionPriority);
|
||||||
|
|
||||||
|
return estimatedTx.amount;
|
||||||
|
} catch (_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getAddress(Object wallet) {
|
String getAddress(Object wallet) {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
|
|
|
@ -81,7 +81,7 @@ class MoonPaySellProvider extends BuyProvider {
|
||||||
'',
|
'',
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'apiKey': _apiKey,
|
'apiKey': _apiKey,
|
||||||
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
|
'defaultBaseCurrencyCode': _normalizeCurrency(currency),
|
||||||
'refundWalletAddress': refundWalletAddress,
|
'refundWalletAddress': refundWalletAddress,
|
||||||
}..addAll(customParams),
|
}..addAll(customParams),
|
||||||
);
|
);
|
||||||
|
@ -134,6 +134,14 @@ class MoonPaySellProvider extends BuyProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _normalizeCurrency(CryptoCurrency currency) {
|
||||||
|
if (currency == CryptoCurrency.maticpoly) {
|
||||||
|
return "MATIC_POLYGON";
|
||||||
|
}
|
||||||
|
|
||||||
|
return currency.toString().toLowerCase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoonPayBuyProvider extends BuyProvider {
|
class MoonPayBuyProvider extends BuyProvider {
|
||||||
|
|
|
@ -274,7 +274,7 @@ class AddressValidator extends TextValidator {
|
||||||
'|([^0-9a-zA-Z]|^)([23][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2shAddress type
|
'|([^0-9a-zA-Z]|^)([23][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2shAddress type
|
||||||
'|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{25,39})([^0-9a-zA-Z]|\$)' //P2wpkhAddress type
|
'|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{25,39})([^0-9a-zA-Z]|\$)' //P2wpkhAddress type
|
||||||
'|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{40,80})([^0-9a-zA-Z]|\$)' //P2wshAddress type
|
'|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{40,80})([^0-9a-zA-Z]|\$)' //P2wshAddress type
|
||||||
'|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)'; //P2trAddress type
|
'|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)'; //P2trAddress type
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
|
return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
|
||||||
'|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
|
'|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
|
||||||
|
|
|
@ -89,7 +89,12 @@ class ProvidersHelper {
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return [ProviderType.askEachTime, ProviderType.moonpaySell];
|
return [ProviderType.askEachTime, ProviderType.moonpaySell];
|
||||||
case WalletType.polygon:
|
case WalletType.polygon:
|
||||||
return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx];
|
return [
|
||||||
|
ProviderType.askEachTime,
|
||||||
|
ProviderType.onramper,
|
||||||
|
ProviderType.moonpaySell,
|
||||||
|
ProviderType.dfx,
|
||||||
|
];
|
||||||
case WalletType.solana:
|
case WalletType.solana:
|
||||||
return [
|
return [
|
||||||
ProviderType.askEachTime,
|
ProviderType.askEachTime,
|
||||||
|
|
|
@ -384,7 +384,7 @@ class ExchangePage extends BasePage {
|
||||||
(CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey));
|
(CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey));
|
||||||
|
|
||||||
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
|
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
|
||||||
if (depositKey.currentState!.amountController.text != amount) {
|
if (depositKey.currentState!.amountController.text != amount && amount != S.of(context).all) {
|
||||||
depositKey.currentState!.amountController.text = amount;
|
depositKey.currentState!.amountController.text = amount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -467,7 +467,9 @@ class ExchangePage extends BasePage {
|
||||||
.addListener(() => exchangeViewModel.depositAddress = depositAddressController.text);
|
.addListener(() => exchangeViewModel.depositAddress = depositAddressController.text);
|
||||||
|
|
||||||
depositAmountController.addListener(() {
|
depositAmountController.addListener(() {
|
||||||
if (depositAmountController.text != exchangeViewModel.depositAmount) {
|
if (depositAmountController.text != exchangeViewModel.depositAmount &&
|
||||||
|
depositAmountController.text != S.of(context).all) {
|
||||||
|
exchangeViewModel.isSendAllEnabled = false;
|
||||||
_depositAmountDebounce.run(() {
|
_depositAmountDebounce.run(() {
|
||||||
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
|
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
|
||||||
exchangeViewModel.isReceiveAmountEntered = false;
|
exchangeViewModel.isReceiveAmountEntered = false;
|
||||||
|
@ -589,8 +591,9 @@ class ExchangePage extends BasePage {
|
||||||
onDispose: disposeBestRateSync,
|
onDispose: disposeBestRateSync,
|
||||||
hasAllAmount: exchangeViewModel.hasAllAmount,
|
hasAllAmount: exchangeViewModel.hasAllAmount,
|
||||||
allAmount: exchangeViewModel.hasAllAmount
|
allAmount: exchangeViewModel.hasAllAmount
|
||||||
? () => exchangeViewModel.calculateDepositAllAmount()
|
? () => exchangeViewModel.enableSendAllAmount()
|
||||||
: null,
|
: null,
|
||||||
|
isAllAmountEnabled: exchangeViewModel.isSendAllEnabled,
|
||||||
amountFocusNode: _depositAmountFocus,
|
amountFocusNode: _depositAmountFocus,
|
||||||
addressFocusNode: _depositAddressFocus,
|
addressFocusNode: _depositAddressFocus,
|
||||||
key: depositKey,
|
key: depositKey,
|
||||||
|
@ -626,10 +629,12 @@ class ExchangePage extends BasePage {
|
||||||
},
|
},
|
||||||
imageArrow: arrowBottomPurple,
|
imageArrow: arrowBottomPurple,
|
||||||
currencyButtonColor: Colors.transparent,
|
currencyButtonColor: Colors.transparent,
|
||||||
addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
addressButtonsColor:
|
||||||
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor,
|
Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
||||||
|
borderColor:
|
||||||
|
Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor,
|
||||||
currencyValueValidator: (value) {
|
currencyValueValidator: (value) {
|
||||||
return !exchangeViewModel.isFixedRateMode
|
return !exchangeViewModel.isFixedRateMode && value != S.of(context).all
|
||||||
? AmountValidator(
|
? AmountValidator(
|
||||||
isAutovalidate: true,
|
isAutovalidate: true,
|
||||||
currency: exchangeViewModel.depositCurrency,
|
currency: exchangeViewModel.depositCurrency,
|
||||||
|
@ -673,8 +678,10 @@ class ExchangePage extends BasePage {
|
||||||
exchangeViewModel.changeReceiveCurrency(currency: currency),
|
exchangeViewModel.changeReceiveCurrency(currency: currency),
|
||||||
imageArrow: arrowBottomCakeGreen,
|
imageArrow: arrowBottomCakeGreen,
|
||||||
currencyButtonColor: Colors.transparent,
|
currencyButtonColor: Colors.transparent,
|
||||||
addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
addressButtonsColor:
|
||||||
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
|
Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
||||||
|
borderColor:
|
||||||
|
Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
|
||||||
currencyValueValidator: (value) {
|
currencyValueValidator: (value) {
|
||||||
return exchangeViewModel.isFixedRateMode
|
return exchangeViewModel.isFixedRateMode
|
||||||
? AmountValidator(
|
? AmountValidator(
|
||||||
|
|
|
@ -56,17 +56,14 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
height: 8,
|
height: 8,
|
||||||
);
|
);
|
||||||
|
|
||||||
final depositWalletName =
|
final depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr
|
||||||
exchangeViewModel.depositCurrency == CryptoCurrency.xmr
|
|
||||||
? exchangeViewModel.wallet.name
|
? exchangeViewModel.wallet.name
|
||||||
: null;
|
: null;
|
||||||
final receiveWalletName =
|
final receiveWalletName = exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
|
||||||
exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
|
|
||||||
? exchangeViewModel.wallet.name
|
? exchangeViewModel.wallet.name
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
WidgetsBinding.instance
|
WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
|
||||||
.addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
|
|
||||||
|
|
||||||
return KeyboardActions(
|
return KeyboardActions(
|
||||||
disableScroll: true,
|
disableScroll: true,
|
||||||
|
@ -76,128 +73,125 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
nextFocus: false,
|
nextFocus: false,
|
||||||
actions: [
|
actions: [
|
||||||
KeyboardActionsItem(
|
KeyboardActionsItem(
|
||||||
focusNode: _depositAmountFocus,
|
focusNode: _depositAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]),
|
||||||
toolbarButtons: [(_) => KeyboardDoneButton()]),
|
|
||||||
KeyboardActionsItem(
|
KeyboardActionsItem(
|
||||||
focusNode: _receiveAmountFocus,
|
focusNode: _receiveAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()])
|
||||||
toolbarButtons: [(_) => KeyboardDoneButton()])
|
|
||||||
]),
|
]),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Theme.of(context).colorScheme.background,
|
color: Theme.of(context).colorScheme.background,
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: ScrollableWithBottomSection(
|
child: ScrollableWithBottomSection(
|
||||||
contentPadding: EdgeInsets.only(bottom: 24),
|
contentPadding: EdgeInsets.only(bottom: 24),
|
||||||
content: Container(
|
content: Container(
|
||||||
padding: EdgeInsets.only(bottom: 32),
|
padding: EdgeInsets.only(bottom: 32),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(24),
|
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
||||||
bottomRight: Radius.circular(24)
|
gradient: LinearGradient(colors: [
|
||||||
),
|
Theme.of(context)
|
||||||
gradient: LinearGradient(
|
.extension<ExchangePageTheme>()!
|
||||||
colors: [
|
.firstGradientBottomPanelColor,
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor,
|
Theme.of(context)
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientBottomPanelColor,
|
.extension<ExchangePageTheme>()!
|
||||||
],
|
.secondGradientBottomPanelColor,
|
||||||
stops: [0.35, 1.0],
|
], stops: [
|
||||||
begin: Alignment.topLeft,
|
0.35,
|
||||||
end: Alignment.bottomRight),
|
1.0
|
||||||
),
|
], begin: Alignment.topLeft, end: Alignment.bottomRight),
|
||||||
child: FocusTraversalGroup(
|
),
|
||||||
policy: OrderedTraversalPolicy(),
|
child: FocusTraversalGroup(
|
||||||
child: Column(
|
policy: OrderedTraversalPolicy(),
|
||||||
children: <Widget>[
|
child: Column(
|
||||||
Container(
|
children: <Widget>[
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
borderRadius: BorderRadius.only(
|
decoration: BoxDecoration(
|
||||||
bottomLeft: Radius.circular(24),
|
borderRadius: BorderRadius.only(
|
||||||
bottomRight: Radius.circular(24)
|
bottomLeft: Radius.circular(24),
|
||||||
|
bottomRight: Radius.circular(24)),
|
||||||
|
gradient: LinearGradient(colors: [
|
||||||
|
Theme.of(context)
|
||||||
|
.extension<ExchangePageTheme>()!
|
||||||
|
.firstGradientTopPanelColor,
|
||||||
|
Theme.of(context)
|
||||||
|
.extension<ExchangePageTheme>()!
|
||||||
|
.secondGradientTopPanelColor,
|
||||||
|
], begin: Alignment.topLeft, end: Alignment.bottomRight),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
|
||||||
|
child: Observer(
|
||||||
|
builder: (_) => ExchangeCard(
|
||||||
|
amountFocusNode: _depositAmountFocus,
|
||||||
|
key: depositKey,
|
||||||
|
title: S.of(context).you_will_send,
|
||||||
|
initialCurrency: exchangeViewModel.depositCurrency,
|
||||||
|
initialWalletName: depositWalletName ?? '',
|
||||||
|
initialAddress: exchangeViewModel.depositCurrency ==
|
||||||
|
exchangeViewModel.wallet.currency
|
||||||
|
? exchangeViewModel.wallet.walletAddresses.address
|
||||||
|
: exchangeViewModel.depositAddress,
|
||||||
|
initialIsAmountEditable: true,
|
||||||
|
initialIsAddressEditable: exchangeViewModel.isDepositAddressEnabled,
|
||||||
|
isAmountEstimated: false,
|
||||||
|
hasRefundAddress: true,
|
||||||
|
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||||
|
currencies: CryptoCurrency.all,
|
||||||
|
onCurrencySelected: (currency) =>
|
||||||
|
exchangeViewModel.changeDepositCurrency(currency: currency),
|
||||||
|
imageArrow: arrowBottomPurple,
|
||||||
|
currencyButtonColor: Colors.transparent,
|
||||||
|
addressButtonsColor: Theme.of(context)
|
||||||
|
.extension<ExchangePageTheme>()!
|
||||||
|
.textFieldButtonColor,
|
||||||
|
borderColor: Theme.of(context)
|
||||||
|
.extension<ExchangePageTheme>()!
|
||||||
|
.textFieldBorderBottomPanelColor,
|
||||||
|
currencyValueValidator:
|
||||||
|
AmountValidator(currency: exchangeViewModel.depositCurrency),
|
||||||
|
//addressTextFieldValidator: AddressValidator(
|
||||||
|
// type: exchangeViewModel.depositCurrency),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
gradient: LinearGradient(
|
Padding(
|
||||||
colors: [
|
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor,
|
child: Observer(
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor,
|
builder: (_) => ExchangeCard(
|
||||||
],
|
amountFocusNode: _receiveAmountFocus,
|
||||||
begin: Alignment.topLeft,
|
key: receiveKey,
|
||||||
end: Alignment.bottomRight),
|
title: S.of(context).you_will_get,
|
||||||
),
|
initialCurrency: exchangeViewModel.receiveCurrency,
|
||||||
padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
|
initialWalletName: receiveWalletName ?? '',
|
||||||
child: Observer(
|
initialAddress: exchangeViewModel.receiveCurrency ==
|
||||||
builder: (_) => ExchangeCard(
|
exchangeViewModel.wallet.currency
|
||||||
amountFocusNode: _depositAmountFocus,
|
? exchangeViewModel.wallet.walletAddresses.address
|
||||||
key: depositKey,
|
: exchangeViewModel.receiveAddress,
|
||||||
title: S.of(context).you_will_send,
|
initialIsAmountEditable: false,
|
||||||
initialCurrency:
|
isAmountEstimated: true,
|
||||||
exchangeViewModel.depositCurrency,
|
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
||||||
initialWalletName: depositWalletName ?? '',
|
currencies: exchangeViewModel.receiveCurrencies,
|
||||||
initialAddress: exchangeViewModel
|
onCurrencySelected: (currency) => exchangeViewModel
|
||||||
.depositCurrency ==
|
.changeReceiveCurrency(currency: currency),
|
||||||
exchangeViewModel.wallet.currency
|
imageArrow: arrowBottomCakeGreen,
|
||||||
? exchangeViewModel.wallet.walletAddresses.address
|
currencyButtonColor: Colors.transparent,
|
||||||
: exchangeViewModel.depositAddress,
|
addressButtonsColor: Theme.of(context)
|
||||||
initialIsAmountEditable: true,
|
.extension<ExchangePageTheme>()!
|
||||||
initialIsAddressEditable: exchangeViewModel
|
.textFieldButtonColor,
|
||||||
.isDepositAddressEnabled,
|
borderColor: Theme.of(context)
|
||||||
isAmountEstimated: false,
|
.extension<ExchangePageTheme>()!
|
||||||
hasRefundAddress: true,
|
.textFieldBorderBottomPanelColor,
|
||||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
currencyValueValidator: AmountValidator(
|
||||||
currencies: CryptoCurrency.all,
|
currency: exchangeViewModel.receiveCurrency),
|
||||||
onCurrencySelected: (currency) =>
|
//addressTextFieldValidator: AddressValidator(
|
||||||
exchangeViewModel.changeDepositCurrency(
|
// type: exchangeViewModel.receiveCurrency),
|
||||||
currency: currency),
|
)),
|
||||||
imageArrow: arrowBottomPurple,
|
)
|
||||||
currencyButtonColor: Colors.transparent,
|
],
|
||||||
addressButtonsColor:
|
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor,
|
|
||||||
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
|
|
||||||
currencyValueValidator: AmountValidator(
|
|
||||||
currency: exchangeViewModel.depositCurrency),
|
|
||||||
//addressTextFieldValidator: AddressValidator(
|
|
||||||
// type: exchangeViewModel.depositCurrency),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
|
||||||
child: Observer(
|
|
||||||
builder: (_) => ExchangeCard(
|
|
||||||
amountFocusNode: _receiveAmountFocus,
|
|
||||||
key: receiveKey,
|
|
||||||
title: S.of(context).you_will_get,
|
|
||||||
initialCurrency:
|
|
||||||
exchangeViewModel.receiveCurrency,
|
|
||||||
initialWalletName: receiveWalletName ?? '',
|
|
||||||
initialAddress:
|
|
||||||
exchangeViewModel.receiveCurrency ==
|
|
||||||
exchangeViewModel.wallet.currency
|
|
||||||
? exchangeViewModel.wallet.walletAddresses.address
|
|
||||||
: exchangeViewModel.receiveAddress,
|
|
||||||
initialIsAmountEditable: false,
|
|
||||||
isAmountEstimated: true,
|
|
||||||
isMoneroWallet: exchangeViewModel.isMoneroWallet,
|
|
||||||
currencies: exchangeViewModel.receiveCurrencies,
|
|
||||||
onCurrencySelected: (currency) =>
|
|
||||||
exchangeViewModel.changeReceiveCurrency(
|
|
||||||
currency: currency),
|
|
||||||
imageArrow: arrowBottomCakeGreen,
|
|
||||||
currencyButtonColor: Colors.transparent,
|
|
||||||
addressButtonsColor:
|
|
||||||
Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor,
|
|
||||||
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
|
|
||||||
currencyValueValidator: AmountValidator(
|
|
||||||
currency: exchangeViewModel.receiveCurrency),
|
|
||||||
//addressTextFieldValidator: AddressValidator(
|
|
||||||
// type: exchangeViewModel.receiveCurrency),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||||
),
|
bottomSection: Column(children: <Widget>[
|
||||||
bottomSectionPadding:
|
|
||||||
EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
|
||||||
bottomSection: Column(children: <Widget>[
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(bottom: 15),
|
padding: EdgeInsets.only(bottom: 15),
|
||||||
child: Observer(
|
child: Observer(
|
||||||
|
@ -217,36 +211,31 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState != null && _formKey.currentState!.validate()) {
|
if (_formKey.currentState != null && _formKey.currentState!.validate()) {
|
||||||
exchangeViewModel.addTemplate(
|
exchangeViewModel.addTemplate(
|
||||||
amount: exchangeViewModel.depositAmount,
|
amount: exchangeViewModel.depositAmount,
|
||||||
depositCurrency:
|
depositCurrency: exchangeViewModel.depositCurrency.name,
|
||||||
exchangeViewModel.depositCurrency.name,
|
depositCurrencyTitle: exchangeViewModel.depositCurrency.title +
|
||||||
depositCurrencyTitle: exchangeViewModel
|
' ${exchangeViewModel.depositCurrency.tag ?? ''}',
|
||||||
.depositCurrency.title + ' ${exchangeViewModel.depositCurrency.tag ?? ''}',
|
receiveCurrency: exchangeViewModel.receiveCurrency.name,
|
||||||
receiveCurrency:
|
receiveCurrencyTitle: exchangeViewModel.receiveCurrency.title +
|
||||||
exchangeViewModel.receiveCurrency.name,
|
' ${exchangeViewModel.receiveCurrency.tag ?? ''}',
|
||||||
receiveCurrencyTitle: exchangeViewModel
|
provider: exchangeViewModel.provider.toString(),
|
||||||
.receiveCurrency.title + ' ${exchangeViewModel.receiveCurrency.tag ?? ''}',
|
depositAddress: exchangeViewModel.depositAddress,
|
||||||
provider: exchangeViewModel.provider.toString(),
|
receiveAddress: exchangeViewModel.receiveAddress);
|
||||||
depositAddress: exchangeViewModel.depositAddress,
|
exchangeViewModel.updateTemplate();
|
||||||
receiveAddress: exchangeViewModel.receiveAddress);
|
Navigator.of(context).pop();
|
||||||
exchangeViewModel.updateTemplate();
|
}
|
||||||
Navigator.of(context).pop();
|
},
|
||||||
}
|
text: S.of(context).save,
|
||||||
},
|
color: Theme.of(context).primaryColor,
|
||||||
text: S.of(context).save,
|
textColor: Colors.white),
|
||||||
color: Theme.of(context).primaryColor,
|
]),
|
||||||
textColor: Colors.white),
|
))));
|
||||||
]),
|
|
||||||
))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setReactions(
|
void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) {
|
||||||
BuildContext context, ExchangeViewModel exchangeViewModel) {
|
|
||||||
if (_isReactionsSet) {
|
if (_isReactionsSet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -272,33 +261,27 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
// key.currentState.changeLimits(min: min, max: max);
|
// key.currentState.changeLimits(min: min, max: max);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
_onCurrencyChange(
|
_onCurrencyChange(exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
|
||||||
exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
|
_onCurrencyChange(exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
|
||||||
_onCurrencyChange(
|
|
||||||
exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
|
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
(_) => exchangeViewModel.wallet.name,
|
(_) => exchangeViewModel.wallet.name,
|
||||||
(String _) => _onWalletNameChange(
|
(String _) =>
|
||||||
exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
|
_onWalletNameChange(exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
(_) => exchangeViewModel.wallet.name,
|
(_) => exchangeViewModel.wallet.name,
|
||||||
(String _) => _onWalletNameChange(
|
(String _) =>
|
||||||
exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
|
_onWalletNameChange(exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
|
||||||
|
|
||||||
reaction(
|
reaction((_) => exchangeViewModel.receiveCurrency,
|
||||||
(_) => exchangeViewModel.receiveCurrency,
|
(CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, receiveKey));
|
||||||
(CryptoCurrency currency) =>
|
|
||||||
_onCurrencyChange(currency, exchangeViewModel, receiveKey));
|
|
||||||
|
|
||||||
reaction(
|
reaction((_) => exchangeViewModel.depositCurrency,
|
||||||
(_) => exchangeViewModel.depositCurrency,
|
(CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey));
|
||||||
(CryptoCurrency currency) =>
|
|
||||||
_onCurrencyChange(currency, exchangeViewModel, depositKey));
|
|
||||||
|
|
||||||
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
|
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
|
||||||
if (depositKey.currentState!.amountController.text != amount) {
|
if (depositKey.currentState!.amountController.text != amount && amount != S.of(context).all) {
|
||||||
depositKey.currentState!.amountController.text = amount;
|
depositKey.currentState!.amountController.text = amount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -309,10 +292,9 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
reaction((_) => exchangeViewModel.isDepositAddressEnabled,
|
reaction((_) => exchangeViewModel.isDepositAddressEnabled, (bool isEnabled) {
|
||||||
(bool isEnabled) {
|
depositKey.currentState!.isAddressEditable(isEditable: isEnabled);
|
||||||
depositKey.currentState!.isAddressEditable(isEditable: isEnabled);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
|
reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
|
||||||
if (receiveKey.currentState!.amountController.text != amount) {
|
if (receiveKey.currentState!.amountController.text != amount) {
|
||||||
|
@ -353,30 +335,28 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
receiveKey.currentState.changeLimits(min: null, max: null);
|
receiveKey.currentState.changeLimits(min: null, max: null);
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
depositAddressController.addListener(
|
depositAddressController
|
||||||
() => exchangeViewModel.depositAddress = depositAddressController.text);
|
.addListener(() => exchangeViewModel.depositAddress = depositAddressController.text);
|
||||||
|
|
||||||
depositAmountController.addListener(() {
|
depositAmountController.addListener(() {
|
||||||
if (depositAmountController.text != exchangeViewModel.depositAmount) {
|
if (depositAmountController.text != exchangeViewModel.depositAmount &&
|
||||||
exchangeViewModel.changeDepositAmount(
|
exchangeViewModel.depositAmount != S.of(context).all) {
|
||||||
amount: depositAmountController.text);
|
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
|
||||||
exchangeViewModel.isReceiveAmountEntered = false;
|
exchangeViewModel.isReceiveAmountEntered = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
receiveAddressController.addListener(
|
receiveAddressController
|
||||||
() => exchangeViewModel.receiveAddress = receiveAddressController.text);
|
.addListener(() => exchangeViewModel.receiveAddress = receiveAddressController.text);
|
||||||
|
|
||||||
receiveAmountController.addListener(() {
|
receiveAmountController.addListener(() {
|
||||||
if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
|
if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
|
||||||
exchangeViewModel.changeReceiveAmount(
|
exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
|
||||||
amount: receiveAmountController.text);
|
|
||||||
exchangeViewModel.isReceiveAmountEntered = true;
|
exchangeViewModel.isReceiveAmountEntered = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
reaction((_) => exchangeViewModel.wallet.walletAddresses.address,
|
reaction((_) => exchangeViewModel.wallet.walletAddresses.address, (String address) {
|
||||||
(String address) {
|
|
||||||
if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
|
if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
|
||||||
depositKey.currentState!.changeAddress(address: address);
|
depositKey.currentState!.changeAddress(address: address);
|
||||||
}
|
}
|
||||||
|
@ -389,29 +369,26 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
_isReactionsSet = true;
|
_isReactionsSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onCurrencyChange(CryptoCurrency currency,
|
void _onCurrencyChange(CryptoCurrency currency, ExchangeViewModel exchangeViewModel,
|
||||||
ExchangeViewModel exchangeViewModel, GlobalKey<ExchangeCardState> key) {
|
GlobalKey<ExchangeCardState> key) {
|
||||||
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
||||||
|
|
||||||
key.currentState!.changeSelectedCurrency(currency);
|
key.currentState!.changeSelectedCurrency(currency);
|
||||||
key.currentState!.changeWalletName(
|
key.currentState!.changeWalletName(isCurrentTypeWallet ? exchangeViewModel.wallet.name : '');
|
||||||
isCurrentTypeWallet ? exchangeViewModel.wallet.name : '');
|
|
||||||
|
|
||||||
key.currentState!.changeAddress(
|
key.currentState!.changeAddress(
|
||||||
address: isCurrentTypeWallet
|
address: isCurrentTypeWallet ? exchangeViewModel.wallet.walletAddresses.address : '');
|
||||||
? exchangeViewModel.wallet.walletAddresses.address : '');
|
|
||||||
|
|
||||||
key.currentState!.changeAmount(amount: '');
|
key.currentState!.changeAmount(amount: '');
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onWalletNameChange(ExchangeViewModel exchangeViewModel,
|
void _onWalletNameChange(ExchangeViewModel exchangeViewModel, CryptoCurrency currency,
|
||||||
CryptoCurrency currency, GlobalKey<ExchangeCardState> key) {
|
GlobalKey<ExchangeCardState> key) {
|
||||||
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
||||||
|
|
||||||
if (isCurrentTypeWallet) {
|
if (isCurrentTypeWallet) {
|
||||||
key.currentState!.changeWalletName(exchangeViewModel.wallet.name);
|
key.currentState!.changeWalletName(exchangeViewModel.wallet.name);
|
||||||
key.currentState!.addressController.text =
|
key.currentState!.addressController.text = exchangeViewModel.wallet.walletAddresses.address;
|
||||||
exchangeViewModel.wallet.walletAddresses.address;
|
|
||||||
} else if (key.currentState!.addressController.text ==
|
} else if (key.currentState!.addressController.text ==
|
||||||
exchangeViewModel.wallet.walletAddresses.address) {
|
exchangeViewModel.wallet.walletAddresses.address) {
|
||||||
key.currentState!.changeWalletName('');
|
key.currentState!.changeWalletName('');
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/core/amount_validator.dart';
|
||||||
import 'package:cake_wallet/entities/contact_base.dart';
|
import 'package:cake_wallet/entities/contact_base.dart';
|
||||||
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
|
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -37,6 +38,7 @@ class ExchangeCard extends StatefulWidget {
|
||||||
this.addressButtonsColor = Colors.transparent,
|
this.addressButtonsColor = Colors.transparent,
|
||||||
this.borderColor = Colors.transparent,
|
this.borderColor = Colors.transparent,
|
||||||
this.hasAllAmount = false,
|
this.hasAllAmount = false,
|
||||||
|
this.isAllAmountEnabled = false,
|
||||||
this.amountFocusNode,
|
this.amountFocusNode,
|
||||||
this.addressFocusNode,
|
this.addressFocusNode,
|
||||||
this.allAmount,
|
this.allAmount,
|
||||||
|
@ -62,9 +64,11 @@ class ExchangeCard extends StatefulWidget {
|
||||||
final Color borderColor;
|
final Color borderColor;
|
||||||
final FormFieldValidator<String>? currencyValueValidator;
|
final FormFieldValidator<String>? currencyValueValidator;
|
||||||
final FormFieldValidator<String>? addressTextFieldValidator;
|
final FormFieldValidator<String>? addressTextFieldValidator;
|
||||||
|
final FormFieldValidator<String> allAmountValidator = AllAmountValidator();
|
||||||
final FocusNode? amountFocusNode;
|
final FocusNode? amountFocusNode;
|
||||||
final FocusNode? addressFocusNode;
|
final FocusNode? addressFocusNode;
|
||||||
final bool hasAllAmount;
|
final bool hasAllAmount;
|
||||||
|
final bool isAllAmountEnabled;
|
||||||
final VoidCallback? allAmount;
|
final VoidCallback? allAmount;
|
||||||
final void Function(BuildContext context)? onPushPasteButton;
|
final void Function(BuildContext context)? onPushPasteButton;
|
||||||
final void Function(BuildContext context)? onPushAddressBookButton;
|
final void Function(BuildContext context)? onPushAddressBookButton;
|
||||||
|
@ -76,15 +80,15 @@ class ExchangeCard extends StatefulWidget {
|
||||||
|
|
||||||
class ExchangeCardState extends State<ExchangeCard> {
|
class ExchangeCardState extends State<ExchangeCard> {
|
||||||
ExchangeCardState()
|
ExchangeCardState()
|
||||||
: _title = '',
|
: _title = '',
|
||||||
_min = '',
|
_min = '',
|
||||||
_max = '',
|
_max = '',
|
||||||
_isAmountEditable = false,
|
_isAmountEditable = false,
|
||||||
_isAddressEditable = false,
|
_isAddressEditable = false,
|
||||||
_walletName = '',
|
_walletName = '',
|
||||||
_selectedCurrency = CryptoCurrency.btc,
|
_selectedCurrency = CryptoCurrency.btc,
|
||||||
_isAmountEstimated = false,
|
_isAmountEstimated = false,
|
||||||
_isMoneroWallet = false;
|
_isMoneroWallet = false;
|
||||||
|
|
||||||
final addressController = TextEditingController();
|
final addressController = TextEditingController();
|
||||||
final amountController = TextEditingController();
|
final amountController = TextEditingController();
|
||||||
|
@ -160,6 +164,12 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
if (widget.isAllAmountEnabled) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
amountController.text = S.of(context).all;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final copyImage = Image.asset('assets/images/copy_content.png',
|
final copyImage = Image.asset('assets/images/copy_content.png',
|
||||||
height: 16,
|
height: 16,
|
||||||
width: 16,
|
width: 16,
|
||||||
|
@ -168,8 +178,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: <
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
|
||||||
Widget>[
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -202,40 +211,38 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
),
|
),
|
||||||
Text(_selectedCurrency.toString(),
|
Text(_selectedCurrency.toString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white))
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.white))
|
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_selectedCurrency.tag != null ? Padding(
|
if (_selectedCurrency.tag != null)
|
||||||
padding: const EdgeInsets.only(right:3.0),
|
Padding(
|
||||||
child: Container(
|
padding: const EdgeInsets.only(right: 3.0),
|
||||||
height: 32,
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
height: 32,
|
||||||
color: widget.addressButtonsColor ??
|
decoration: BoxDecoration(
|
||||||
Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
color: widget.addressButtonsColor ??
|
||||||
borderRadius:
|
Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
||||||
BorderRadius.all(Radius.circular(6))),
|
borderRadius: BorderRadius.all(Radius.circular(6))),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(6.0),
|
padding: const EdgeInsets.all(6.0),
|
||||||
child: Text(_selectedCurrency.tag!,
|
child: Text(_selectedCurrency.tag!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)),
|
color: Theme.of(context)
|
||||||
|
.extension<SendPageTheme>()!
|
||||||
|
.textFieldButtonIconColor)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
) : Container(),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 4.0),
|
padding: const EdgeInsets.only(right: 4.0),
|
||||||
child: Text(':',
|
child: Text(':',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white)),
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.white)),
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -249,26 +256,25 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
controller: amountController,
|
controller: amountController,
|
||||||
enabled: _isAmountEditable,
|
enabled: _isAmountEditable,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
keyboardType: TextInputType.numberWithOptions(
|
keyboardType:
|
||||||
signed: false, decimal: true),
|
TextInputType.numberWithOptions(signed: false, decimal: true),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.deny(
|
FilteringTextInputFormatter.deny(RegExp('[\\-|\\ ]'))
|
||||||
RegExp('[\\-|\\ ]'))
|
|
||||||
],
|
],
|
||||||
hintText: '0.0000',
|
hintText: '0.0000',
|
||||||
borderColor: Colors.transparent,
|
borderColor: Colors.transparent,
|
||||||
//widget.borderColor,
|
//widget.borderColor,
|
||||||
textStyle: TextStyle(
|
textStyle: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.white),
|
|
||||||
placeholderTextStyle: TextStyle(
|
placeholderTextStyle: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
|
color: Theme.of(context)
|
||||||
|
.extension<ExchangePageTheme>()!
|
||||||
|
.hintTextColor),
|
||||||
validator: _isAmountEditable
|
validator: _isAmountEditable
|
||||||
? widget.currencyValueValidator
|
? widget.currencyValueValidator
|
||||||
: null),
|
: null),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.hasAllAmount)
|
if (widget.hasAllAmount)
|
||||||
|
@ -276,9 +282,10 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
height: 32,
|
height: 32,
|
||||||
width: 32,
|
width: 32,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
color: Theme.of(context)
|
||||||
borderRadius:
|
.extension<SendPageTheme>()!
|
||||||
BorderRadius.all(Radius.circular(6))),
|
.textFieldButtonColor,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6))),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => widget.allAmount?.call(),
|
onTap: () => widget.allAmount?.call(),
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -287,7 +294,9 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)),
|
color: Theme.of(context)
|
||||||
|
.extension<SendPageTheme>()!
|
||||||
|
.textFieldButtonIconColor)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -296,39 +305,30 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
Divider(
|
Divider(height: 1, color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
||||||
height: 1,
|
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 5),
|
padding: EdgeInsets.only(top: 5),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 15,
|
height: 15,
|
||||||
child: Row(
|
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
_min != null
|
||||||
children: <Widget>[
|
? Text(
|
||||||
_min != null
|
S.of(context).min_value(_min ?? '', _selectedCurrency.toString()),
|
||||||
? Text(
|
style: TextStyle(
|
||||||
S
|
fontSize: 10,
|
||||||
.of(context)
|
height: 1.2,
|
||||||
.min_value(_min ?? '', _selectedCurrency.toString()),
|
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
|
||||||
style: TextStyle(
|
)
|
||||||
fontSize: 10,
|
: Offstage(),
|
||||||
height: 1.2,
|
_min != null ? SizedBox(width: 10) : Offstage(),
|
||||||
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
|
_max != null
|
||||||
)
|
? Text(S.of(context).max_value(_max ?? '', _selectedCurrency.toString()),
|
||||||
: Offstage(),
|
style: TextStyle(
|
||||||
_min != null ? SizedBox(width: 10) : Offstage(),
|
fontSize: 10,
|
||||||
_max != null
|
height: 1.2,
|
||||||
? Text(
|
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor))
|
||||||
S
|
: Offstage(),
|
||||||
.of(context)
|
])),
|
||||||
.max_value(_max ?? '', _selectedCurrency.toString()),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
height: 1.2,
|
|
||||||
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor))
|
|
||||||
: Offstage(),
|
|
||||||
])),
|
|
||||||
),
|
),
|
||||||
!_isAddressEditable && widget.hasRefundAddress
|
!_isAddressEditable && widget.hasRefundAddress
|
||||||
? Padding(
|
? Padding(
|
||||||
|
@ -343,7 +343,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
: Offstage(),
|
: Offstage(),
|
||||||
_isAddressEditable
|
_isAddressEditable
|
||||||
? FocusTraversalOrder(
|
? FocusTraversalOrder(
|
||||||
order: NumericFocusOrder(2),
|
order: NumericFocusOrder(2),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: 20),
|
padding: EdgeInsets.only(top: 20),
|
||||||
child: AddressTextField(
|
child: AddressTextField(
|
||||||
|
@ -352,27 +352,23 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
onURIScanned: (uri) {
|
onURIScanned: (uri) {
|
||||||
final paymentRequest = PaymentRequest.fromUri(uri);
|
final paymentRequest = PaymentRequest.fromUri(uri);
|
||||||
addressController.text = paymentRequest.address;
|
addressController.text = paymentRequest.address;
|
||||||
|
|
||||||
if (amountController.text.isNotEmpty) {
|
if (amountController.text.isNotEmpty) {
|
||||||
_showAmountPopup(context, paymentRequest);
|
_showAmountPopup(context, paymentRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
widget.amountFocusNode?.requestFocus();
|
widget.amountFocusNode?.requestFocus();
|
||||||
amountController.text = paymentRequest.amount;
|
amountController.text = paymentRequest.amount;
|
||||||
},
|
},
|
||||||
placeholder: widget.hasRefundAddress
|
placeholder: widget.hasRefundAddress ? S.of(context).refund_address : null,
|
||||||
? S.of(context).refund_address
|
|
||||||
: null,
|
|
||||||
options: [
|
options: [
|
||||||
AddressTextFieldOption.paste,
|
AddressTextFieldOption.paste,
|
||||||
AddressTextFieldOption.qrCode,
|
AddressTextFieldOption.qrCode,
|
||||||
AddressTextFieldOption.addressBook,
|
AddressTextFieldOption.addressBook,
|
||||||
],
|
],
|
||||||
isBorderExist: false,
|
isBorderExist: false,
|
||||||
textStyle: TextStyle(
|
textStyle:
|
||||||
fontSize: 16,
|
TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.white),
|
|
||||||
hintStyle: TextStyle(
|
hintStyle: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
@ -381,27 +377,22 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
validator: widget.addressTextFieldValidator,
|
validator: widget.addressTextFieldValidator,
|
||||||
onPushPasteButton: widget.onPushPasteButton,
|
onPushPasteButton: widget.onPushPasteButton,
|
||||||
onPushAddressBookButton: widget.onPushAddressBookButton,
|
onPushAddressBookButton: widget.onPushAddressBookButton,
|
||||||
selectedCurrency: _selectedCurrency
|
selectedCurrency: _selectedCurrency),
|
||||||
),
|
|
||||||
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: EdgeInsets.only(top: 10),
|
padding: EdgeInsets.only(top: 10),
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) => Stack(children: <Widget>[
|
builder: (context) => Stack(children: <Widget>[
|
||||||
FocusTraversalOrder(
|
FocusTraversalOrder(
|
||||||
order: NumericFocusOrder(3),
|
order: NumericFocusOrder(3),
|
||||||
child: BaseTextFormField(
|
child: BaseTextFormField(
|
||||||
controller: addressController,
|
controller: addressController,
|
||||||
borderColor: Colors.transparent,
|
borderColor: Colors.transparent,
|
||||||
suffixIcon:
|
suffixIcon: SizedBox(width: _isMoneroWallet ? 80 : 36),
|
||||||
SizedBox(width: _isMoneroWallet ? 80 : 36),
|
textStyle: TextStyle(
|
||||||
textStyle: TextStyle(
|
fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
|
||||||
fontSize: 16,
|
validator: widget.addressTextFieldValidator),
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.white),
|
|
||||||
validator: widget.addressTextFieldValidator),
|
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 2,
|
top: 2,
|
||||||
|
@ -421,33 +412,28 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final contact =
|
final contact =
|
||||||
await Navigator.of(context)
|
await Navigator.of(context).pushNamed(
|
||||||
.pushNamed(
|
|
||||||
Routes.pickerAddressBook,
|
Routes.pickerAddressBook,
|
||||||
arguments: widget.initialCurrency,
|
arguments: widget.initialCurrency,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (contact is ContactBase &&
|
if (contact is ContactBase) {
|
||||||
contact.address != null) {
|
|
||||||
setState(() =>
|
setState(() =>
|
||||||
addressController.text =
|
addressController.text = contact.address);
|
||||||
contact.address);
|
widget.onPushAddressBookButton?.call(context);
|
||||||
widget.onPushAddressBookButton
|
|
||||||
?.call(context);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget
|
color: widget.addressButtonsColor,
|
||||||
.addressButtonsColor,
|
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.all(
|
BorderRadius.all(Radius.circular(6))),
|
||||||
Radius.circular(
|
|
||||||
6))),
|
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/open_book.png',
|
'assets/images/open_book.png',
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
|
color: Theme.of(context)
|
||||||
|
.extension<SendPageTheme>()!
|
||||||
|
.textFieldButtonIconColor,
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
@ -462,18 +448,13 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
label: S.of(context).copy_address,
|
label: S.of(context).copy_address,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Clipboard.setData(ClipboardData(
|
Clipboard.setData(
|
||||||
text: addressController
|
ClipboardData(text: addressController.text));
|
||||||
.text));
|
|
||||||
showBar<void>(
|
showBar<void>(
|
||||||
context,
|
context, S.of(context).copied_to_clipboard);
|
||||||
S
|
|
||||||
.of(context)
|
|
||||||
.copied_to_clipboard);
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(8, 8, 0, 8),
|
||||||
8, 8, 0, 8),
|
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: copyImage),
|
child: copyImage),
|
||||||
),
|
),
|
||||||
|
@ -514,7 +495,6 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
actionLeftButton: () => Navigator.of(dialogContext).pop());
|
actionLeftButton: () => Navigator.of(dialogContext).pop());
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
import 'package:cake_wallet/utils/payment_request.dart';
|
import 'package:cake_wallet/utils/payment_request.dart';
|
||||||
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||||
|
@ -12,6 +13,7 @@ import 'package:cake_wallet/store/app_store.dart';
|
||||||
import 'package:cake_wallet/store/authentication_store.dart';
|
import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
import 'package:cake_wallet/entities/qr_scanner.dart';
|
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:uni_links/uni_links.dart';
|
import 'package:uni_links/uni_links.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
||||||
|
|
||||||
|
@ -49,6 +51,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||||
bool _requestAuth;
|
bool _requestAuth;
|
||||||
|
|
||||||
StreamSubscription<Uri?>? stream;
|
StreamSubscription<Uri?>? stream;
|
||||||
|
ReactionDisposer? _walletReactionDisposer;
|
||||||
Uri? launchUri;
|
Uri? launchUri;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -72,6 +75,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
stream?.cancel();
|
stream?.cancel();
|
||||||
|
_walletReactionDisposer?.call();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,10 +173,20 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else if (_isValidPaymentUri()) {
|
} else if (_isValidPaymentUri()) {
|
||||||
widget.navigatorKey.currentState?.pushNamed(
|
if (widget.authenticationStore.state == AuthenticationState.uninitialized) {
|
||||||
Routes.send,
|
launchUri = null;
|
||||||
arguments: PaymentRequest.fromUri(launchUri),
|
} else {
|
||||||
);
|
if (widget.appStore.wallet == null) {
|
||||||
|
waitForWalletInstance(context, launchUri!);
|
||||||
|
launchUri = null;
|
||||||
|
} else {
|
||||||
|
widget.navigatorKey.currentState?.pushNamed(
|
||||||
|
Routes.send,
|
||||||
|
arguments: PaymentRequest.fromUri(launchUri),
|
||||||
|
);
|
||||||
|
launchUri = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
launchUri = null;
|
launchUri = null;
|
||||||
} else if (isWalletConnectLink) {
|
} else if (isWalletConnectLink) {
|
||||||
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
|
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
|
||||||
|
@ -233,4 +247,24 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waitForWalletInstance(BuildContext context, Uri tempLaunchUri) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (context.mounted) {
|
||||||
|
_walletReactionDisposer = reaction(
|
||||||
|
(_) => widget.appStore.wallet,
|
||||||
|
(WalletBase? wallet) {
|
||||||
|
if (wallet != null) {
|
||||||
|
widget.navigatorKey.currentState?.pushNamed(
|
||||||
|
Routes.send,
|
||||||
|
arguments: PaymentRequest.fromUri(tempLaunchUri),
|
||||||
|
);
|
||||||
|
_walletReactionDisposer?.call();
|
||||||
|
_walletReactionDisposer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/core/auth_service.dart';
|
import 'package:cake_wallet/core/auth_service.dart';
|
||||||
|
import 'package:cake_wallet/entities/contact_record.dart';
|
||||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
import 'package:cake_wallet/entities/template.dart';
|
import 'package:cake_wallet/entities/template.dart';
|
||||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||||
|
@ -48,6 +49,7 @@ class SendPage extends BasePage {
|
||||||
final PaymentRequest? initialPaymentRequest;
|
final PaymentRequest? initialPaymentRequest;
|
||||||
|
|
||||||
bool _effectsInstalled = false;
|
bool _effectsInstalled = false;
|
||||||
|
ContactRecord? newContactAddress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.send;
|
String get title => S.current.send;
|
||||||
|
@ -443,22 +445,50 @@ class SendPage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is TransactionCommitted) {
|
if (state is TransactionCommitted) {
|
||||||
String alertContent;
|
newContactAddress =
|
||||||
if (sendViewModel.walletType == WalletType.solana) {
|
newContactAddress ?? sendViewModel.newContactAddress();
|
||||||
alertContent =
|
|
||||||
'${S.of(_dialogContext).send_success(sendViewModel.selectedCryptoCurrency.toString())}. ${S.of(_dialogContext).waitFewSecondForTxUpdate}';
|
final successMessage = S.of(_dialogContext).send_success(
|
||||||
|
sendViewModel.selectedCryptoCurrency.toString());
|
||||||
|
|
||||||
|
final waitMessage = sendViewModel.walletType == WalletType.solana
|
||||||
|
? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' : '';
|
||||||
|
|
||||||
|
final newContactMessage = newContactAddress != null
|
||||||
|
? '\n${S.of(context).add_contact_to_address_book}' : '';
|
||||||
|
|
||||||
|
final alertContent =
|
||||||
|
"$successMessage$waitMessage$newContactMessage";
|
||||||
|
|
||||||
|
if (newContactAddress != null) {
|
||||||
|
return AlertWithTwoActions(
|
||||||
|
alertTitle: '',
|
||||||
|
alertContent: alertContent,
|
||||||
|
rightButtonText: S.of(_dialogContext).add_contact,
|
||||||
|
leftButtonText: S.of(_dialogContext).ignor,
|
||||||
|
actionRightButton: () {
|
||||||
|
Navigator.of(_dialogContext).pop();
|
||||||
|
RequestReviewHandler.requestReview();
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
Routes.addressBookAddContact,
|
||||||
|
arguments: newContactAddress);
|
||||||
|
newContactAddress = null;
|
||||||
|
},
|
||||||
|
actionLeftButton: () {
|
||||||
|
Navigator.of(_dialogContext).pop();
|
||||||
|
RequestReviewHandler.requestReview();
|
||||||
|
newContactAddress = null;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alertContent = S.of(_dialogContext).send_success(
|
return AlertWithOneAction(
|
||||||
sendViewModel.selectedCryptoCurrency.toString());
|
alertTitle: '',
|
||||||
|
alertContent: alertContent,
|
||||||
|
buttonText: S.of(_dialogContext).ok,
|
||||||
|
buttonAction: () {
|
||||||
|
Navigator.of(_dialogContext).pop();
|
||||||
|
RequestReviewHandler.requestReview();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return AlertWithOneAction(
|
|
||||||
alertTitle: '',
|
|
||||||
alertContent: alertContent,
|
|
||||||
buttonText: S.of(_dialogContext).ok,
|
|
||||||
buttonAction: () {
|
|
||||||
Navigator.of(_dialogContext).pop();
|
|
||||||
RequestReviewHandler.requestReview();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Offstage();
|
return Offstage();
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||||
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
|
||||||
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
|
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
|
||||||
import 'package:cake_wallet/utils/payment_request.dart';
|
|
||||||
import 'package:cake_wallet/src/widgets/trail_button.dart';
|
import 'package:cake_wallet/src/widgets/trail_button.dart';
|
||||||
import 'package:cake_wallet/view_model/send/template_view_model.dart';
|
import 'package:cake_wallet/view_model/send/template_view_model.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
@ -11,7 +9,6 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
|
import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
import 'package:cake_wallet/src/screens/send/widgets/prefix_currency_icon_widget.dart';
|
|
||||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||||
import 'package:cake_wallet/src/screens/send/widgets/send_template_card.dart';
|
import 'package:cake_wallet/src/screens/send/widgets/send_template_card.dart';
|
||||||
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||||
|
@ -97,8 +94,13 @@ class SendTemplatePage extends BasePage {
|
||||||
radius: 6.0,
|
radius: 6.0,
|
||||||
dotWidth: 6.0,
|
dotWidth: 6.0,
|
||||||
dotHeight: 6.0,
|
dotHeight: 6.0,
|
||||||
dotColor: Theme.of(context).extension<SendPageTheme>()!.indicatorDotColor,
|
dotColor: Theme.of(context)
|
||||||
activeDotColor: Theme.of(context).extension<DashboardPageTheme>()!.indicatorDotTheme.activeIndicatorColor))
|
.extension<SendPageTheme>()!
|
||||||
|
.indicatorDotColor,
|
||||||
|
activeDotColor: Theme.of(context)
|
||||||
|
.extension<DashboardPageTheme>()!
|
||||||
|
.indicatorDotTheme
|
||||||
|
.activeIndicatorColor))
|
||||||
: Offstage();
|
: Offstage();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -80,15 +80,17 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
if (initialPaymentRequest != null &&
|
if (initialPaymentRequest != null &&
|
||||||
sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) {
|
sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
showPopUp<void>(
|
if (context.mounted) {
|
||||||
context: context,
|
showPopUp<void>(
|
||||||
builder: (BuildContext context) {
|
context: context,
|
||||||
return AlertWithOneAction(
|
builder: (BuildContext context) {
|
||||||
alertTitle: S.of(context).error,
|
return AlertWithOneAction(
|
||||||
alertContent: S.of(context).unmatched_currencies,
|
alertTitle: S.of(context).error,
|
||||||
buttonText: S.of(context).ok,
|
alertContent: S.of(context).unmatched_currencies,
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
buttonText: S.of(context).ok,
|
||||||
});
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,7 +323,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
? sendViewModel.allAmountValidator
|
? sendViewModel.allAmountValidator
|
||||||
: sendViewModel.amountValidator,
|
: sendViewModel.amountValidator,
|
||||||
),
|
),
|
||||||
if (!sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL)
|
if (!sendViewModel.isBatchSending &&
|
||||||
|
sendViewModel.shouldDisplaySendALL)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 2,
|
top: 2,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
|
|
@ -48,11 +48,11 @@ abstract class ContactViewModelBase with Store {
|
||||||
currency = null;
|
currency = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future save() async {
|
Future<void> save() async {
|
||||||
try {
|
try {
|
||||||
state = IsExecutingState();
|
state = IsExecutingState();
|
||||||
|
|
||||||
if (_contact != null) {
|
if (_contact != null && _contact!.original.isInBox) {
|
||||||
_contact?.name = name;
|
_contact?.name = name;
|
||||||
_contact?.address = address;
|
_contact?.address = address;
|
||||||
_contact?.type = currency!;
|
_contact?.type = currency!;
|
||||||
|
|
|
@ -61,6 +61,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
this.sharedPreferences,
|
this.sharedPreferences,
|
||||||
this.contactListViewModel,
|
this.contactListViewModel,
|
||||||
) : _cryptoNumberFormat = NumberFormat(),
|
) : _cryptoNumberFormat = NumberFormat(),
|
||||||
|
isSendAllEnabled = false,
|
||||||
isFixedRateMode = false,
|
isFixedRateMode = false,
|
||||||
isReceiveAmountEntered = false,
|
isReceiveAmountEntered = false,
|
||||||
depositAmount = '',
|
depositAmount = '',
|
||||||
|
@ -206,6 +207,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
@observable
|
@observable
|
||||||
bool isFixedRateMode;
|
bool isFixedRateMode;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool isSendAllEnabled;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
Limits limits;
|
Limits limits;
|
||||||
|
|
||||||
|
@ -531,10 +535,14 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void calculateDepositAllAmount() {
|
void enableSendAllAmount() {
|
||||||
if (wallet.type == WalletType.bitcoin ||
|
isSendAllEnabled = true;
|
||||||
wallet.type == WalletType.litecoin ||
|
calculateDepositAllAmount();
|
||||||
wallet.type == WalletType.bitcoinCash) {
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> calculateDepositAllAmount() async {
|
||||||
|
if (wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) {
|
||||||
final availableBalance = wallet.balance[wallet.currency]!.available;
|
final availableBalance = wallet.balance[wallet.currency]!.available;
|
||||||
final priority = _settingsStore.priority[wallet.type]!;
|
final priority = _settingsStore.priority[wallet.type]!;
|
||||||
final fee = wallet.calculateEstimatedFee(priority, null);
|
final fee = wallet.calculateEstimatedFee(priority, null);
|
||||||
|
@ -543,6 +551,13 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
|
|
||||||
final amount = availableBalance - fee;
|
final amount = availableBalance - fee;
|
||||||
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
||||||
|
} else if (wallet.type == WalletType.bitcoin) {
|
||||||
|
final priority = _settingsStore.priority[wallet.type]!;
|
||||||
|
|
||||||
|
final amount = await bitcoin!.estimateFakeSendAllTxAmount(
|
||||||
|
wallet, bitcoin!.deserializeBitcoinTransactionPriority(priority.raw));
|
||||||
|
|
||||||
|
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/entities/contact.dart';
|
||||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||||
import 'package:cake_wallet/entities/transaction_description.dart';
|
import 'package:cake_wallet/entities/transaction_description.dart';
|
||||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||||
|
@ -420,6 +421,34 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContactRecord? newContactAddress () {
|
||||||
|
|
||||||
|
final Set<String> contactAddresses =
|
||||||
|
Set.from(contactListViewModel.contacts.map((contact) => contact.address))
|
||||||
|
..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
|
||||||
|
|
||||||
|
for (var output in outputs) {
|
||||||
|
String address;
|
||||||
|
if (output.isParsedAddress) {
|
||||||
|
address = output.parsedAddress.addresses.first;
|
||||||
|
} else {
|
||||||
|
address = output.address;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address.isNotEmpty && !contactAddresses.contains(address)) {
|
||||||
|
|
||||||
|
return ContactRecord(
|
||||||
|
contactListViewModel.contactSource,
|
||||||
|
Contact(
|
||||||
|
name: '',
|
||||||
|
address: address,
|
||||||
|
type: selectedCryptoCurrency,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
String translateErrorMessage(
|
String translateErrorMessage(
|
||||||
String error,
|
String error,
|
||||||
WalletType walletType,
|
WalletType walletType,
|
||||||
|
|
|
@ -125,4 +125,4 @@ SPEC CHECKSUMS:
|
||||||
|
|
||||||
PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb
|
PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
COCOAPODS: 1.15.2
|
||||||
|
|
|
@ -113,7 +113,7 @@ dependencies:
|
||||||
bitcoin_base:
|
bitcoin_base:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/bitcoin_base.git
|
url: https://github.com/cake-tech/bitcoin_base.git
|
||||||
ref: cake-update-v1
|
ref: cake-update-v2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ",
|
"activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ",
|
||||||
"add": "إضافة",
|
"add": "إضافة",
|
||||||
"add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ",
|
"add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ",
|
||||||
|
"add_contact_to_address_book": "هل ترغب في إضافة جهة الاتصال هذه إلى دفتر العناوين الخاص بك؟",
|
||||||
"add_custom_node": "إضافة عقدة مخصصة جديدة",
|
"add_custom_node": "إضافة عقدة مخصصة جديدة",
|
||||||
"add_custom_redemption": "إضافة استرداد مخصص",
|
"add_custom_redemption": "إضافة استرداد مخصص",
|
||||||
"add_fund_to_card": "أضف أموالاً مدفوعة مسبقًا إلى البطاقات (حتى ${value})",
|
"add_fund_to_card": "أضف أموالاً مدفوعة مسبقًا إلى البطاقات (حتى ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Тук ще се появят активни връзки",
|
"activeConnectionsPrompt": "Тук ще се появят активни връзки",
|
||||||
"add": "Добави",
|
"add": "Добави",
|
||||||
"add_contact": "Добави контакт",
|
"add_contact": "Добави контакт",
|
||||||
|
"add_contact_to_address_book": "Искате ли да добавите този контакт към вашата адресна книга?",
|
||||||
"add_custom_node": "Добавяне на нов персонализиран Node",
|
"add_custom_node": "Добавяне на нов персонализиран Node",
|
||||||
"add_custom_redemption": "Добавете персонализиран Redemption",
|
"add_custom_redemption": "Добавете персонализиран Redemption",
|
||||||
"add_fund_to_card": "Добавете предплатени средства в картите (до ${value})",
|
"add_fund_to_card": "Добавете предплатени средства в картите (до ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Zde se zobrazí aktivní připojení",
|
"activeConnectionsPrompt": "Zde se zobrazí aktivní připojení",
|
||||||
"add": "Přidat",
|
"add": "Přidat",
|
||||||
"add_contact": "Přidat kontakt",
|
"add_contact": "Přidat kontakt",
|
||||||
|
"add_contact_to_address_book": "Chcete přidat tento kontakt do svého adresáře?",
|
||||||
"add_custom_node": "Přidat vlastní uzel",
|
"add_custom_node": "Přidat vlastní uzel",
|
||||||
"add_custom_redemption": "Přidat vlastní uplatnění",
|
"add_custom_redemption": "Přidat vlastní uplatnění",
|
||||||
"add_fund_to_card": "Všechny předplacené prostředky na kartě (až ${value})",
|
"add_fund_to_card": "Všechny předplacené prostředky na kartě (až ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt",
|
"activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt",
|
||||||
"add": "Hinzufügen",
|
"add": "Hinzufügen",
|
||||||
"add_contact": "Kontakt hinzufügen",
|
"add_contact": "Kontakt hinzufügen",
|
||||||
|
"add_contact_to_address_book": "Möchten Sie diesen Kontakt zu Ihrem Adressbuch hinzufügen?",
|
||||||
"add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen",
|
"add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen",
|
||||||
"add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen",
|
"add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen",
|
||||||
"add_fund_to_card": "Prepaid-Guthaben zu den Karten hinzufügen (bis zu ${value})",
|
"add_fund_to_card": "Prepaid-Guthaben zu den Karten hinzufügen (bis zu ${value})",
|
||||||
|
@ -414,8 +415,8 @@
|
||||||
"placeholder_transactions": "Ihre Transaktionen werden hier angezeigt",
|
"placeholder_transactions": "Ihre Transaktionen werden hier angezeigt",
|
||||||
"please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist",
|
"please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist",
|
||||||
"please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.",
|
"please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.",
|
||||||
"please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.",
|
|
||||||
"Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.",
|
"Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.",
|
||||||
|
"please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.",
|
||||||
"please_select": "Bitte auswählen:",
|
"please_select": "Bitte auswählen:",
|
||||||
"please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.",
|
"please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.",
|
||||||
"please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden",
|
"please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Active connections will appear here",
|
"activeConnectionsPrompt": "Active connections will appear here",
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
"add_contact": "Add contact",
|
"add_contact": "Add contact",
|
||||||
|
"add_contact_to_address_book": "Would you like to add this contact to your address book?",
|
||||||
"add_custom_node": "Add New Custom Node",
|
"add_custom_node": "Add New Custom Node",
|
||||||
"add_custom_redemption": "Add Custom Redemption",
|
"add_custom_redemption": "Add Custom Redemption",
|
||||||
"add_fund_to_card": "Add prepaid funds to the cards (up to ${value})",
|
"add_fund_to_card": "Add prepaid funds to the cards (up to ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Las conexiones activas aparecerán aquí",
|
"activeConnectionsPrompt": "Las conexiones activas aparecerán aquí",
|
||||||
"add": "Añadir",
|
"add": "Añadir",
|
||||||
"add_contact": "Agregar contacto",
|
"add_contact": "Agregar contacto",
|
||||||
|
"add_contact_to_address_book": "¿Le gustaría agregar este contacto a su libreta de direcciones?",
|
||||||
"add_custom_node": "Agregar nuevo nodo personalizado",
|
"add_custom_node": "Agregar nuevo nodo personalizado",
|
||||||
"add_custom_redemption": "Agregar redención personalizada",
|
"add_custom_redemption": "Agregar redención personalizada",
|
||||||
"add_fund_to_card": "Agregar fondos prepagos a las tarjetas (hasta ${value})",
|
"add_fund_to_card": "Agregar fondos prepagos a las tarjetas (hasta ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
|
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
|
||||||
"add": "Ajouter",
|
"add": "Ajouter",
|
||||||
"add_contact": "Ajouter le contact",
|
"add_contact": "Ajouter le contact",
|
||||||
|
"add_contact_to_address_book": "Souhaitez-vous ajouter ce contact à votre carnet d'adresses?",
|
||||||
"add_custom_node": "Ajouter un nouveau nœud personnalisé",
|
"add_custom_node": "Ajouter un nouveau nœud personnalisé",
|
||||||
"add_custom_redemption": "Ajouter un remboursement personnalisé",
|
"add_custom_redemption": "Ajouter un remboursement personnalisé",
|
||||||
"add_fund_to_card": "Ajouter des fonds prépayés aux cartes (jusqu'à ${value})",
|
"add_fund_to_card": "Ajouter des fonds prépayés aux cartes (jusqu'à ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan",
|
"activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan",
|
||||||
"add": "Ƙara",
|
"add": "Ƙara",
|
||||||
"add_contact": "Ƙara lamba",
|
"add_contact": "Ƙara lamba",
|
||||||
|
"add_contact_to_address_book": "Kuna so ku ƙara wannan lamba zuwa littafin adireshinku?",
|
||||||
"add_custom_node": "Ƙara Sabon Kulli na Custom",
|
"add_custom_node": "Ƙara Sabon Kulli na Custom",
|
||||||
"add_custom_redemption": "Ƙara Ceto na Musamman",
|
"add_custom_redemption": "Ƙara Ceto na Musamman",
|
||||||
"add_fund_to_card": "Ƙara kuɗin da aka riga aka biya a katunan (har zuwa ${value})",
|
"add_fund_to_card": "Ƙara kuɗin da aka riga aka biya a katunan (har zuwa ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे",
|
"activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे",
|
||||||
"add": "जोड़ना",
|
"add": "जोड़ना",
|
||||||
"add_contact": "संपर्क जोड़ें",
|
"add_contact": "संपर्क जोड़ें",
|
||||||
|
"add_contact_to_address_book": "क्या आप इस संपर्क को अपनी एड्रेस बुक में जोड़ना चाहेंगे?",
|
||||||
"add_custom_node": "नया कस्टम नोड जोड़ें",
|
"add_custom_node": "नया कस्टम नोड जोड़ें",
|
||||||
"add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें",
|
"add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें",
|
||||||
"add_fund_to_card": "कार्ड में प्रीपेड धनराशि जोड़ें (${value} तक)",
|
"add_fund_to_card": "कार्ड में प्रीपेड धनराशि जोड़ें (${value} तक)",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze",
|
"activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze",
|
||||||
"add": "Dodaj",
|
"add": "Dodaj",
|
||||||
"add_contact": "Dodaj kontakt",
|
"add_contact": "Dodaj kontakt",
|
||||||
|
"add_contact_to_address_book": "Želite li dodati ovaj kontakt u svoj adresar?",
|
||||||
"add_custom_node": "Dodaj novi prilagođeni čvor",
|
"add_custom_node": "Dodaj novi prilagođeni čvor",
|
||||||
"add_custom_redemption": "Dodaj prilagođeni otkup",
|
"add_custom_redemption": "Dodaj prilagođeni otkup",
|
||||||
"add_fund_to_card": "Dodajte unaprijed uplaćena sredstva na kartice (do ${value})",
|
"add_fund_to_card": "Dodajte unaprijed uplaćena sredstva na kartice (do ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Koneksi aktif akan muncul di sini",
|
"activeConnectionsPrompt": "Koneksi aktif akan muncul di sini",
|
||||||
"add": "Menambahkan",
|
"add": "Menambahkan",
|
||||||
"add_contact": "Tambah kontak",
|
"add_contact": "Tambah kontak",
|
||||||
|
"add_contact_to_address_book": "Apakah Anda ingin menambahkan kontak ini ke buku alamat Anda?",
|
||||||
"add_custom_node": "Tambahkan Node Kustom Baru",
|
"add_custom_node": "Tambahkan Node Kustom Baru",
|
||||||
"add_custom_redemption": "Tambahkan Tukar Kustom",
|
"add_custom_redemption": "Tambahkan Tukar Kustom",
|
||||||
"add_fund_to_card": "Tambahkan dana pra-bayar ke kartu (hingga ${value})",
|
"add_fund_to_card": "Tambahkan dana pra-bayar ke kartu (hingga ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui",
|
"activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui",
|
||||||
"add": "Aggiungi",
|
"add": "Aggiungi",
|
||||||
"add_contact": "Aggiungi contatto",
|
"add_contact": "Aggiungi contatto",
|
||||||
|
"add_contact_to_address_book": "Vorresti aggiungere questo contatto alla tua rubrica?",
|
||||||
"add_custom_node": "Aggiungi nuovo nodo personalizzato",
|
"add_custom_node": "Aggiungi nuovo nodo personalizzato",
|
||||||
"add_custom_redemption": "Aggiungi riscatto personalizzato",
|
"add_custom_redemption": "Aggiungi riscatto personalizzato",
|
||||||
"add_fund_to_card": "Aggiungi fondi prepagati alle carte (fino a ${value})",
|
"add_fund_to_card": "Aggiungi fondi prepagati alle carte (fino a ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "アクティブな接続がここに表示されます",
|
"activeConnectionsPrompt": "アクティブな接続がここに表示されます",
|
||||||
"add": "加える",
|
"add": "加える",
|
||||||
"add_contact": "連絡先を追加",
|
"add_contact": "連絡先を追加",
|
||||||
|
"add_contact_to_address_book": "この連絡先をアドレス帳に追加しますか?",
|
||||||
"add_custom_node": "新しいカスタム ノードを追加",
|
"add_custom_node": "新しいカスタム ノードを追加",
|
||||||
"add_custom_redemption": "カスタム引き換えを追加",
|
"add_custom_redemption": "カスタム引き換えを追加",
|
||||||
"add_fund_to_card": "プリペイド資金をカードに追加します(最大 ${value})",
|
"add_fund_to_card": "プリペイド資金をカードに追加します(最大 ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다",
|
"activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다",
|
||||||
"add": "더하다",
|
"add": "더하다",
|
||||||
"add_contact": "주소록에 추가",
|
"add_contact": "주소록에 추가",
|
||||||
|
"add_contact_to_address_book": "이 연락처를 주소록에 추가 하시겠습니까?",
|
||||||
"add_custom_node": "새 사용자 정의 노드 추가",
|
"add_custom_node": "새 사용자 정의 노드 추가",
|
||||||
"add_custom_redemption": "사용자 지정 상환 추가",
|
"add_custom_redemption": "사용자 지정 상환 추가",
|
||||||
"add_fund_to_card": "카드에 선불 금액 추가(최대 ${value})",
|
"add_fund_to_card": "카드에 선불 금액 추가(최대 ${value})",
|
||||||
|
@ -414,8 +415,8 @@
|
||||||
"placeholder_transactions": "거래가 여기에 표시됩니다",
|
"placeholder_transactions": "거래가 여기에 표시됩니다",
|
||||||
"please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.",
|
"please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.",
|
||||||
"please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.",
|
"please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.",
|
||||||
"please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
|
|
||||||
"Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
|
"Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
|
||||||
|
"please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.",
|
||||||
"please_select": "선택 해주세요:",
|
"please_select": "선택 해주세요:",
|
||||||
"please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.",
|
"please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.",
|
||||||
"please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오",
|
"please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။",
|
"activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။",
|
||||||
"add": "ထည့်ပါ။",
|
"add": "ထည့်ပါ။",
|
||||||
"add_contact": "အဆက်အသွယ်ထည့်ပါ။",
|
"add_contact": "အဆက်အသွယ်ထည့်ပါ။",
|
||||||
|
"add_contact_to_address_book": "ဒီအဆက်အသွယ်ကိုမင်းရဲ့လိပ်စာစာအုပ်နဲ့ထပ်ထည့်ချင်ပါသလား။",
|
||||||
"add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။",
|
"add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။",
|
||||||
"add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။",
|
"add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။",
|
||||||
"add_fund_to_card": "ကတ်များသို့ ကြိုတင်ငွေပေးငွေများ ထည့်ပါ (${value} အထိ)",
|
"add_fund_to_card": "ကတ်များသို့ ကြိုတင်ငွေပေးငွေများ ထည့်ပါ (${value} အထိ)",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven",
|
"activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven",
|
||||||
"add": "Toevoegen",
|
"add": "Toevoegen",
|
||||||
"add_contact": "Contactpersoon toevoegen",
|
"add_contact": "Contactpersoon toevoegen",
|
||||||
|
"add_contact_to_address_book": "Wilt u dit contact toevoegen aan uw adresboek?",
|
||||||
"add_custom_node": "Voeg een nieuw aangepast knooppunt toe",
|
"add_custom_node": "Voeg een nieuw aangepast knooppunt toe",
|
||||||
"add_custom_redemption": "Voeg aangepaste inwisseling toe",
|
"add_custom_redemption": "Voeg aangepaste inwisseling toe",
|
||||||
"add_fund_to_card": "Voeg prepaid tegoed toe aan de kaarten (tot ${value})",
|
"add_fund_to_card": "Voeg prepaid tegoed toe aan de kaarten (tot ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia",
|
"activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia",
|
||||||
"add": "Dodaj",
|
"add": "Dodaj",
|
||||||
"add_contact": "Dodaj kontakt",
|
"add_contact": "Dodaj kontakt",
|
||||||
|
"add_contact_to_address_book": "Czy chciałbyś dodać ten kontakt do swojej książki adresowej?",
|
||||||
"add_custom_node": "Dodaj nowy węzeł niestandardowy",
|
"add_custom_node": "Dodaj nowy węzeł niestandardowy",
|
||||||
"add_custom_redemption": "Dodaj niestandardowe wykorzystanie",
|
"add_custom_redemption": "Dodaj niestandardowe wykorzystanie",
|
||||||
"add_fund_to_card": "Dodaj przedpłacone środki do kart (do ${value})",
|
"add_fund_to_card": "Dodaj przedpłacone środki do kart (do ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Conexões ativas aparecerão aqui",
|
"activeConnectionsPrompt": "Conexões ativas aparecerão aqui",
|
||||||
"add": "Adicionar",
|
"add": "Adicionar",
|
||||||
"add_contact": "Adicionar contato",
|
"add_contact": "Adicionar contato",
|
||||||
|
"add_contact_to_address_book": "Você gostaria de adicionar esse contato ao seu catálogo de endereços?",
|
||||||
"add_custom_node": "Adicionar novo nó personalizado",
|
"add_custom_node": "Adicionar novo nó personalizado",
|
||||||
"add_custom_redemption": "Adicionar resgate personalizado",
|
"add_custom_redemption": "Adicionar resgate personalizado",
|
||||||
"add_fund_to_card": "Adicionar fundos pré-pagos aos cartões (até ${value})",
|
"add_fund_to_card": "Adicionar fundos pré-pagos aos cartões (até ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Здесь появятся активные подключения",
|
"activeConnectionsPrompt": "Здесь появятся активные подключения",
|
||||||
"add": "Добавить",
|
"add": "Добавить",
|
||||||
"add_contact": "Добавить контакт",
|
"add_contact": "Добавить контакт",
|
||||||
|
"add_contact_to_address_book": "Хотели бы вы добавить этот контакт в свою адресную книгу?",
|
||||||
"add_custom_node": "Добавить новый пользовательский узел",
|
"add_custom_node": "Добавить новый пользовательский узел",
|
||||||
"add_custom_redemption": "Добавить пользовательское погашение",
|
"add_custom_redemption": "Добавить пользовательское погашение",
|
||||||
"add_fund_to_card": "Добавить предоплаченные средства на карты (до ${value})",
|
"add_fund_to_card": "Добавить предоплаченные средства на карты (до ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่",
|
"activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่",
|
||||||
"add": "เพิ่ม",
|
"add": "เพิ่ม",
|
||||||
"add_contact": "เพิ่มผู้ติดต่อ",
|
"add_contact": "เพิ่มผู้ติดต่อ",
|
||||||
|
"add_contact_to_address_book": "คุณต้องการเพิ่มผู้ติดต่อนี้ในสมุดที่อยู่ของคุณหรือไม่?",
|
||||||
"add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง",
|
"add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง",
|
||||||
"add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง",
|
"add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง",
|
||||||
"add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})",
|
"add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon",
|
"activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon",
|
||||||
"add": "Idagdag",
|
"add": "Idagdag",
|
||||||
"add_contact": "Magdagdag ng contact",
|
"add_contact": "Magdagdag ng contact",
|
||||||
|
"add_contact_to_address_book": "Nais mo bang idagdag ang contact na ito sa iyong address book?",
|
||||||
"add_custom_node": "Magdagdag ng bagong pasadyang node",
|
"add_custom_node": "Magdagdag ng bagong pasadyang node",
|
||||||
"add_custom_redemption": "Magdagdag ng pasadyang pagtubos",
|
"add_custom_redemption": "Magdagdag ng pasadyang pagtubos",
|
||||||
"add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})",
|
"add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Aktif bağlantılar burada görünecek",
|
"activeConnectionsPrompt": "Aktif bağlantılar burada görünecek",
|
||||||
"add": "Ekle",
|
"add": "Ekle",
|
||||||
"add_contact": "Kişi ekle",
|
"add_contact": "Kişi ekle",
|
||||||
|
"add_contact_to_address_book": "Bu kişiyi adres defterinize eklemek ister misiniz?",
|
||||||
"add_custom_node": "Yeni Özel Düğüm Ekleme",
|
"add_custom_node": "Yeni Özel Düğüm Ekleme",
|
||||||
"add_custom_redemption": "Özel Bozdurma Ekle",
|
"add_custom_redemption": "Özel Bozdurma Ekle",
|
||||||
"add_fund_to_card": "Ön ödemeli kartlara para ekle (En fazla yüklenebilir tutar: ${value})",
|
"add_fund_to_card": "Ön ödemeli kartlara para ekle (En fazla yüklenebilir tutar: ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Тут з’являться активні підключення",
|
"activeConnectionsPrompt": "Тут з’являться активні підключення",
|
||||||
"add": "Добавити",
|
"add": "Добавити",
|
||||||
"add_contact": "Додати контакт",
|
"add_contact": "Додати контакт",
|
||||||
|
"add_contact_to_address_book": "Хотіли б ви додати цей контакт до своєї адресної книги?",
|
||||||
"add_custom_node": "Додати новий спеціальний вузол",
|
"add_custom_node": "Додати новий спеціальний вузол",
|
||||||
"add_custom_redemption": "Додати спеціальне погашення",
|
"add_custom_redemption": "Додати спеціальне погашення",
|
||||||
"add_fund_to_card": "Додайте передплачені кошти на картки (до ${value})",
|
"add_fund_to_card": "Додайте передплачені кошти на картки (до ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ",
|
"activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ",
|
||||||
"add": "شامل کریں۔",
|
"add": "شامل کریں۔",
|
||||||
"add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ",
|
"add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ",
|
||||||
|
"add_contact_to_address_book": "کیا آپ اس رابطہ کو اپنی ایڈریس بک میں شامل کرنا چاہیں گے؟",
|
||||||
"add_custom_node": "نیا کسٹم نوڈ شامل کریں۔",
|
"add_custom_node": "نیا کسٹم نوڈ شامل کریں۔",
|
||||||
"add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔",
|
"add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔",
|
||||||
"add_fund_to_card": "کارڈز میں پری پیڈ فنڈز شامل کریں (${value} تک)",
|
"add_fund_to_card": "کارڈز میں پری پیڈ فنڈز شامل کریں (${value} تک)",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi",
|
"activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi",
|
||||||
"add": "Fikún",
|
"add": "Fikún",
|
||||||
"add_contact": "Fi olubasọrọ kun",
|
"add_contact": "Fi olubasọrọ kun",
|
||||||
|
"add_contact_to_address_book": "Ṣe o fẹ lati ṣafikun olubasọrọ yii si iwe adirẹsi rẹ?",
|
||||||
"add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀",
|
"add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀",
|
||||||
"add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná",
|
"add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná",
|
||||||
"add_fund_to_card": "Ẹ fikún owó sí àwọn káàdì (kò tóbi ju ${value})",
|
"add_fund_to_card": "Ẹ fikún owó sí àwọn káàdì (kò tóbi ju ${value})",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"activeConnectionsPrompt": "活动连接将出现在这里",
|
"activeConnectionsPrompt": "活动连接将出现在这里",
|
||||||
"add": "添加",
|
"add": "添加",
|
||||||
"add_contact": "增加联系人",
|
"add_contact": "增加联系人",
|
||||||
|
"add_contact_to_address_book": "您想将此联系人添加到您的通讯录中吗?",
|
||||||
"add_custom_node": "添加新的自定义节点",
|
"add_custom_node": "添加新的自定义节点",
|
||||||
"add_custom_redemption": "添加自定义兑换",
|
"add_custom_redemption": "添加自定义兑换",
|
||||||
"add_fund_to_card": "向卡中添加预付资金(最多 ${value})",
|
"add_fund_to_card": "向卡中添加预付资金(最多 ${value})",
|
||||||
|
|
|
@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app"
|
||||||
MONERO_COM_SCHEME="monero.com"
|
MONERO_COM_SCHEME="monero.com"
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="4.15.0"
|
CAKEWALLET_VERSION="4.15.2"
|
||||||
CAKEWALLET_BUILD_NUMBER=198
|
CAKEWALLET_BUILD_NUMBER=200
|
||||||
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
||||||
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
||||||
CAKEWALLET_SCHEME="cakewallet"
|
CAKEWALLET_SCHEME="cakewallet"
|
||||||
|
|
|
@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=77
|
||||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="4.15.0"
|
CAKEWALLET_VERSION="4.15.2"
|
||||||
CAKEWALLET_BUILD_NUMBER=217
|
CAKEWALLET_BUILD_NUMBER=219
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
HAVEN_NAME="Haven"
|
HAVEN_NAME="Haven"
|
||||||
|
|
|
@ -21,8 +21,8 @@ MONERO_COM_BUILD_NUMBER=10
|
||||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="1.8.0"
|
CAKEWALLET_VERSION="1.8.2"
|
||||||
CAKEWALLET_BUILD_NUMBER=57
|
CAKEWALLET_BUILD_NUMBER=59
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||||
|
|
|
@ -70,7 +70,6 @@ import 'package:cw_core/output_info.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
import 'package:cake_wallet/view_model/send/output.dart';
|
import 'package:cake_wallet/view_model/send/output.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';""";
|
import 'package:bitcoin_base/bitcoin_base.dart';""";
|
||||||
const bitcoinCWHeaders = """
|
const bitcoinCWHeaders = """
|
||||||
|
@ -127,6 +126,7 @@ abstract class Bitcoin {
|
||||||
List<String> getAddresses(Object wallet);
|
List<String> getAddresses(Object wallet);
|
||||||
String getAddress(Object wallet);
|
String getAddress(Object wallet);
|
||||||
|
|
||||||
|
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority);
|
||||||
List<ElectrumSubAddress> getSubAddresses(Object wallet);
|
List<ElectrumSubAddress> getSubAddresses(Object wallet);
|
||||||
|
|
||||||
String formatterBitcoinAmountToString({required int amount});
|
String formatterBitcoinAmountToString({required int amount});
|
||||||
|
|
Loading…
Reference in a new issue