mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-23 06:38:35 +02:00
Btc address types (#1263)
* inital migration changes * feat: rest of changes * minor fix [skip ci] * fix: P2wshAddress & wallet address index * fix: address review comments * fix: address type restore * feat: add testnet * Fix review comments Remove bitcoin_base from cw_core * Fix address not matching selected type on start * remove un-necessary parameter [skip ci] * Remove bitcoin specific code from main lib Fix possible runtime exception from list wrong access * Minor fix * fix: fixes for Testnet * fix: bitcoin receive option dependency breaks monerocom * Fix issues when building Monero.com * feat: Transaction Builder changes * fix: discover addresses, testnet restoring, duplicate unspent coins, and taproot address vs schnorr sig tweak * fix: remove print * feat: improve error when failed broadcast response * feat: create fish shell env script * fix: unmodifiable maps * fix: build * fix: build * fix: computed observable side effect bug * feat: add nix script for android build_all * fix: wrong keypairs used for signing * fix: wrong addresses when using fromScriptPubKey scripts * fix(actual commit): testnet tx expanded + wrong addresses when using fromScriptPubKey scripts (update bitcoin_base deps) * fix: self-send [skip ci] * fix: p2wsh * fix: testnet fees * New versions * Update macos build number Minor UI fix * fix: use new bitcoin_base ref, fix tx list wrong hex value & refactor hidden vs hd use - if always use sideHd for isHidden, it is easier to simplify the functions instead of passing both which can be error prone - (ps: now this could probably be changed, for example from isHidden to isChange since with address list we now see "hidden" addresses) * Fix if condition to handle litecoin case * fix: self-send, change address was always making direction incoming * refactor: improve estimation function, add more inputs if balance missing * fix: new bitcoin_base update, fixes script issues * Update evm chain wallet service arguments * Fix translation [skip ci] * Fix translation [skip ci] * Update strings_fr.arb [skip ci] * fix: async isChange function not being awaited, refactor to reduce looping into a single place * fix: _address vs address, missing p2sh * fix: minor mistake in storing p2sh page type [skip ci] * refactor: use already matched addresses property * feat: improved perfomance for fetching transaction histories * feat: continue perfomance change, improve address discovery only to last address by type with history * fix: make sure transaction list is sorted by date * refactor: isTestnet only for bitcoin * fix: walletInfo type null case * fix: deprecated p2pk * refactor: make condition more readable * refactor: remove unnecessary Str variant * refactor: make condition more readable * fix: infinite loop possible * Revert removing isTestnet from other wallets [skip ci] * refactor: rename addresses when matched by receive type * Make the beta build [skip ci] Remove app_env.fish --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
+181
-171
@@ -1,181 +1,191 @@
|
||||
part of 'bitcoin.dart';
|
||||
|
||||
class CWBitcoin extends Bitcoin {
|
||||
@override
|
||||
TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({
|
||||
required String name,
|
||||
required String mnemonic,
|
||||
required String password})
|
||||
=> BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password);
|
||||
|
||||
@override
|
||||
WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({
|
||||
required String name,
|
||||
required String password,
|
||||
required String wif,
|
||||
WalletInfo? walletInfo})
|
||||
=> BitcoinRestoreWalletFromWIFCredentials(name: name, password: password, wif: wif, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
WalletCredentials createBitcoinNewWalletCredentials({
|
||||
required String name,
|
||||
WalletInfo? walletInfo})
|
||||
=> BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
List<String> getWordList() => wordlist;
|
||||
|
||||
@override
|
||||
Map<String, String> getWalletKeys(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
final keys = bitcoinWallet.keys;
|
||||
|
||||
return <String, String>{
|
||||
'wif': keys.wif,
|
||||
'privateKey': keys.privateKey,
|
||||
'publicKey': keys.publicKey
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities()
|
||||
=> BitcoinTransactionPriority.all;
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getLitecoinTransactionPriorities()
|
||||
=> LitecoinTransactionPriority.all;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeBitcoinTransactionPriority(int raw)
|
||||
=> BitcoinTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeLitecoinTransactionPriority(int raw)
|
||||
=> LitecoinTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
int getFeeRate(Object wallet, TransactionPriority priority) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.feeRate(priority);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateNewAddress(Object wallet, String label) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.walletAddresses.generateNewAddress(label: label, hd: bitcoinWallet.hd);
|
||||
await wallet.save();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateAddress(Object wallet,String address, String label) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
bitcoinWallet.walletAddresses.updateAddress(address, label);
|
||||
await wallet.save();
|
||||
}
|
||||
|
||||
@override
|
||||
Object createBitcoinTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate})
|
||||
=> BitcoinTransactionCredentials(
|
||||
outputs.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as BitcoinTransactionPriority,
|
||||
feeRate: feeRate);
|
||||
|
||||
@override
|
||||
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate})
|
||||
=> BitcoinTransactionCredentials(
|
||||
outputs,
|
||||
priority: priority != null ? priority as BitcoinTransactionPriority : null,
|
||||
feeRate: feeRate);
|
||||
|
||||
@override
|
||||
List<String> getAddresses(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.walletAddresses.addresses
|
||||
.map((BitcoinAddressRecord addr) => addr.address)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@computed
|
||||
List<ElectrumSubAddress> getSubAddresses(Object wallet) {
|
||||
final electrumWallet = wallet as ElectrumWallet;
|
||||
return electrumWallet.walletAddresses.addresses
|
||||
.map((BitcoinAddressRecord addr) => ElectrumSubAddress(
|
||||
id: addr.index,
|
||||
name: addr.name,
|
||||
address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address,
|
||||
txCount: addr.txCount,
|
||||
balance: addr.balance,
|
||||
isChange: addr.isHidden))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.walletAddresses.address;
|
||||
}
|
||||
|
||||
@override
|
||||
String formatterBitcoinAmountToString({required int amount})
|
||||
=> bitcoinAmountToString(amount: amount);
|
||||
|
||||
@override
|
||||
double formatterBitcoinAmountToDouble({required int amount})
|
||||
=> bitcoinAmountToDouble(amount: amount);
|
||||
|
||||
@override
|
||||
int formatterStringDoubleToBitcoinAmount(String amount)
|
||||
=> stringDoubleToBitcoinAmount(amount);
|
||||
@override
|
||||
TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate)
|
||||
=> (priority as BitcoinTransactionPriority).labelWithRate(rate);
|
||||
|
||||
@override
|
||||
List<BitcoinUnspent> getUnspents(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.unspentCoins;
|
||||
}
|
||||
|
||||
Future<void> updateUnspents(Object wallet) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.updateUnspent();
|
||||
}
|
||||
|
||||
WalletService createBitcoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return BitcoinWalletService(walletInfoSource, unspentCoinSource);
|
||||
}
|
||||
|
||||
WalletService createLitecoinWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return LitecoinWalletService(walletInfoSource, unspentCoinSource);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getBitcoinTransactionPriorityMedium()
|
||||
=> BitcoinTransactionPriority.medium;
|
||||
WalletCredentials createBitcoinRestoreWalletFromSeedCredentials(
|
||||
{required String name, required String mnemonic, required String password}) =>
|
||||
BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password);
|
||||
|
||||
@override
|
||||
TransactionPriority getLitecoinTransactionPriorityMedium()
|
||||
=> LitecoinTransactionPriority.medium;
|
||||
WalletCredentials createBitcoinRestoreWalletFromWIFCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required String wif,
|
||||
WalletInfo? walletInfo}) =>
|
||||
BitcoinRestoreWalletFromWIFCredentials(
|
||||
name: name, password: password, wif: wif, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
TransactionPriority getBitcoinTransactionPrioritySlow()
|
||||
=> BitcoinTransactionPriority.slow;
|
||||
|
||||
WalletCredentials createBitcoinNewWalletCredentials(
|
||||
{required String name, WalletInfo? walletInfo}) =>
|
||||
BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
TransactionPriority getLitecoinTransactionPrioritySlow()
|
||||
=> LitecoinTransactionPriority.slow;
|
||||
}
|
||||
List<String> getWordList() => wordlist;
|
||||
|
||||
@override
|
||||
Map<String, String> getWalletKeys(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
final keys = bitcoinWallet.keys;
|
||||
|
||||
return <String, String>{
|
||||
'wif': keys.wif,
|
||||
'privateKey': keys.privateKey,
|
||||
'publicKey': keys.publicKey
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() => BitcoinTransactionPriority.all;
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getLitecoinTransactionPriorities() => LitecoinTransactionPriority.all;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeBitcoinTransactionPriority(int raw) =>
|
||||
BitcoinTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeLitecoinTransactionPriority(int raw) =>
|
||||
LitecoinTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
int getFeeRate(Object wallet, TransactionPriority priority) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.feeRate(priority);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateNewAddress(Object wallet, String label) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.walletAddresses.generateNewAddress(label: label);
|
||||
await wallet.save();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateAddress(Object wallet, String address, String label) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
bitcoinWallet.walletAddresses.updateAddress(address, label);
|
||||
await wallet.save();
|
||||
}
|
||||
|
||||
@override
|
||||
Object createBitcoinTransactionCredentials(List<Output> outputs,
|
||||
{required TransactionPriority priority, int? feeRate}) =>
|
||||
BitcoinTransactionCredentials(
|
||||
outputs
|
||||
.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as BitcoinTransactionPriority,
|
||||
feeRate: feeRate);
|
||||
|
||||
@override
|
||||
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs,
|
||||
{TransactionPriority? priority, required int feeRate}) =>
|
||||
BitcoinTransactionCredentials(outputs,
|
||||
priority: priority != null ? priority as BitcoinTransactionPriority : null,
|
||||
feeRate: feeRate);
|
||||
|
||||
@override
|
||||
List<String> getAddresses(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.walletAddresses.addressesByReceiveType
|
||||
.map((BitcoinAddressRecord addr) => addr.address)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@computed
|
||||
List<ElectrumSubAddress> getSubAddresses(Object wallet) {
|
||||
final electrumWallet = wallet as ElectrumWallet;
|
||||
return electrumWallet.walletAddresses.addressesByReceiveType
|
||||
.map((BitcoinAddressRecord addr) => ElectrumSubAddress(
|
||||
id: addr.index,
|
||||
name: addr.name,
|
||||
address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address,
|
||||
txCount: addr.txCount,
|
||||
balance: addr.balance,
|
||||
isChange: addr.isHidden))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.walletAddresses.address;
|
||||
}
|
||||
|
||||
@override
|
||||
String formatterBitcoinAmountToString({required int amount}) =>
|
||||
bitcoinAmountToString(amount: amount);
|
||||
|
||||
@override
|
||||
double formatterBitcoinAmountToDouble({required int amount}) =>
|
||||
bitcoinAmountToDouble(amount: amount);
|
||||
|
||||
@override
|
||||
int formatterStringDoubleToBitcoinAmount(String amount) => stringDoubleToBitcoinAmount(amount);
|
||||
|
||||
@override
|
||||
String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) =>
|
||||
(priority as BitcoinTransactionPriority).labelWithRate(rate);
|
||||
|
||||
@override
|
||||
List<BitcoinUnspent> getUnspents(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return bitcoinWallet.unspentCoins;
|
||||
}
|
||||
|
||||
Future<void> updateUnspents(Object wallet) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.updateUnspent();
|
||||
}
|
||||
|
||||
WalletService createBitcoinWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return BitcoinWalletService(walletInfoSource, unspentCoinSource);
|
||||
}
|
||||
|
||||
WalletService createLitecoinWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return LitecoinWalletService(walletInfoSource, unspentCoinSource);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getBitcoinTransactionPriorityMedium() => BitcoinTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
TransactionPriority getLitecoinTransactionPriorityMedium() => LitecoinTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
TransactionPriority getBitcoinTransactionPrioritySlow() => BitcoinTransactionPriority.slow;
|
||||
|
||||
@override
|
||||
TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow;
|
||||
|
||||
@override
|
||||
Future<void> setAddressType(Object wallet, dynamic option) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType);
|
||||
}
|
||||
|
||||
@override
|
||||
BitcoinReceivePageOption getSelectedAddressType(Object wallet) {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType);
|
||||
}
|
||||
|
||||
@override
|
||||
List<BitcoinReceivePageOption> getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
@@ -9,7 +9,9 @@ class AddressValidator extends TextValidator {
|
||||
AddressValidator({required CryptoCurrency type})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_address,
|
||||
useAdditionalValidation: type == CryptoCurrency.btc ? bitcoin.Address.validateAddress : null,
|
||||
useAdditionalValidation: type == CryptoCurrency.btc
|
||||
? (String txt) => validateAddress(address: txt, network: BitcoinNetwork.mainnet)
|
||||
: null,
|
||||
pattern: getPattern(type),
|
||||
length: getLength(type));
|
||||
|
||||
@@ -24,7 +26,7 @@ class AddressValidator extends TextValidator {
|
||||
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
|
||||
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
|
||||
case CryptoCurrency.btc:
|
||||
return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$';
|
||||
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$';
|
||||
case CryptoCurrency.nano:
|
||||
return '[0-9a-zA-Z_]';
|
||||
case CryptoCurrency.banano:
|
||||
@@ -89,7 +91,7 @@ class AddressValidator extends TextValidator {
|
||||
case CryptoCurrency.dai:
|
||||
case CryptoCurrency.dash:
|
||||
case CryptoCurrency.eos:
|
||||
return '[0-9a-zA-Z]';
|
||||
return '[0-9a-zA-Z]';
|
||||
case CryptoCurrency.bch:
|
||||
return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$';
|
||||
case CryptoCurrency.bnb:
|
||||
@@ -268,12 +270,11 @@ class AddressValidator extends TextValidator {
|
||||
'|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)';
|
||||
case CryptoCurrency.btc:
|
||||
return '([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{39}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{59}([^0-9a-zA-Z]|\$)';
|
||||
return '([^0-9a-zA-Z]|^)${P2pkhAddress.regex.pattern}|\$)'
|
||||
'([^0-9a-zA-Z]|^)${P2shAddress.regex.pattern}|\$)'
|
||||
'([^0-9a-zA-Z]|^)${P2wpkhAddress.regex.pattern}|\$)'
|
||||
'([^0-9a-zA-Z]|^)${P2wshAddress.regex.pattern}|\$)'
|
||||
'([^0-9a-zA-Z]|^)${P2trAddress.regex.pattern}|\$)';
|
||||
case CryptoCurrency.ltc:
|
||||
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]|\$)'
|
||||
@@ -297,4 +298,4 @@ class AddressValidator extends TextValidator {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -55,7 +54,7 @@ class WalletCreationService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<WalletBase> create(WalletCredentials credentials) async {
|
||||
Future<WalletBase> create(WalletCredentials credentials, {bool? isTestnet}) async {
|
||||
checkIfExists(credentials.name);
|
||||
final password = generateWalletPassword();
|
||||
credentials.password = password;
|
||||
@@ -63,7 +62,7 @@ class WalletCreationService {
|
||||
credentials.seedPhraseLength = settingsStore.seedPhraseLength.value;
|
||||
}
|
||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service!.create(credentials);
|
||||
final wallet = await _service!.create(credentials, isTestnet: isTestnet);
|
||||
|
||||
if (wallet.type == WalletType.monero) {
|
||||
await sharedPreferences.setBool(
|
||||
@@ -73,12 +72,12 @@ class WalletCreationService {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Future<WalletBase> restoreFromKeys(WalletCredentials credentials) async {
|
||||
Future<WalletBase> restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) async {
|
||||
checkIfExists(credentials.name);
|
||||
final password = generateWalletPassword();
|
||||
credentials.password = password;
|
||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service!.restoreFromKeys(credentials);
|
||||
final wallet = await _service!.restoreFromKeys(credentials, isTestnet: isTestnet);
|
||||
|
||||
if (wallet.type == WalletType.monero) {
|
||||
await sharedPreferences.setBool(
|
||||
@@ -88,12 +87,12 @@ class WalletCreationService {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
Future<WalletBase> restoreFromSeed(WalletCredentials credentials) async {
|
||||
Future<WalletBase> restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) async {
|
||||
checkIfExists(credentials.name);
|
||||
final password = generateWalletPassword();
|
||||
credentials.password = password;
|
||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service!.restoreFromSeed(credentials);
|
||||
final wallet = await _service!.restoreFromSeed(credentials, isTestnet: isTestnet);
|
||||
|
||||
if (wallet.type == WalletType.monero) {
|
||||
await sharedPreferences.setBool(
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import 'package:cake_wallet/core/yat_service.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_anypay.dart';
|
||||
|
||||
@@ -23,6 +23,10 @@ import 'package:collection/collection.dart';
|
||||
|
||||
const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081';
|
||||
const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002';
|
||||
const publicBitcoinTestnetElectrumAddress = 'electrum.blockstream.info';
|
||||
const publicBitcoinTestnetElectrumPort = '60002';
|
||||
const publicBitcoinTestnetElectrumUri =
|
||||
'$publicBitcoinTestnetElectrumAddress:$publicBitcoinTestnetElectrumPort';
|
||||
const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002';
|
||||
const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
|
||||
const ethereumDefaultNodeUri = 'ethereum.publicnode.com';
|
||||
@@ -334,6 +338,12 @@ Node? getBitcoinDefaultElectrumServer({required Box<Node> nodes}) {
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
|
||||
}
|
||||
|
||||
Node? getBitcoinTestnetDefaultElectrumServer({required Box<Node> nodes}) {
|
||||
return nodes.values
|
||||
.firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
|
||||
}
|
||||
|
||||
Node? getLitecoinDefaultElectrumServer({required Box<Node> nodes}) {
|
||||
return nodes.values
|
||||
.firstWhereOrNull((Node node) => node.uriRaw == cakeWalletLitecoinElectrumUri) ??
|
||||
@@ -503,8 +513,15 @@ Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorag
|
||||
}
|
||||
|
||||
Future<void> changeBitcoinCurrentElectrumServerToDefault(
|
||||
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
|
||||
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
||||
{required SharedPreferences sharedPreferences,
|
||||
required Box<Node> nodes,
|
||||
bool? isTestnet}) async {
|
||||
Node? server;
|
||||
if (isTestnet == true) {
|
||||
server = getBitcoinTestnetDefaultElectrumServer(nodes: nodes);
|
||||
} else {
|
||||
server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
||||
}
|
||||
final serverId = server?.key as int? ?? 0;
|
||||
|
||||
await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId);
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
enum ReceivePageOption {
|
||||
mainnet,
|
||||
anonPayInvoice,
|
||||
anonPayDonationLink;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
String label = '';
|
||||
switch (this) {
|
||||
case ReceivePageOption.mainnet:
|
||||
label = 'Mainnet';
|
||||
break;
|
||||
case ReceivePageOption.anonPayInvoice:
|
||||
label = 'Trocador AnonPay Invoice';
|
||||
break;
|
||||
case ReceivePageOption.anonPayDonationLink:
|
||||
label = 'Trocador AnonPay Donation Link';
|
||||
break;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
+10
-4
@@ -532,13 +532,19 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
builder: (_) => getIt.get<WebViewPage>(param1: title, param2: url));
|
||||
|
||||
case Routes.advancedPrivacySettings:
|
||||
final type = settings.arguments as WalletType;
|
||||
final args = settings.arguments as Map<String, dynamic>;
|
||||
final type = args['type'] as WalletType;
|
||||
final useTestnet = args['useTestnet'] as bool;
|
||||
final toggleTestnet = args['toggleTestnet'] as Function(bool? val);
|
||||
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => AdvancedPrivacySettingsPage(
|
||||
getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
|
||||
getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
|
||||
getIt.get<SeedTypeViewModel>()));
|
||||
useTestnet,
|
||||
toggleTestnet,
|
||||
getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
|
||||
getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
|
||||
getIt.get<SeedTypeViewModel>(),
|
||||
));
|
||||
|
||||
case Routes.anonPayInvoicePage:
|
||||
final args = settings.arguments as List;
|
||||
|
||||
@@ -5,7 +5,8 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
@@ -27,6 +28,7 @@ import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
|
||||
class AddressPage extends BasePage {
|
||||
AddressPage({
|
||||
@@ -69,7 +71,7 @@ class AddressPage extends BasePage {
|
||||
size: 16,
|
||||
);
|
||||
final _closeButton =
|
||||
currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
|
||||
currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
|
||||
|
||||
bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI;
|
||||
|
||||
@@ -163,11 +165,10 @@ class AddressPage extends BasePage {
|
||||
return SelectButton(
|
||||
text: addressListViewModel.buttonTitle,
|
||||
onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled &&
|
||||
(WalletType.monero == addressListViewModel.wallet.type ||
|
||||
WalletType.haven == addressListViewModel.wallet.type)
|
||||
(WalletType.monero == addressListViewModel.wallet.type ||
|
||||
WalletType.haven == addressListViewModel.wallet.type)
|
||||
? await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => getIt.get<MoneroAccountListPage>())
|
||||
context: context, builder: (_) => getIt.get<MoneroAccountListPage>())
|
||||
: Navigator.of(context).pushNamed(Routes.receive),
|
||||
textColor: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor,
|
||||
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
|
||||
@@ -229,6 +230,21 @@ class AddressPage extends BasePage {
|
||||
);
|
||||
}
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2pkh:
|
||||
addressListViewModel.setAddressType(P2pkhAddressType.p2pkh);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2sh:
|
||||
addressListViewModel.setAddressType(P2shAddressType.p2wpkhInP2sh);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2wpkh:
|
||||
addressListViewModel.setAddressType(SegwitAddresType.p2wpkh);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2tr:
|
||||
addressListViewModel.setAddressType(SegwitAddresType.p2tr);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2wsh:
|
||||
addressListViewModel.setAddressType(SegwitAddresType.p2wsh);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cake_wallet/entities/default_settings_migration.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
@@ -11,6 +12,7 @@ import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
@@ -19,7 +21,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
|
||||
class AdvancedPrivacySettingsPage extends BasePage {
|
||||
AdvancedPrivacySettingsPage(
|
||||
AdvancedPrivacySettingsPage(this.useTestnet, this.toggleUseTestnet,
|
||||
this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel);
|
||||
|
||||
final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
|
||||
@@ -29,13 +31,16 @@ class AdvancedPrivacySettingsPage extends BasePage {
|
||||
@override
|
||||
String get title => S.current.privacy_settings;
|
||||
|
||||
final bool useTestnet;
|
||||
final Function(bool? val) toggleUseTestnet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => AdvancedPrivacySettingsBody(
|
||||
Widget body(BuildContext context) => AdvancedPrivacySettingsBody(useTestnet, toggleUseTestnet,
|
||||
advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel);
|
||||
}
|
||||
|
||||
class AdvancedPrivacySettingsBody extends StatefulWidget {
|
||||
const AdvancedPrivacySettingsBody(
|
||||
const AdvancedPrivacySettingsBody(this.useTestnet, this.toggleUseTestnet,
|
||||
this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel,
|
||||
{Key? key})
|
||||
: super(key: key);
|
||||
@@ -44,6 +49,9 @@ class AdvancedPrivacySettingsBody extends StatefulWidget {
|
||||
final NodeCreateOrEditViewModel nodeViewModel;
|
||||
final SeedTypeViewModel seedTypeViewModel;
|
||||
|
||||
final bool useTestnet;
|
||||
final Function(bool? val) toggleUseTestnet;
|
||||
|
||||
@override
|
||||
_AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState();
|
||||
}
|
||||
@@ -52,9 +60,14 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
||||
_AdvancedPrivacySettingsBodyState();
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool? testnetValue;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (testnetValue == null && widget.useTestnet != null) {
|
||||
testnetValue = widget.useTestnet;
|
||||
}
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
@@ -125,6 +138,19 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
||||
),
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.type == WalletType.bitcoin)
|
||||
Builder(builder: (_) {
|
||||
final val = testnetValue!;
|
||||
return SettingsSwitcherCell(
|
||||
title: S.current.use_testnet,
|
||||
value: val,
|
||||
onValueChange: (_, __) {
|
||||
setState(() {
|
||||
testnetValue = !val;
|
||||
});
|
||||
widget.toggleUseTestnet!.call(testnetValue);
|
||||
});
|
||||
}),
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.all(24),
|
||||
@@ -137,6 +163,13 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
||||
return;
|
||||
}
|
||||
|
||||
widget.nodeViewModel.save();
|
||||
} else if (testnetValue == true) {
|
||||
// TODO: add type (mainnet/testnet) to Node class so when switching wallets the node can be switched to a matching type
|
||||
// Currently this is so you can create a working testnet wallet but you need to keep switching back the node if you use multiple wallets at once
|
||||
widget.nodeViewModel.address = publicBitcoinTestnetElectrumAddress;
|
||||
widget.nodeViewModel.port = publicBitcoinTestnetElectrumPort;
|
||||
|
||||
widget.nodeViewModel.save();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ class NewWalletPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletNameForm(
|
||||
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _seedTypeViewModel);
|
||||
_walletNewVM,
|
||||
currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage,
|
||||
_seedTypeViewModel);
|
||||
}
|
||||
|
||||
class WalletNameForm extends StatefulWidget {
|
||||
@@ -187,7 +189,6 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (_walletNewVM.hasLanguageSelector) ...[
|
||||
if (_walletNewVM.hasSeedType) ...[
|
||||
Observer(
|
||||
@@ -222,7 +223,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
),
|
||||
),
|
||||
)
|
||||
]
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -245,8 +246,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
const SizedBox(height: 25),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type);
|
||||
Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: {
|
||||
"type": _walletNewVM.type,
|
||||
"useTestnet": _walletNewVM.useTestnet,
|
||||
"toggleTestnet": _walletNewVM.toggleUseTestnet
|
||||
});
|
||||
},
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
||||
@@ -210,8 +210,12 @@ class WalletRestorePage extends BasePage {
|
||||
const SizedBox(height: 25),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(Routes.advancedPrivacySettings,
|
||||
arguments: walletRestoreViewModel.type);
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: {
|
||||
'type': walletRestoreViewModel.type,
|
||||
'useTestnet': walletRestoreViewModel.useTestnet,
|
||||
'toggleTestnet': walletRestoreViewModel.toggleUseTestnet
|
||||
});
|
||||
},
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_request.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
|
||||
@@ -148,17 +148,21 @@ abstract class DashboardViewModelBase with Store {
|
||||
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
.toList();
|
||||
|
||||
transactions = ObservableList.of(_accountTransactions.map((transaction) =>
|
||||
TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
final sortedTransactions = [..._accountTransactions];
|
||||
sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
|
||||
|
||||
transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
} else {
|
||||
transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map(
|
||||
(transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
final sortedTransactions = [...wallet.transactionHistory.transactions.values];
|
||||
sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
|
||||
|
||||
transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
}
|
||||
|
||||
// TODO: nano sub-account generation is disabled:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -9,11 +10,20 @@ class ReceiveOptionViewModel = ReceiveOptionViewModelBase with _$ReceiveOptionVi
|
||||
|
||||
abstract class ReceiveOptionViewModelBase with Store {
|
||||
ReceiveOptionViewModelBase(this._wallet, this.initialPageOption)
|
||||
: selectedReceiveOption = initialPageOption ?? ReceivePageOption.mainnet,
|
||||
: selectedReceiveOption = initialPageOption ??
|
||||
(_wallet.type == WalletType.bitcoin
|
||||
? bitcoin!.getSelectedAddressType(_wallet)
|
||||
: ReceivePageOption.mainnet),
|
||||
_options = [] {
|
||||
final walletType = _wallet.type;
|
||||
_options =
|
||||
walletType == WalletType.haven ? [ReceivePageOption.mainnet] : ReceivePageOption.values;
|
||||
_options = walletType == WalletType.haven
|
||||
? [ReceivePageOption.mainnet]
|
||||
: walletType == WalletType.bitcoin
|
||||
? [
|
||||
...bitcoin!.getBitcoinReceivePageOptions(),
|
||||
...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet)
|
||||
]
|
||||
: ReceivePageOptions;
|
||||
}
|
||||
|
||||
final WalletBase _wallet;
|
||||
|
||||
@@ -65,6 +65,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
||||
bool get hasAuthCredentials =>
|
||||
_walletType == WalletType.monero || _walletType == WalletType.haven;
|
||||
|
||||
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
|
||||
|
||||
String get uri {
|
||||
var uri = address;
|
||||
|
||||
|
||||
@@ -52,7 +52,11 @@ abstract class NodeListViewModelBase with Store {
|
||||
|
||||
switch (_appStore.wallet!.type) {
|
||||
case WalletType.bitcoin:
|
||||
node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!;
|
||||
if (_appStore.wallet!.isTestnet == true) {
|
||||
node = getBitcoinTestnetDefaultElectrumServer(nodes: _nodeSource)!;
|
||||
} else {
|
||||
node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!;
|
||||
}
|
||||
break;
|
||||
case WalletType.monero:
|
||||
node = getMoneroDefaultNode(nodes: _nodeSource);
|
||||
|
||||
@@ -119,7 +119,7 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
case WalletType.monero:
|
||||
return 'https://monero.com/tx/${txId}';
|
||||
case WalletType.bitcoin:
|
||||
return 'https://mempool.space/tx/${txId}';
|
||||
return 'https://mempool.space/${wallet.isTestnet == true ? "testnet/" : ""}tx/${txId}';
|
||||
case WalletType.litecoin:
|
||||
return 'https://blockchair.com/litecoin/transaction/${txId}';
|
||||
case WalletType.bitcoinCash:
|
||||
|
||||
@@ -388,9 +388,6 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
wallet.type == WalletType.bitcoin ||
|
||||
wallet.type == WalletType.litecoin;
|
||||
|
||||
// wallet.type == WalletType.nano ||
|
||||
// wallet.type == WalletType.banano; TODO: nano accounts are disabled for now
|
||||
|
||||
@computed
|
||||
bool get isElectrumWallet =>
|
||||
wallet.type == WalletType.bitcoin ||
|
||||
@@ -409,16 +406,17 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
void setAddress(WalletAddressListItem address) =>
|
||||
wallet.walletAddresses.address = address.address;
|
||||
|
||||
@action
|
||||
Future<void> setAddressType(dynamic option) async {
|
||||
if (wallet.type == WalletType.bitcoin) {
|
||||
await bitcoin!.setAddressType(wallet, option);
|
||||
}
|
||||
}
|
||||
|
||||
void _init() {
|
||||
_baseItems = [];
|
||||
|
||||
if (wallet.type == WalletType.monero ||
|
||||
wallet.type ==
|
||||
WalletType
|
||||
.haven /*||
|
||||
wallet.type == WalletType.nano ||
|
||||
wallet.type == WalletType.banano*/
|
||||
) {
|
||||
if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) {
|
||||
_baseItems.add(WalletAccountListHeader());
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ abstract class WalletCreationVMBase with Store {
|
||||
: state = InitialExecutionState(),
|
||||
name = '';
|
||||
|
||||
@observable
|
||||
bool _useTestnet = false;
|
||||
|
||||
@computed
|
||||
bool get useTestnet => _useTestnet;
|
||||
|
||||
@observable
|
||||
String name;
|
||||
|
||||
@@ -94,4 +100,9 @@ abstract class WalletCreationVMBase with Store {
|
||||
Future<WalletBase> processFromRestoredWallet(
|
||||
WalletCredentials credentials, RestoredWallet restoreWallet) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@action
|
||||
void toggleUseTestnet(bool? value) {
|
||||
_useTestnet = value ?? !_useTestnet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
@override
|
||||
Future<WalletBase> process(WalletCredentials credentials) async {
|
||||
walletCreationService.changeWalletType(type: type);
|
||||
return walletCreationService.create(credentials);
|
||||
return walletCreationService.create(credentials, isTestnet: useTestnet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,9 +207,9 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
@override
|
||||
Future<WalletBase> process(WalletCredentials credentials) async {
|
||||
if (mode == WalletRestoreMode.keys) {
|
||||
return walletCreationService.restoreFromKeys(credentials);
|
||||
return walletCreationService.restoreFromKeys(credentials, isTestnet: useTestnet);
|
||||
}
|
||||
|
||||
return walletCreationService.restoreFromSeed(credentials);
|
||||
return walletCreationService.restoreFromSeed(credentials, isTestnet: useTestnet);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user