mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-11 17:06:34 +00:00
Merge branch 'refs/heads/main' into ui-enhancements
# Conflicts: # res/values/strings_ar.arb # res/values/strings_bg.arb # res/values/strings_cs.arb # res/values/strings_de.arb # res/values/strings_en.arb # res/values/strings_es.arb # res/values/strings_fr.arb # res/values/strings_ha.arb # res/values/strings_hi.arb # res/values/strings_hr.arb # res/values/strings_hy.arb # res/values/strings_id.arb # res/values/strings_it.arb # res/values/strings_ja.arb # res/values/strings_ko.arb # res/values/strings_my.arb # res/values/strings_nl.arb # res/values/strings_pl.arb # res/values/strings_pt.arb # res/values/strings_ru.arb # res/values/strings_th.arb # res/values/strings_tl.arb # res/values/strings_tr.arb # res/values/strings_uk.arb # res/values/strings_ur.arb # res/values/strings_vi.arb # res/values/strings_yo.arb # res/values/strings_zh.arb
This commit is contained in:
commit
98b1c149f0
41 changed files with 393 additions and 378 deletions
assets/text
cw_bitcoin/lib
cw_core/lib
cw_evm/lib
cw_monero/lib
cw_nano/lib
cw_solana/lib
ios
lib
bitcoin
buy/robinhood
cake_pay
entities
monero
src/screens
buy
dashboard/pages/balance
seed/seed_verification
send
utils
view_model
linux
scripts
tool
|
@ -1,3 +1,2 @@
|
||||||
Support Monero Ledger
|
UI enhancements
|
||||||
Bug fixes
|
Bug fixes
|
||||||
New designs and better user experience
|
|
|
@ -1,5 +1,4 @@
|
||||||
Support Monero Ledger
|
Bitcoin and Litecoin enhancements
|
||||||
Prepare for Haven removal
|
Solana and Nano fixes/improvements
|
||||||
Improve Ethereum and Polygon sending process
|
UI enhancements
|
||||||
Bug fixes
|
Bug fixes
|
||||||
New designs and better user experience
|
|
|
@ -4,7 +4,6 @@ import 'dart:io';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
|
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||||
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
||||||
|
@ -991,6 +990,9 @@ abstract class ElectrumWalletBase
|
||||||
@override
|
@override
|
||||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||||
try {
|
try {
|
||||||
|
// start by updating unspent coins
|
||||||
|
await updateAllUnspents();
|
||||||
|
|
||||||
final outputs = <BitcoinOutput>[];
|
final outputs = <BitcoinOutput>[];
|
||||||
final transactionCredentials = credentials as BitcoinTransactionCredentials;
|
final transactionCredentials = credentials as BitcoinTransactionCredentials;
|
||||||
final hasMultiDestination = transactionCredentials.outputs.length > 1;
|
final hasMultiDestination = transactionCredentials.outputs.length > 1;
|
||||||
|
|
|
@ -349,8 +349,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
type: addressPageType,
|
type: addressPageType,
|
||||||
network: network,
|
network: network,
|
||||||
);
|
);
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
_addresses.add(address);
|
_addresses.add(address);
|
||||||
Future.delayed(Duration.zero, () => updateAddressesByMatch());
|
updateAddressesByMatch();
|
||||||
|
});
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:cw_core/monero_amount_format.dart';
|
||||||
class MoneroBalance extends Balance {
|
class MoneroBalance extends Balance {
|
||||||
MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
||||||
: formattedUnconfirmedBalance = moneroAmountToString(amount: fullBalance - unlockedBalance),
|
: formattedUnconfirmedBalance = moneroAmountToString(amount: fullBalance - unlockedBalance),
|
||||||
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance - frozenBalance),
|
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance),
|
||||||
formattedFrozenBalance = moneroAmountToString(amount: frozenBalance),
|
formattedFrozenBalance = moneroAmountToString(amount: frozenBalance),
|
||||||
super(unlockedBalance, fullBalance);
|
super(unlockedBalance, fullBalance);
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ class Node extends HiveObject with Keyable {
|
||||||
return requestMoneroNode();
|
return requestMoneroNode();
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
case WalletType.banano:
|
case WalletType.banano:
|
||||||
|
return requestNanoNode();
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
|
@ -198,14 +199,16 @@ class Node extends HiveObject with Keyable {
|
||||||
);
|
);
|
||||||
client.close();
|
client.close();
|
||||||
|
|
||||||
if ((
|
if ((response.body.contains("400 Bad Request") // Some other generic error
|
||||||
response.body.contains("400 Bad Request") // Some other generic error
|
||
|
||||||
|| response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare
|
response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare
|
||||||
|| response.headers["location"] != null // Generic reverse proxy
|
||
|
||||||
|| response.body.contains("301 Moved Permanently") // Poorly configured generic reverse proxy
|
response.headers["location"] != null // Generic reverse proxy
|
||||||
) && !(useSSL??false)
|
||
|
||||||
) {
|
response.body
|
||||||
|
.contains("301 Moved Permanently") // Poorly configured generic reverse proxy
|
||||||
|
) &&
|
||||||
|
!(useSSL ?? false)) {
|
||||||
final oldUseSSL = useSSL;
|
final oldUseSSL = useSSL;
|
||||||
useSSL = true;
|
useSSL = true;
|
||||||
try {
|
try {
|
||||||
|
@ -271,6 +274,35 @@ class Node extends HiveObject with Keyable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> requestNanoNode() async {
|
||||||
|
try {
|
||||||
|
final response = await http.post(
|
||||||
|
uri,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"nano-app": "cake-wallet"
|
||||||
|
},
|
||||||
|
body: jsonEncode(
|
||||||
|
{
|
||||||
|
"action": "account_balance",
|
||||||
|
"account": "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final data = await jsonDecode(response.body);
|
||||||
|
if (response.statusCode != 200 ||
|
||||||
|
data["error"] != null ||
|
||||||
|
data["balance"] == null ||
|
||||||
|
data["receivable"] == null) {
|
||||||
|
throw Exception(
|
||||||
|
"Error while trying to get balance! ${data["error"] != null ? data["error"] : ""}");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> requestEthereumServer() async {
|
Future<bool> requestEthereumServer() async {
|
||||||
try {
|
try {
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:cw_core/wownero_amount_format.dart';
|
||||||
class WowneroBalance extends Balance {
|
class WowneroBalance extends Balance {
|
||||||
WowneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
WowneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
||||||
: formattedUnconfirmedBalance = wowneroAmountToString(amount: fullBalance - unlockedBalance),
|
: formattedUnconfirmedBalance = wowneroAmountToString(amount: fullBalance - unlockedBalance),
|
||||||
formattedUnlockedBalance = wowneroAmountToString(amount: unlockedBalance - frozenBalance),
|
formattedUnlockedBalance = wowneroAmountToString(amount: unlockedBalance),
|
||||||
formattedFrozenBalance =
|
formattedFrozenBalance =
|
||||||
wowneroAmountToString(amount: frozenBalance),
|
wowneroAmountToString(amount: frozenBalance),
|
||||||
super(unlockedBalance, fullBalance);
|
super(unlockedBalance, fullBalance);
|
||||||
|
|
|
@ -29,7 +29,6 @@ import 'package:cw_evm/evm_chain_transaction_model.dart';
|
||||||
import 'package:cw_evm/evm_chain_transaction_priority.dart';
|
import 'package:cw_evm/evm_chain_transaction_priority.dart';
|
||||||
import 'package:cw_evm/evm_chain_wallet_addresses.dart';
|
import 'package:cw_evm/evm_chain_wallet_addresses.dart';
|
||||||
import 'package:cw_evm/evm_ledger_credentials.dart';
|
import 'package:cw_evm/evm_ledger_credentials.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:hex/hex.dart';
|
import 'package:hex/hex.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -348,7 +347,7 @@ abstract class EVMChainWalletBase
|
||||||
final CryptoCurrency transactionCurrency =
|
final CryptoCurrency transactionCurrency =
|
||||||
balance.keys.firstWhere((element) => element.title == _credentials.currency.title);
|
balance.keys.firstWhere((element) => element.title == _credentials.currency.title);
|
||||||
|
|
||||||
final erc20Balance = balance[transactionCurrency]!;
|
final currencyBalance = balance[transactionCurrency]!;
|
||||||
BigInt totalAmount = BigInt.zero;
|
BigInt totalAmount = BigInt.zero;
|
||||||
BigInt estimatedFeesForTransaction = BigInt.zero;
|
BigInt estimatedFeesForTransaction = BigInt.zero;
|
||||||
int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
|
int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
|
||||||
|
@ -385,7 +384,7 @@ abstract class EVMChainWalletBase
|
||||||
estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits;
|
estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits;
|
||||||
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
|
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
|
||||||
|
|
||||||
if (erc20Balance.balance < totalAmount) {
|
if (currencyBalance.balance < totalAmount) {
|
||||||
throw EVMChainTransactionCreationException(transactionCurrency);
|
throw EVMChainTransactionCreationException(transactionCurrency);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,7 +397,7 @@ abstract class EVMChainWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.sendAll && transactionCurrency is Erc20Token) {
|
if (output.sendAll && transactionCurrency is Erc20Token) {
|
||||||
totalAmount = erc20Balance.balance;
|
totalAmount = currencyBalance.balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction(
|
final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction(
|
||||||
|
@ -413,14 +412,15 @@ abstract class EVMChainWalletBase
|
||||||
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
|
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
|
||||||
|
|
||||||
if (output.sendAll && transactionCurrency is! Erc20Token) {
|
if (output.sendAll && transactionCurrency is! Erc20Token) {
|
||||||
totalAmount = (erc20Balance.balance - estimatedFeesForTransaction);
|
totalAmount = (currencyBalance.balance - estimatedFeesForTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
if (estimatedFeesForTransaction > erc20Balance.balance) {
|
// check the fees on the base currency (Eth/Polygon)
|
||||||
|
if (estimatedFeesForTransaction > balance[currency]!.balance) {
|
||||||
throw EVMChainTransactionFeesException();
|
throw EVMChainTransactionFeesException();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (erc20Balance.balance < totalAmount) {
|
if (currencyBalance.balance < totalAmount) {
|
||||||
throw EVMChainTransactionCreationException(transactionCurrency);
|
throw EVMChainTransactionCreationException(transactionCurrency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,9 +126,11 @@ Future<bool> setupNodeSync(
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
final error = monero.Wallet_errorString(wptr!);
|
final error = monero.Wallet_errorString(wptr!);
|
||||||
|
if (error != "no tx keys found for this txid") {
|
||||||
printV("error: $error");
|
printV("error: $error");
|
||||||
throw SetupWalletException(message: error);
|
throw SetupWalletException(message: error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
monero.Wallet_init3(
|
monero.Wallet_init3(
|
||||||
|
|
|
@ -7,7 +7,6 @@ import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/account.dart';
|
import 'package:cw_core/account.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/monero_amount_format.dart';
|
|
||||||
import 'package:cw_core/monero_balance.dart';
|
import 'package:cw_core/monero_balance.dart';
|
||||||
import 'package:cw_core/monero_transaction_priority.dart';
|
import 'package:cw_core/monero_transaction_priority.dart';
|
||||||
import 'package:cw_core/monero_wallet_keys.dart';
|
import 'package:cw_core/monero_wallet_keys.dart';
|
||||||
|
@ -28,7 +27,6 @@ import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
|
||||||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||||
import 'package:cw_monero/api/wallet_manager.dart';
|
import 'package:cw_monero/api/wallet_manager.dart';
|
||||||
import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart';
|
import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart';
|
||||||
import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart';
|
|
||||||
import 'package:cw_monero/ledger.dart';
|
import 'package:cw_monero/ledger.dart';
|
||||||
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
|
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
|
||||||
import 'package:cw_monero/monero_transaction_history.dart';
|
import 'package:cw_monero/monero_transaction_history.dart';
|
||||||
|
@ -59,7 +57,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
|
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
|
||||||
CryptoCurrency.xmr: MoneroBalance(
|
CryptoCurrency.xmr: MoneroBalance(
|
||||||
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
||||||
unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0))
|
unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: 0),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_isTransactionUpdating = false,
|
_isTransactionUpdating = false,
|
||||||
_hasSyncAfterStartup = false,
|
_hasSyncAfterStartup = false,
|
||||||
|
@ -265,6 +264,14 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needExportOutputs(int amount) {
|
||||||
|
// viewOnlyBalance - balance that we can spend
|
||||||
|
// TODO(mrcyjanek): remove hasUnknownKeyImages when we cleanup coin control
|
||||||
|
return (monero.Wallet_viewOnlyBalance(wptr!,
|
||||||
|
accountIndex: walletAddresses.account!.id) < amount) ||
|
||||||
|
monero.Wallet_hasUnknownKeyImages(wptr!);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||||
final _credentials = credentials as MoneroTransactionCreationCredentials;
|
final _credentials = credentials as MoneroTransactionCreationCredentials;
|
||||||
|
@ -273,7 +280,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
final hasMultiDestination = outputs.length > 1;
|
final hasMultiDestination = outputs.length > 1;
|
||||||
final unlockedBalance = monero_wallet.getUnlockedBalance(
|
final unlockedBalance = monero_wallet.getUnlockedBalance(
|
||||||
accountIndex: walletAddresses.account!.id);
|
accountIndex: walletAddresses.account!.id);
|
||||||
var allInputsAmount = 0;
|
|
||||||
|
|
||||||
PendingTransactionDescription pendingTransactionDescription;
|
PendingTransactionDescription pendingTransactionDescription;
|
||||||
|
|
||||||
|
@ -287,11 +293,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
|
|
||||||
for (final utx in unspentCoins) {
|
for (final utx in unspentCoins) {
|
||||||
if (utx.isSending) {
|
if (utx.isSending) {
|
||||||
allInputsAmount += utx.value;
|
|
||||||
inputs.add(utx.keyImage!);
|
inputs.add(utx.keyImage!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final spendAllCoins = inputs.length == unspentCoins.length;
|
|
||||||
|
|
||||||
if (hasMultiDestination) {
|
if (hasMultiDestination) {
|
||||||
if (outputs.any(
|
if (outputs.any(
|
||||||
|
@ -303,8 +307,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
final int totalAmount = outputs.fold(
|
final int totalAmount = outputs.fold(
|
||||||
0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0));
|
0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0));
|
||||||
|
|
||||||
final estimatedFee =
|
|
||||||
calculateEstimatedFee(_credentials.priority, totalAmount);
|
|
||||||
if (unlockedBalance < totalAmount) {
|
if (unlockedBalance < totalAmount) {
|
||||||
throw MoneroTransactionCreationException(
|
throw MoneroTransactionCreationException(
|
||||||
'You do not have enough XMR to send this amount.');
|
'You do not have enough XMR to send this amount.');
|
||||||
|
@ -334,8 +336,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
output.isParsedAddress ? output.extractedAddress : output.address;
|
output.isParsedAddress ? output.extractedAddress : output.address;
|
||||||
final amount =
|
final amount =
|
||||||
output.sendAll ? null : output.cryptoAmount!.replaceAll(',', '.');
|
output.sendAll ? null : output.cryptoAmount!.replaceAll(',', '.');
|
||||||
final formattedAmount =
|
|
||||||
output.sendAll ? null : output.formattedCryptoAmount;
|
|
||||||
|
|
||||||
// if ((formattedAmount != null && unlockedBalance < formattedAmount) ||
|
// if ((formattedAmount != null && unlockedBalance < formattedAmount) ||
|
||||||
// (formattedAmount == null && unlockedBalance <= 0)) {
|
// (formattedAmount == null && unlockedBalance <= 0)) {
|
||||||
|
@ -345,8 +345,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
// 'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.');
|
// 'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.');
|
||||||
// }
|
// }
|
||||||
|
|
||||||
final estimatedFee =
|
|
||||||
calculateEstimatedFee(_credentials.priority, formattedAmount);
|
|
||||||
if (inputs.isEmpty) MoneroTransactionCreationException(
|
if (inputs.isEmpty) MoneroTransactionCreationException(
|
||||||
'No inputs selected');
|
'No inputs selected');
|
||||||
pendingTransactionDescription =
|
pendingTransactionDescription =
|
||||||
|
@ -742,26 +740,16 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
Future<void> _askForUpdateTransactionHistory() async =>
|
Future<void> _askForUpdateTransactionHistory() async =>
|
||||||
await updateTransactions();
|
await updateTransactions();
|
||||||
|
|
||||||
int _getFullBalance() =>
|
|
||||||
monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id);
|
|
||||||
|
|
||||||
int _getUnlockedBalance() => monero_wallet.getUnlockedBalance(
|
int _getUnlockedBalance() => monero_wallet.getUnlockedBalance(
|
||||||
accountIndex: walletAddresses.account!.id);
|
accountIndex: walletAddresses.account!.id);
|
||||||
|
|
||||||
int _getFrozenBalance() {
|
int _getFrozenBalance() {
|
||||||
var frozenBalance = 0;
|
var frozenBalance = 0;
|
||||||
|
|
||||||
unspentCoinsInfo.values.forEach((info) {
|
for (var coin in unspentCoinsInfo.values.where((element) =>
|
||||||
unspentCoins.forEach((element) {
|
element.walletId == id && element.accountIndex == walletAddresses.account!.id)) {
|
||||||
if (element.hash == info.hash &&
|
if (coin.isFrozen && !coin.isSending) frozenBalance += coin.value;
|
||||||
element.vout == info.vout &&
|
|
||||||
info.isFrozen &&
|
|
||||||
element.value == info.value && info.walletId == id &&
|
|
||||||
info.accountIndex == walletAddresses.account!.id) {
|
|
||||||
if (element.isFrozen && !element.isSending) frozenBalance+= element.value;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return frozenBalance;
|
return frozenBalance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,12 +54,12 @@ class NanoClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> getHeaders() {
|
Map<String, String> getHeaders(String host) {
|
||||||
final headers = Map<String, String>.from(CAKE_HEADERS);
|
final headers = Map<String, String>.from(CAKE_HEADERS);
|
||||||
if (_node!.uri.host == "rpc.nano.to") {
|
if (host == "rpc.nano.to") {
|
||||||
headers["key"] = nano_secrets.nano2ApiKey;
|
headers["key"] = nano_secrets.nano2ApiKey;
|
||||||
}
|
}
|
||||||
if (_node!.uri.host == "nano.nownodes.io") {
|
if (host == "nano.nownodes.io") {
|
||||||
headers["api-key"] = nano_secrets.nanoNowNodesApiKey;
|
headers["api-key"] = nano_secrets.nanoNowNodesApiKey;
|
||||||
}
|
}
|
||||||
return headers;
|
return headers;
|
||||||
|
@ -68,7 +68,7 @@ class NanoClient {
|
||||||
Future<NanoBalance> getBalance(String address) async {
|
Future<NanoBalance> getBalance(String address) async {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: jsonEncode(
|
body: jsonEncode(
|
||||||
{
|
{
|
||||||
"action": "account_balance",
|
"action": "account_balance",
|
||||||
|
@ -95,7 +95,7 @@ class NanoClient {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: jsonEncode(
|
body: jsonEncode(
|
||||||
{
|
{
|
||||||
"action": "account_info",
|
"action": "account_info",
|
||||||
|
@ -116,7 +116,7 @@ class NanoClient {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
headers: CAKE_HEADERS,
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: jsonEncode(
|
body: jsonEncode(
|
||||||
{
|
{
|
||||||
"action": "block_info",
|
"action": "block_info",
|
||||||
|
@ -183,7 +183,7 @@ class NanoClient {
|
||||||
Future<String> requestWork(String hash) async {
|
Future<String> requestWork(String hash) async {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
_powNode!.uri,
|
_powNode!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_powNode!.uri.host),
|
||||||
body: json.encode(
|
body: json.encode(
|
||||||
{
|
{
|
||||||
"action": "work_generate",
|
"action": "work_generate",
|
||||||
|
@ -226,7 +226,7 @@ class NanoClient {
|
||||||
|
|
||||||
final processResponse = await http.post(
|
final processResponse = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: processBody,
|
body: processBody,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ class NanoClient {
|
||||||
});
|
});
|
||||||
final processResponse = await http.post(
|
final processResponse = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: processBody,
|
body: processBody,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -441,7 +441,7 @@ class NanoClient {
|
||||||
required String privateKey,
|
required String privateKey,
|
||||||
}) async {
|
}) async {
|
||||||
final receivableResponse = await http.post(_node!.uri,
|
final receivableResponse = await http.post(_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "receivable",
|
"action": "receivable",
|
||||||
"account": destinationAddress,
|
"account": destinationAddress,
|
||||||
|
@ -493,7 +493,7 @@ class NanoClient {
|
||||||
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
|
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(_node!.uri,
|
final response = await http.post(_node!.uri,
|
||||||
headers: getHeaders(),
|
headers: getHeaders(_node!.uri.host),
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "account_history",
|
"action": "account_history",
|
||||||
"account": address,
|
"account": address,
|
||||||
|
@ -509,15 +509,16 @@ class NanoClient {
|
||||||
.map<NanoTransactionModel>((transaction) => NanoTransactionModel.fromJson(transaction))
|
.map<NanoTransactionModel>((transaction) => NanoTransactionModel.fromJson(transaction))
|
||||||
.toList();
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV("error fetching transactions: $e");
|
||||||
return [];
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<N2Node>> getN2Reps() async {
|
Future<List<N2Node>> getN2Reps() async {
|
||||||
|
final uri = Uri.parse(N2_REPS_ENDPOINT);
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(N2_REPS_ENDPOINT),
|
uri,
|
||||||
headers: CAKE_HEADERS,
|
headers: getHeaders(uri.host),
|
||||||
body: jsonEncode({"action": "reps"}),
|
body: jsonEncode({"action": "reps"}),
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
|
@ -531,9 +532,10 @@ class NanoClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> getRepScore(String rep) async {
|
Future<int> getRepScore(String rep) async {
|
||||||
|
final uri = Uri.parse(N2_REPS_ENDPOINT);
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(N2_REPS_ENDPOINT),
|
uri,
|
||||||
headers: CAKE_HEADERS,
|
headers: getHeaders(uri.host),
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "rep_info",
|
"action": "rep_info",
|
||||||
"account": rep,
|
"account": rep,
|
||||||
|
|
|
@ -481,6 +481,9 @@ class SolanaWalletClient {
|
||||||
final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress);
|
final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress);
|
||||||
final mint = Ed25519HDPublicKey.fromBase58(tokenMint);
|
final mint = Ed25519HDPublicKey.fromBase58(tokenMint);
|
||||||
|
|
||||||
|
// Input by the user
|
||||||
|
final amount = (inputAmount * math.pow(10, tokenDecimals)).toInt();
|
||||||
|
|
||||||
ProgramAccount? associatedRecipientAccount;
|
ProgramAccount? associatedRecipientAccount;
|
||||||
ProgramAccount? associatedSenderAccount;
|
ProgramAccount? associatedSenderAccount;
|
||||||
|
|
||||||
|
@ -503,18 +506,48 @@ class SolanaWalletClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
associatedRecipientAccount ??= await _client!.createAssociatedTokenAccount(
|
if (associatedRecipientAccount == null) {
|
||||||
mint: mint,
|
final derivedAddress = await findAssociatedTokenAddress(
|
||||||
owner: destinationOwner,
|
owner: destinationOwner,
|
||||||
funder: ownerKeypair,
|
mint: mint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final instruction = AssociatedTokenAccountInstruction.createAccount(
|
||||||
|
mint: mint,
|
||||||
|
address: derivedAddress,
|
||||||
|
owner: destinationOwner,
|
||||||
|
funder: ownerKeypair.publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
final _signedTx = await _signTransactionInternal(
|
||||||
|
message: Message.only(instruction),
|
||||||
|
signers: [ownerKeypair],
|
||||||
|
commitment: commitment,
|
||||||
|
latestBlockhash: await _getLatestBlockhash(commitment),
|
||||||
|
);
|
||||||
|
|
||||||
|
await sendTransaction(
|
||||||
|
signedTransaction: _signedTx,
|
||||||
|
commitment: commitment,
|
||||||
|
);
|
||||||
|
|
||||||
|
associatedRecipientAccount = ProgramAccount(
|
||||||
|
pubkey: derivedAddress.toBase58(),
|
||||||
|
account: Account(
|
||||||
|
owner: destinationOwner.toBase58(),
|
||||||
|
lamports: 0,
|
||||||
|
executable: false,
|
||||||
|
rentEpoch: BigInt.zero,
|
||||||
|
data: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Future.delayed(Duration(seconds: 5));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw SolanaCreateAssociatedTokenAccountException(e.toString());
|
throw SolanaCreateAssociatedTokenAccountException(e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input by the user
|
|
||||||
final amount = (inputAmount * math.pow(10, tokenDecimals)).toInt();
|
|
||||||
|
|
||||||
final instruction = TokenInstruction.transfer(
|
final instruction = TokenInstruction.transfer(
|
||||||
source: Ed25519HDPublicKey.fromBase58(associatedSenderAccount.pubkey),
|
source: Ed25519HDPublicKey.fromBase58(associatedSenderAccount.pubkey),
|
||||||
destination: Ed25519HDPublicKey.fromBase58(associatedRecipientAccount.pubkey),
|
destination: Ed25519HDPublicKey.fromBase58(associatedRecipientAccount.pubkey),
|
||||||
|
@ -552,10 +585,14 @@ class SolanaWalletClient {
|
||||||
latestBlockhash: latestBlockhash,
|
latestBlockhash: latestBlockhash,
|
||||||
);
|
);
|
||||||
|
|
||||||
sendTx() async => await sendTransaction(
|
sendTx() async {
|
||||||
|
await Future.delayed(Duration(seconds: 3));
|
||||||
|
|
||||||
|
return await sendTransaction(
|
||||||
signedTransaction: signedTx,
|
signedTransaction: signedTx,
|
||||||
commitment: commitment,
|
commitment: commitment,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final pendingTransaction = PendingSolanaTransaction(
|
final pendingTransaction = PendingSolanaTransaction(
|
||||||
amount: inputAmount,
|
amount: inputAmount,
|
||||||
|
|
|
@ -33,7 +33,6 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:solana/base58.dart';
|
import 'package:solana/base58.dart';
|
||||||
import 'package:solana/metaplex.dart' as metaplex;
|
import 'package:solana/metaplex.dart' as metaplex;
|
||||||
import 'package:solana/solana.dart';
|
import 'package:solana/solana.dart';
|
||||||
import 'package:solana/src/crypto/ed25519_hd_keypair.dart';
|
|
||||||
|
|
||||||
part 'solana_wallet.g.dart';
|
part 'solana_wallet.g.dart';
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,7 @@ SPEC CHECKSUMS:
|
||||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||||
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
|
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
|
||||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||||
|
|
||||||
PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597
|
PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597
|
||||||
|
|
|
@ -149,7 +149,8 @@ class CWBitcoin extends Bitcoin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async {
|
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority,
|
||||||
|
{UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) async {
|
||||||
try {
|
try {
|
||||||
final sk = ECPrivate.random();
|
final sk = ECPrivate.random();
|
||||||
final electrumWallet = wallet as ElectrumWallet;
|
final electrumWallet = wallet as ElectrumWallet;
|
||||||
|
@ -173,6 +174,7 @@ class CWBitcoin extends Bitcoin {
|
||||||
? priority as LitecoinTransactionPriority
|
? priority as LitecoinTransactionPriority
|
||||||
: priority as BitcoinTransactionPriority,
|
: priority as BitcoinTransactionPriority,
|
||||||
),
|
),
|
||||||
|
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
||||||
);
|
);
|
||||||
|
|
||||||
return estimatedTx.amount;
|
return estimatedTx.amount;
|
||||||
|
|
|
@ -51,6 +51,8 @@ class RobinhoodBuyProvider extends BuyProvider {
|
||||||
switch (wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
case WalletType.polygon:
|
case WalletType.polygon:
|
||||||
|
case WalletType.solana:
|
||||||
|
case WalletType.tron:
|
||||||
return await wallet.signMessage(message);
|
return await wallet.signMessage(message);
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
|
@ -78,8 +80,7 @@ class RobinhoodBuyProvider extends BuyProvider {
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return (jsonDecode(response.body) as Map<String, dynamic>)['connectId'] as String;
|
return (jsonDecode(response.body) as Map<String, dynamic>)['connectId'] as String;
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception('Provider currently unavailable. Status: ${response.statusCode}');
|
||||||
'Provider currently unavailable. Status: ${response.statusCode} ${response.body}');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +121,13 @@ class RobinhoodBuyProvider extends BuyProvider {
|
||||||
try {
|
try {
|
||||||
final uri = await requestProviderUrl();
|
final uri = await requestProviderUrl();
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
} catch (_) {
|
} catch (e) {
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertWithOneAction(
|
return AlertWithOneAction(
|
||||||
alertTitle: "Robinhood Connect",
|
alertTitle: "Robinhood Connect",
|
||||||
alertContent: S.of(context).buy_provider_unavailable,
|
alertContent: e.toString(),
|
||||||
buttonText: S.of(context).ok,
|
buttonText: S.of(context).ok,
|
||||||
buttonAction: () => Navigator.of(context).pop());
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
});
|
});
|
||||||
|
|
|
@ -230,6 +230,7 @@ class CakePayApi {
|
||||||
|
|
||||||
var headers = {
|
var headers = {
|
||||||
'accept': 'application/json; charset=UTF-8',
|
'accept': 'application/json; charset=UTF-8',
|
||||||
|
'Content-Type': 'application/json; charset=UTF-8',
|
||||||
'Authorization': 'Api-Key $apiKey',
|
'Authorization': 'Api-Key $apiKey',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ class CakePayApi {
|
||||||
'Failed to fetch vendors: statusCode - ${response.statusCode}, queryParams -$queryParams, response - ${response.body}');
|
'Failed to fetch vendors: statusCode - ${response.statusCode}, queryParams -$queryParams, response - ${response.body}');
|
||||||
}
|
}
|
||||||
|
|
||||||
final bodyJson = json.decode(response.body);
|
final bodyJson = json.decode(utf8.decode(response.bodyBytes));
|
||||||
|
|
||||||
if (bodyJson is List<dynamic> && bodyJson.isEmpty) {
|
if (bodyJson is List<dynamic> && bodyJson.isEmpty) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
|
|
||||||
class CakePayCard {
|
class CakePayCard {
|
||||||
|
@ -38,17 +36,11 @@ class CakePayCard {
|
||||||
});
|
});
|
||||||
|
|
||||||
factory CakePayCard.fromJson(Map<String, dynamic> json) {
|
factory CakePayCard.fromJson(Map<String, dynamic> json) {
|
||||||
|
|
||||||
final name = stripHtmlIfNeeded(json['name'] as String? ?? '');
|
final name = stripHtmlIfNeeded(json['name'] as String? ?? '');
|
||||||
final decodedName = fixEncoding(name);
|
|
||||||
|
|
||||||
final description = stripHtmlIfNeeded(json['description'] as String? ?? '');
|
final description = stripHtmlIfNeeded(json['description'] as String? ?? '');
|
||||||
final decodedDescription = fixEncoding(description);
|
|
||||||
|
|
||||||
final termsAndConditions = stripHtmlIfNeeded(json['terms_and_conditions'] as String? ?? '');
|
final termsAndConditions = stripHtmlIfNeeded(json['terms_and_conditions'] as String? ?? '');
|
||||||
final decodedTermsAndConditions = fixEncoding(termsAndConditions);
|
|
||||||
|
|
||||||
final howToUse = stripHtmlIfNeeded(json['how_to_use'] as String? ?? '');
|
final howToUse = stripHtmlIfNeeded(json['how_to_use'] as String? ?? '');
|
||||||
final decodedHowToUse = fixEncoding(howToUse);
|
|
||||||
|
|
||||||
final fiatCurrency = FiatCurrency.deserialize(raw: json['currency_code'] as String? ?? '');
|
final fiatCurrency = FiatCurrency.deserialize(raw: json['currency_code'] as String? ?? '');
|
||||||
|
|
||||||
|
@ -59,10 +51,10 @@ class CakePayCard {
|
||||||
|
|
||||||
return CakePayCard(
|
return CakePayCard(
|
||||||
id: json['id'] as int? ?? 0,
|
id: json['id'] as int? ?? 0,
|
||||||
name: decodedName,
|
name: name,
|
||||||
description: decodedDescription,
|
description: description,
|
||||||
termsAndConditions: decodedTermsAndConditions,
|
termsAndConditions: termsAndConditions,
|
||||||
howToUse: decodedHowToUse,
|
howToUse: howToUse,
|
||||||
expiryAndValidity: json['expiry_and_validity'] as String?,
|
expiryAndValidity: json['expiry_and_validity'] as String?,
|
||||||
cardImageUrl: json['card_image_url'] as String?,
|
cardImageUrl: json['card_image_url'] as String?,
|
||||||
country: json['country'] as String?,
|
country: json['country'] as String?,
|
||||||
|
@ -79,13 +71,4 @@ class CakePayCard {
|
||||||
static String stripHtmlIfNeeded(String text) {
|
static String stripHtmlIfNeeded(String text) {
|
||||||
return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
|
return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
static String fixEncoding(String text) {
|
|
||||||
try {
|
|
||||||
final bytes = latin1.encode(text);
|
|
||||||
return utf8.decode(bytes, allowMalformed: true);
|
|
||||||
} catch (_) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'cake_pay_card.dart';
|
import 'cake_pay_card.dart';
|
||||||
|
|
||||||
class CakePayVendor {
|
class CakePayVendor {
|
||||||
|
@ -21,7 +19,6 @@ class CakePayVendor {
|
||||||
|
|
||||||
factory CakePayVendor.fromJson(Map<String, dynamic> json, String country) {
|
factory CakePayVendor.fromJson(Map<String, dynamic> json, String country) {
|
||||||
final name = stripHtmlIfNeeded(json['name'] as String);
|
final name = stripHtmlIfNeeded(json['name'] as String);
|
||||||
final decodedName = fixEncoding(name);
|
|
||||||
|
|
||||||
var cardsJson = json['cards'] as List?;
|
var cardsJson = json['cards'] as List?;
|
||||||
CakePayCard? cardForVendor;
|
CakePayCard? cardForVendor;
|
||||||
|
@ -36,7 +33,7 @@ class CakePayVendor {
|
||||||
|
|
||||||
return CakePayVendor(
|
return CakePayVendor(
|
||||||
id: json['id'] as int,
|
id: json['id'] as int,
|
||||||
name: decodedName,
|
name: name,
|
||||||
unavailable: json['unavailable'] as bool? ?? false,
|
unavailable: json['unavailable'] as bool? ?? false,
|
||||||
cakeWarnings: json['cake_warnings'] as String?,
|
cakeWarnings: json['cake_warnings'] as String?,
|
||||||
country: country,
|
country: country,
|
||||||
|
@ -47,9 +44,4 @@ class CakePayVendor {
|
||||||
static String stripHtmlIfNeeded(String text) {
|
static String stripHtmlIfNeeded(String text) {
|
||||||
return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
|
return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
static String fixEncoding(String text) {
|
|
||||||
final bytes = latin1.encode(text);
|
|
||||||
return utf8.decode(bytes, allowMalformed: true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,7 +505,7 @@ Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
|
||||||
];
|
];
|
||||||
// add new nodes:
|
// add new nodes:
|
||||||
for (final node in nodeList) {
|
for (final node in nodeList) {
|
||||||
if (listOfNewEndpoints.contains(node.uriRaw)) {
|
if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.values.contains(node)) {
|
||||||
await nodes.add(node);
|
await nodes.add(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,9 +244,11 @@ class AddressResolver {
|
||||||
if (unstoppableDomains.any((domain) => name.trim() == domain)) {
|
if (unstoppableDomains.any((domain) => name.trim() == domain)) {
|
||||||
if (settingsStore.lookupsUnstoppableDomains) {
|
if (settingsStore.lookupsUnstoppableDomains) {
|
||||||
final address = await fetchUnstoppableDomainAddress(text, ticker);
|
final address = await fetchUnstoppableDomainAddress(text, ticker);
|
||||||
|
if (address.isNotEmpty) {
|
||||||
return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text);
|
return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (text.endsWith(".eth")) {
|
if (text.endsWith(".eth")) {
|
||||||
if (settingsStore.lookupsENS) {
|
if (settingsStore.lookupsENS) {
|
||||||
|
@ -260,6 +262,7 @@ class AddressResolver {
|
||||||
if (formattedName.contains(".")) {
|
if (formattedName.contains(".")) {
|
||||||
if (settingsStore.lookupsOpenAlias) {
|
if (settingsStore.lookupsOpenAlias) {
|
||||||
final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName);
|
final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName);
|
||||||
|
|
||||||
if (txtRecord != null) {
|
if (txtRecord != null) {
|
||||||
final record = await OpenaliasRecord.fetchAddressAndName(
|
final record = await OpenaliasRecord.fetchAddressAndName(
|
||||||
formattedName: formattedName, ticker: ticker.toLowerCase(), txtRecord: txtRecord);
|
formattedName: formattedName, ticker: ticker.toLowerCase(), txtRecord: txtRecord);
|
||||||
|
|
|
@ -391,6 +391,12 @@ class CWMonero extends Monero {
|
||||||
return moneroWallet.exportOutputsUR(all);
|
return moneroWallet.exportOutputsUR(all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool needExportOutputs(Object wallet, int amount) {
|
||||||
|
final moneroWallet = wallet as MoneroWallet;
|
||||||
|
return moneroWallet.needExportOutputs(amount);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void monerocCheck() {
|
void monerocCheck() {
|
||||||
checkIfMoneroCIsFine();
|
checkIfMoneroCIsFine();
|
||||||
|
|
|
@ -312,6 +312,10 @@ class BuySellPage extends BasePage {
|
||||||
|
|
||||||
reaction((_) => buySellViewModel.isReadyToTrade, (bool isReady) {
|
reaction((_) => buySellViewModel.isReadyToTrade, (bool isReady) {
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
|
if (buySellViewModel.skipIsReadyToTradeReaction) {
|
||||||
|
buySellViewModel.skipIsReadyToTradeReaction = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (cryptoAmountController.text.isNotEmpty &&
|
if (cryptoAmountController.text.isNotEmpty &&
|
||||||
cryptoAmountController.text != S.current.fetching) {
|
cryptoAmountController.text != S.current.fetching) {
|
||||||
buySellViewModel.changeCryptoAmount(amount: cryptoAmountController.text);
|
buySellViewModel.changeCryptoAmount(amount: cryptoAmountController.text);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/unspent_coin_type.dart';
|
import 'package:cw_core/unspent_coin_type.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class BalanceRowWidget extends StatelessWidget {
|
class BalanceRowWidget extends StatelessWidget {
|
||||||
|
@ -85,14 +86,21 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
blurRadius: 7)
|
blurRadius: 7)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => Fluttertoast.showToast(
|
||||||
|
msg: S.current.show_balance_toast,
|
||||||
|
backgroundColor: Color.fromRGBO(0, 0, 0, 0.85),
|
||||||
|
),
|
||||||
|
onLongPress: () => dashboardViewModel.balanceViewModel.switchBalanceValue(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
||||||
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16),
|
margin: const EdgeInsets.only(top: 10, left: 12, right: 12, bottom: 10),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
Row(
|
||||||
onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
@ -168,7 +176,7 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: min(MediaQuery.of(context).size.width * 0.2, 100),
|
//width: min(MediaQuery.of(context).size.width * 0.2, 100),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -210,22 +218,16 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
//),
|
||||||
if (frozenBalance.isNotEmpty)
|
if (frozenBalance.isNotEmpty)
|
||||||
GestureDetector(
|
Column(
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: hasAdditionalBalance
|
|
||||||
? () => _showBalanceDescription(
|
|
||||||
context, S.of(context).unavailable_balance_description)
|
|
||||||
: null,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 26),
|
SizedBox(height: 26),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
S.of(context).unavailable_balance,
|
S.of(context).frozen_balance,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
@ -236,14 +238,6 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
height: 1,
|
height: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
|
||||||
child: Icon(Icons.help_outline,
|
|
||||||
size: 16,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<BalancePageTheme>()!
|
|
||||||
.labelTextColor),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
|
@ -275,11 +269,8 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (hasAdditionalBalance)
|
if (hasAdditionalBalance)
|
||||||
GestureDetector(
|
Column(
|
||||||
onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
|
@ -322,11 +313,11 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[
|
if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Container(
|
Container(
|
||||||
|
@ -348,12 +339,20 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
blurRadius: 7)
|
blurRadius: 7)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Container(
|
child: TextButton(
|
||||||
|
onPressed: () => Fluttertoast.showToast(
|
||||||
|
msg: S.current.show_balance_toast,
|
||||||
|
backgroundColor: Color.fromRGBO(0, 0, 0, 0.85),
|
||||||
|
),
|
||||||
|
onLongPress: () => dashboardViewModel.balanceViewModel.switchBalanceValue(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16),
|
margin: const EdgeInsets.only(top: 10, left: 12, right: 12, bottom: 10),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (currency == CryptoCurrency.ltc)
|
if (currency == CryptoCurrency.ltc)
|
||||||
|
@ -361,7 +360,6 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(right: 16, top: 0),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
|
@ -392,9 +390,7 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (hasSecondAvailableBalance)
|
if (hasSecondAvailableBalance)
|
||||||
GestureDetector(
|
Row(
|
||||||
onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -403,7 +399,7 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () => launchUrl(
|
onTap: () => launchUrl(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
"https://docs.cakewallet.com/cryptos/litecoin.html#mweb"),
|
"https://docs.cakewallet.com/cryptos/litecoin#mweb"),
|
||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -466,7 +462,6 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -533,7 +528,7 @@ class BalanceRowWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
IntrinsicHeight(
|
IntrinsicHeight(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -20,7 +20,8 @@ class SeedVerificationPage extends BasePage {
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: walletSeedViewModel.isVerificationComplete
|
child: walletSeedViewModel.isVerificationComplete ||
|
||||||
|
walletSeedViewModel.verificationIndices.isEmpty
|
||||||
? SeedVerificationSuccessView(
|
? SeedVerificationSuccessView(
|
||||||
imageColor: titleColor(context),
|
imageColor: titleColor(context),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/contact_record.dart';
|
||||||
import 'package:cake_wallet/core/execution_state.dart';
|
import 'package:cake_wallet/core/execution_state.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/monero/monero.dart';
|
||||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -412,6 +413,20 @@ class SendPage extends BasePage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sendViewModel.wallet.type == WalletType.monero) {
|
||||||
|
int amount = 0;
|
||||||
|
for (var item in sendViewModel.outputs) {
|
||||||
|
amount += item.formattedCryptoAmount;
|
||||||
|
}
|
||||||
|
if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
|
||||||
|
await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage, arguments: 'export-outputs');
|
||||||
|
await Future.delayed(Duration(seconds: 1)); // wait for monero to refresh the state
|
||||||
|
}
|
||||||
|
if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final check = sendViewModel.shouldDisplayTotp();
|
final check = sendViewModel.shouldDisplayTotp();
|
||||||
authService.authenticateAction(
|
authService.authenticateAction(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -215,6 +215,7 @@ class ExceptionHandler {
|
||||||
"input stream error",
|
"input stream error",
|
||||||
"invalid signature",
|
"invalid signature",
|
||||||
"invalid password",
|
"invalid password",
|
||||||
|
"NetworkImage._loadAsync",
|
||||||
// Temporary ignored, More context: Flutter secure storage reads the values as null some times
|
// Temporary ignored, More context: Flutter secure storage reads the values as null some times
|
||||||
// probably when the device was locked and then opened on Cake
|
// probably when the device was locked and then opened on Cake
|
||||||
// this is solved by a restart of the app
|
// this is solved by a restart of the app
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class FeatureFlag {
|
class FeatureFlag {
|
||||||
static const bool isCakePayEnabled = false;
|
static const bool isCakePayEnabled = false;
|
||||||
static const bool isExolixEnabled = true;
|
static const bool isExolixEnabled = true;
|
||||||
static const bool isInAppTorEnabled = false;
|
static const bool isInAppTorEnabled = false;
|
||||||
static const bool isBackgroundSyncEnabled = false;
|
static const bool isBackgroundSyncEnabled = false;
|
||||||
static const int verificationWordsCount = 2;
|
static const int verificationWordsCount = kDebugMode ? 0 : 2;
|
||||||
}
|
}
|
|
@ -149,6 +149,9 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
|
||||||
@observable
|
@observable
|
||||||
BuySellQuotLoadingState buySellQuotState;
|
BuySellQuotLoadingState buySellQuotState;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool skipIsReadyToTradeReaction = false;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isReadyToTrade {
|
bool get isReadyToTrade {
|
||||||
final hasSelectedQuote = selectedQuote != null;
|
final hasSelectedQuote = selectedQuote != null;
|
||||||
|
@ -266,6 +269,7 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTapChoseProvider(BuildContext context) async {
|
void onTapChoseProvider(BuildContext context) async {
|
||||||
|
skipIsReadyToTradeReaction = true;
|
||||||
final initialQuotes = List<Quote>.from(sortedRecommendedQuotes + sortedQuotes);
|
final initialQuotes = List<Quote>.from(sortedRecommendedQuotes + sortedQuotes);
|
||||||
await calculateBestRate();
|
await calculateBestRate();
|
||||||
final newQuotes = (sortedRecommendedQuotes + sortedQuotes);
|
final newQuotes = (sortedRecommendedQuotes + sortedQuotes);
|
||||||
|
|
|
@ -20,7 +20,8 @@ part 'balance_view_model.g.dart';
|
||||||
|
|
||||||
class BalanceRecord {
|
class BalanceRecord {
|
||||||
const BalanceRecord(
|
const BalanceRecord(
|
||||||
{required this.availableBalance,
|
{
|
||||||
|
required this.availableBalance,
|
||||||
required this.additionalBalance,
|
required this.additionalBalance,
|
||||||
required this.secondAvailableBalance,
|
required this.secondAvailableBalance,
|
||||||
required this.secondAdditionalBalance,
|
required this.secondAdditionalBalance,
|
||||||
|
@ -148,26 +149,18 @@ abstract class BalanceViewModelBase with Store {
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
String get availableBalanceLabel {
|
String get availableBalanceLabel {
|
||||||
switch (wallet.type) {
|
|
||||||
case WalletType.monero:
|
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
||||||
case WalletType.wownero:
|
return S.current.show_balance;
|
||||||
case WalletType.haven:
|
}
|
||||||
case WalletType.ethereum:
|
else {
|
||||||
case WalletType.polygon:
|
|
||||||
case WalletType.nano:
|
|
||||||
case WalletType.banano:
|
|
||||||
case WalletType.solana:
|
|
||||||
case WalletType.tron:
|
|
||||||
case WalletType.bitcoin:
|
|
||||||
case WalletType.litecoin:
|
|
||||||
case WalletType.bitcoinCash:
|
|
||||||
case WalletType.none:
|
|
||||||
return S.current.xmr_available_balance;
|
return S.current.xmr_available_balance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
String get additionalBalanceLabel {
|
String get additionalBalanceLabel {
|
||||||
|
|
||||||
switch (wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.haven:
|
case WalletType.haven:
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
|
@ -203,98 +196,35 @@ abstract class BalanceViewModelBase with Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
|
||||||
bool get hasMultiBalance => appStore.wallet!.type == WalletType.haven;
|
|
||||||
|
|
||||||
@computed
|
|
||||||
String get availableBalance {
|
|
||||||
final walletBalance = _walletBalance;
|
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
|
||||||
return '---';
|
|
||||||
}
|
|
||||||
|
|
||||||
return walletBalance.formattedAvailableBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
|
||||||
String get frozenBalance {
|
|
||||||
final walletBalance = _walletBalance;
|
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
|
||||||
return '---';
|
|
||||||
}
|
|
||||||
|
|
||||||
return getFormattedFrozenBalance(walletBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
|
||||||
String get frozenFiatBalance {
|
|
||||||
final walletBalance = _walletBalance;
|
|
||||||
final fiatCurrency = settingsStore.fiatCurrency;
|
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
|
||||||
return '---';
|
|
||||||
}
|
|
||||||
|
|
||||||
return _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(walletBalance)) +
|
|
||||||
' ${fiatCurrency.toString()}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
String get additionalBalance {
|
String get additionalBalance {
|
||||||
final walletBalance = _walletBalance;
|
final walletBalance = _walletBalance;
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
||||||
return '---';
|
return '0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return walletBalance.formattedAdditionalBalance;
|
return walletBalance.formattedAdditionalBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
|
||||||
String get availableFiatBalance {
|
|
||||||
final walletBalance = _walletBalance;
|
|
||||||
final fiatCurrency = settingsStore.fiatCurrency;
|
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
|
||||||
return '---';
|
|
||||||
}
|
|
||||||
|
|
||||||
return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAvailableBalance) +
|
|
||||||
' ${fiatCurrency.toString()}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
|
||||||
String get additionalFiatBalance {
|
|
||||||
final walletBalance = _walletBalance;
|
|
||||||
final fiatCurrency = settingsStore.fiatCurrency;
|
|
||||||
|
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
|
||||||
return '---';
|
|
||||||
}
|
|
||||||
|
|
||||||
return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAdditionalBalance) +
|
|
||||||
' ${fiatCurrency.toString()}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
Map<CryptoCurrency, BalanceRecord> get balances {
|
Map<CryptoCurrency, BalanceRecord> get balances {
|
||||||
return wallet.balance.map((key, value) {
|
return wallet.balance.map((key, value) {
|
||||||
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
if (displayMode == BalanceDisplayMode.hiddenBalance) {
|
||||||
|
final fiatCurrency = settingsStore.fiatCurrency;
|
||||||
return MapEntry(
|
return MapEntry(
|
||||||
key,
|
key,
|
||||||
BalanceRecord(
|
BalanceRecord(
|
||||||
availableBalance: '---',
|
availableBalance: '●●●●●●',
|
||||||
additionalBalance: '---',
|
additionalBalance: additionalBalance,
|
||||||
frozenBalance: '',
|
frozenBalance: '',
|
||||||
secondAvailableBalance: '---',
|
secondAvailableBalance: '●●●●●●',
|
||||||
secondAdditionalBalance: '---',
|
secondAdditionalBalance: '●●●●●●',
|
||||||
fiatAdditionalBalance: isFiatDisabled ? '' : '---',
|
fiatAdditionalBalance: isFiatDisabled ? '' : '${fiatCurrency.toString()} ●●●●●',
|
||||||
fiatAvailableBalance: isFiatDisabled ? '' : '---',
|
fiatAvailableBalance: isFiatDisabled ? '' : '${fiatCurrency.toString()} ●●●●●',
|
||||||
fiatFrozenBalance: isFiatDisabled ? '' : '---',
|
fiatFrozenBalance: isFiatDisabled ? '' : '',
|
||||||
fiatSecondAvailableBalance: isFiatDisabled ? '' : '---',
|
fiatSecondAvailableBalance: isFiatDisabled ? '' : '${fiatCurrency.toString()} ●●●●●',
|
||||||
fiatSecondAdditionalBalance: isFiatDisabled ? '' : '---',
|
fiatSecondAdditionalBalance: isFiatDisabled ? '' : '${fiatCurrency.toString()} ●●●●●',
|
||||||
asset: key,
|
asset: key,
|
||||||
formattedAssetTitle: _formatterAsset(key)));
|
formattedAssetTitle: _formatterAsset(key)));
|
||||||
}
|
}
|
||||||
|
@ -374,16 +304,11 @@ abstract class BalanceViewModelBase with Store {
|
||||||
|
|
||||||
bool _hasAdditionalBalanceForWalletType(WalletType type) {
|
bool _hasAdditionalBalanceForWalletType(WalletType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WalletType.ethereum:
|
case WalletType.monero:
|
||||||
case WalletType.polygon:
|
case WalletType.wownero:
|
||||||
case WalletType.solana:
|
|
||||||
case WalletType.tron:
|
|
||||||
case WalletType.bitcoin:
|
|
||||||
case WalletType.bitcoinCash:
|
|
||||||
case WalletType.litecoin:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,8 +393,6 @@ abstract class BalanceViewModelBase with Store {
|
||||||
return balance;
|
return balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
|
||||||
CryptoCurrency get currency => appStore.wallet!.currency;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool isShowCard;
|
bool isShowCard;
|
||||||
|
|
|
@ -641,7 +641,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
transactions.clear();
|
transactions.clear();
|
||||||
|
|
||||||
transactions = ObservableList.of(
|
transactions.addAll(
|
||||||
wallet.transactionHistory.transactions.values.map(
|
wallet.transactionHistory.transactions.values.map(
|
||||||
(transaction) => TransactionListItem(
|
(transaction) => TransactionListItem(
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
|
@ -703,7 +703,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
transactions = ObservableList.of(
|
transactions.addAll(
|
||||||
_accountTransactions.map(
|
_accountTransactions.map(
|
||||||
(transaction) => TransactionListItem(
|
(transaction) => TransactionListItem(
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
|
@ -723,7 +723,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
wow.wownero!.getCurrentAccount(wallet).id)
|
wow.wownero!.getCurrentAccount(wallet).id)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
transactions = ObservableList.of(
|
transactions.addAll(
|
||||||
_accountTransactions.map(
|
_accountTransactions.map(
|
||||||
(transaction) => TransactionListItem(
|
(transaction) => TransactionListItem(
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart'
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/sync_status.dart';
|
import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
|
import 'package:cw_core/unspent_coin_type.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -122,7 +123,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
depositAmount = '';
|
depositAmount = '';
|
||||||
receiveAmount = '';
|
receiveAmount = '';
|
||||||
receiveAddress = '';
|
receiveAddress = '';
|
||||||
depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
depositAddress =
|
||||||
|
depositCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
||||||
provider = providersForCurrentPair().first;
|
provider = providersForCurrentPair().first;
|
||||||
final initialProvider = provider;
|
final initialProvider = provider;
|
||||||
provider!.checkIsAvailable().then((bool isAvailable) {
|
provider!.checkIsAvailable().then((bool isAvailable) {
|
||||||
|
@ -157,8 +159,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
wallet.type == WalletType.bitcoinCash;
|
wallet.type == WalletType.bitcoinCash;
|
||||||
|
|
||||||
bool get hideAddressAfterExchange =>
|
bool get hideAddressAfterExchange =>
|
||||||
wallet.type == WalletType.monero ||
|
wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
|
||||||
wallet.type == WalletType.wownero;
|
|
||||||
|
|
||||||
bool _useTorOnly;
|
bool _useTorOnly;
|
||||||
final Box<Trade> trades;
|
final Box<Trade> trades;
|
||||||
|
@ -613,8 +614,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
isReceiveAmountEntered = false;
|
isReceiveAmountEntered = false;
|
||||||
depositAmount = '';
|
depositAmount = '';
|
||||||
receiveAmount = '';
|
receiveAmount = '';
|
||||||
depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
depositAddress =
|
||||||
receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
depositCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
||||||
|
receiveAddress =
|
||||||
|
receiveCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
||||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||||
isFixedRateMode = false;
|
isFixedRateMode = false;
|
||||||
_onPairChange();
|
_onPairChange();
|
||||||
|
@ -640,7 +643,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
wallet.type == WalletType.bitcoinCash) {
|
wallet.type == WalletType.bitcoinCash) {
|
||||||
final priority = _settingsStore.priority[wallet.type]!;
|
final priority = _settingsStore.priority[wallet.type]!;
|
||||||
|
|
||||||
final amount = await bitcoin!.estimateFakeSendAllTxAmount(wallet, priority);
|
final amount = await bitcoin!.estimateFakeSendAllTxAmount(
|
||||||
|
wallet,
|
||||||
|
priority,
|
||||||
|
coinTypeToSpendFrom:
|
||||||
|
wallet.type == WalletType.litecoin ? UnspentCoinType.nonMweb : UnspentCoinType.any,
|
||||||
|
);
|
||||||
|
|
||||||
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,7 +394,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
|
|
||||||
if (wallet.isHardwareWallet) state = IsAwaitingDeviceResponseState();
|
if (wallet.isHardwareWallet) state = IsAwaitingDeviceResponseState();
|
||||||
|
|
||||||
pendingTransaction = await wallet.createTransaction(_credentials());
|
pendingTransaction = await wallet.createTransaction(_credentials(provider));
|
||||||
|
|
||||||
if (provider is ThorChainExchangeProvider) {
|
if (provider is ThorChainExchangeProvider) {
|
||||||
final outputCount = pendingTransaction?.outputCount ?? 0;
|
final outputCount = pendingTransaction?.outputCount ?? 0;
|
||||||
|
@ -522,7 +522,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
void setTransactionPriority(TransactionPriority priority) =>
|
void setTransactionPriority(TransactionPriority priority) =>
|
||||||
_settingsStore.priority[wallet.type] = priority;
|
_settingsStore.priority[wallet.type] = priority;
|
||||||
|
|
||||||
Object _credentials() {
|
Object _credentials([ExchangeProvider? provider]) {
|
||||||
final priority = _settingsStore.priority[wallet.type];
|
final priority = _settingsStore.priority[wallet.type];
|
||||||
|
|
||||||
if (priority == null &&
|
if (priority == null &&
|
||||||
|
@ -535,7 +535,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
|
|
||||||
switch (wallet.type) {
|
switch (wallet.type) {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.litecoin:
|
|
||||||
case WalletType.bitcoinCash:
|
case WalletType.bitcoinCash:
|
||||||
return bitcoin!.createBitcoinTransactionCredentials(
|
return bitcoin!.createBitcoinTransactionCredentials(
|
||||||
outputs,
|
outputs,
|
||||||
|
@ -543,6 +542,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
feeRate: customBitcoinFeeRate,
|
feeRate: customBitcoinFeeRate,
|
||||||
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
||||||
);
|
);
|
||||||
|
case WalletType.litecoin:
|
||||||
|
return bitcoin!.createBitcoinTransactionCredentials(
|
||||||
|
outputs,
|
||||||
|
priority: priority!,
|
||||||
|
feeRate: customBitcoinFeeRate,
|
||||||
|
// if it's an exchange flow then disable sending from mweb coins
|
||||||
|
coinTypeToSpendFrom: provider != null ? UnspentCoinType.nonMweb : coinTypeToSpendFrom,
|
||||||
|
);
|
||||||
|
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
return monero!
|
return monero!
|
||||||
|
|
|
@ -29,6 +29,7 @@ abstract class WalletSeedViewModelBase with Store {
|
||||||
List<String> get seedSplit => seed.split(RegExp(r'\s+'));
|
List<String> get seedSplit => seed.split(RegExp(r'\s+'));
|
||||||
|
|
||||||
int get columnCount => seedSplit.length <= 16 ? 2 : 3;
|
int get columnCount => seedSplit.length <= 16 ? 2 : 3;
|
||||||
|
|
||||||
double get columnAspectRatio => seedSplit.length <= 16 ? 1.8 : 2.8;
|
double get columnAspectRatio => seedSplit.length <= 16 ? 1.8 : 2.8;
|
||||||
|
|
||||||
/// The indices of the seed to be verified.
|
/// The indices of the seed to be verified.
|
||||||
|
@ -60,9 +61,11 @@ abstract class WalletSeedViewModelBase with Store {
|
||||||
bool isVerificationComplete = false;
|
bool isVerificationComplete = false;
|
||||||
|
|
||||||
void setupSeedVerification() {
|
void setupSeedVerification() {
|
||||||
|
if (verificationWordCount != 0) {
|
||||||
generateRandomIndices();
|
generateRandomIndices();
|
||||||
generateOptions();
|
generateOptions();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate the indices of the seeds to be verified.
|
/// Generate the indices of the seeds to be verified.
|
||||||
///
|
///
|
||||||
|
|
|
@ -40,11 +40,11 @@ static void my_application_activate(GApplication* application) {
|
||||||
if (use_header_bar) {
|
if (use_header_bar) {
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
gtk_header_bar_set_title(header_bar, "cake_wallet");
|
gtk_header_bar_set_title(header_bar, "Cake Wallet");
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
} else {
|
} else {
|
||||||
gtk_window_set_title(window, "cake_wallet");
|
gtk_window_set_title(window, "Cake Wallet");
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|
|
@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
||||||
APP_ANDROID_TYPE=$1
|
APP_ANDROID_TYPE=$1
|
||||||
|
|
||||||
MONERO_COM_NAME="Monero.com"
|
MONERO_COM_NAME="Monero.com"
|
||||||
MONERO_COM_VERSION="1.19.0"
|
MONERO_COM_VERSION="1.19.1"
|
||||||
MONERO_COM_BUILD_NUMBER=109
|
MONERO_COM_BUILD_NUMBER=110
|
||||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||||
MONERO_COM_PACKAGE="com.monero.app"
|
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.22.0"
|
CAKEWALLET_VERSION="4.22.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=240
|
CAKEWALLET_BUILD_NUMBER=241
|
||||||
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"
|
||||||
|
|
|
@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
||||||
APP_IOS_TYPE=$1
|
APP_IOS_TYPE=$1
|
||||||
|
|
||||||
MONERO_COM_NAME="Monero.com"
|
MONERO_COM_NAME="Monero.com"
|
||||||
MONERO_COM_VERSION="1.19.0"
|
MONERO_COM_VERSION="1.19.1"
|
||||||
MONERO_COM_BUILD_NUMBER=106
|
MONERO_COM_BUILD_NUMBER=107
|
||||||
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.22.0"
|
CAKEWALLET_VERSION="4.22.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=287
|
CAKEWALLET_BUILD_NUMBER=288
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
HAVEN_NAME="Haven"
|
HAVEN_NAME="Haven"
|
||||||
|
|
|
@ -14,8 +14,8 @@ if [ -n "$1" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CAKEWALLET_NAME="Cake Wallet"
|
CAKEWALLET_NAME="Cake Wallet"
|
||||||
CAKEWALLET_VERSION="1.12.0"
|
CAKEWALLET_VERSION="1.12.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=41
|
CAKEWALLET_BUILD_NUMBER=42
|
||||||
|
|
||||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
|
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
|
||||||
echo "Wrong app type."
|
echo "Wrong app type."
|
||||||
|
|
|
@ -16,13 +16,13 @@ if [ -n "$1" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MONERO_COM_NAME="Monero.com"
|
MONERO_COM_NAME="Monero.com"
|
||||||
MONERO_COM_VERSION="1.9.0"
|
MONERO_COM_VERSION="1.9.1"
|
||||||
MONERO_COM_BUILD_NUMBER=39
|
MONERO_COM_BUILD_NUMBER=40
|
||||||
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.15.0"
|
CAKEWALLET_VERSION="1.15.1"
|
||||||
CAKEWALLET_BUILD_NUMBER=99
|
CAKEWALLET_BUILD_NUMBER=100
|
||||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||||
|
|
||||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#define MyAppName "Cake Wallet"
|
#define MyAppName "Cake Wallet"
|
||||||
#define MyAppVersion "0.3.0"
|
#define MyAppVersion "0.3.1"
|
||||||
#define MyAppPublisher "Cake Labs LLC"
|
#define MyAppPublisher "Cake Labs LLC"
|
||||||
#define MyAppURL "https://cakewallet.com/"
|
#define MyAppURL "https://cakewallet.com/"
|
||||||
#define MyAppExeName "CakeWallet.exe"
|
#define MyAppExeName "CakeWallet.exe"
|
||||||
|
|
|
@ -109,7 +109,6 @@ import 'package:cw_bitcoin/electrum.dart';
|
||||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||||
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
|
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
|
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
|
||||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
|
@ -173,7 +172,8 @@ abstract class Bitcoin {
|
||||||
List<ElectrumSubAddress> getSilentPaymentAddresses(Object wallet);
|
List<ElectrumSubAddress> getSilentPaymentAddresses(Object wallet);
|
||||||
List<ElectrumSubAddress> getSilentPaymentReceivedAddresses(Object wallet);
|
List<ElectrumSubAddress> getSilentPaymentReceivedAddresses(Object wallet);
|
||||||
|
|
||||||
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority);
|
Future<int> estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority,
|
||||||
|
{UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any});
|
||||||
List<ElectrumSubAddress> getSubAddresses(Object wallet);
|
List<ElectrumSubAddress> getSubAddresses(Object wallet);
|
||||||
|
|
||||||
String formatterBitcoinAmountToString({required int amount});
|
String formatterBitcoinAmountToString({required int amount});
|
||||||
|
@ -387,6 +387,8 @@ abstract class Monero {
|
||||||
|
|
||||||
String exportOutputsUR(Object wallet, bool all);
|
String exportOutputsUR(Object wallet, bool all);
|
||||||
|
|
||||||
|
bool needExportOutputs(Object wallet, int amount);
|
||||||
|
|
||||||
bool importKeyImagesUR(Object wallet, String ur);
|
bool importKeyImagesUR(Object wallet, String ur);
|
||||||
|
|
||||||
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
|
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
|
||||||
|
|
Loading…
Reference in a new issue