mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
CW-997 coin control enhancements / send ALL fixes (#2114)
* computed sending balance value * files that didnt get added before * monero + move unspent calc to view model * working * remove old code * Update lib/view_model/send/send_view_model.dart --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
7831b421b1
commit
40a0989956
8 changed files with 106 additions and 12 deletions
|
@ -65,6 +65,6 @@ class ElectrumBalance extends Balance {
|
||||||
'unconfirmed': unconfirmed,
|
'unconfirmed': unconfirmed,
|
||||||
'frozen': frozen,
|
'frozen': frozen,
|
||||||
'secondConfirmed': secondConfirmed,
|
'secondConfirmed': secondConfirmed,
|
||||||
'secondUnconfirmed': secondUnconfirmed
|
'secondUnconfirmed': secondUnconfirmed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ 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/bitcoin_amount_format.dart';
|
||||||
|
import 'package:cw_core/format_amount.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';
|
||||||
|
@ -2240,10 +2242,11 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
if (element.hash == info.hash &&
|
if (element.hash == info.hash &&
|
||||||
element.vout == info.vout &&
|
element.vout == info.vout &&
|
||||||
info.isFrozen &&
|
|
||||||
element.bitcoinAddressRecord.address == info.address &&
|
element.bitcoinAddressRecord.address == info.address &&
|
||||||
element.value == info.value) {
|
element.value == info.value) {
|
||||||
totalFrozen += element.value;
|
if (info.isFrozen) {
|
||||||
|
totalFrozen += element.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2499,6 +2502,12 @@ abstract class ElectrumWalletBase
|
||||||
transactionHistory.addOne(tx);
|
transactionHistory.addOne(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String formatCryptoAmount(String amount) {
|
||||||
|
final amountInt = int.parse(amount);
|
||||||
|
return bitcoinAmountToString(amount: amountInt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScanNode {
|
class ScanNode {
|
||||||
|
|
|
@ -36,6 +36,8 @@ abstract class WalletBase<BalanceType extends Balance, HistoryType extends Trans
|
||||||
|
|
||||||
ObservableMap<CryptoCurrency, BalanceType> get balance;
|
ObservableMap<CryptoCurrency, BalanceType> get balance;
|
||||||
|
|
||||||
|
String formatCryptoAmount(String amount) => amount;
|
||||||
|
|
||||||
SyncStatus get syncStatus;
|
SyncStatus get syncStatus;
|
||||||
|
|
||||||
set syncStatus(SyncStatus status);
|
set syncStatus(SyncStatus status);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:ffi';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
|
|
||||||
|
import 'package:cw_core/monero_amount_format.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
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';
|
||||||
|
@ -905,4 +906,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
||||||
monero.WalletManager_openWallet(wmPtr, path: '', password: '');
|
monero.WalletManager_openWallet(wmPtr, path: '', password: '');
|
||||||
enableLedgerExchange(dummyWPtr, connection);
|
enableLedgerExchange(dummyWPtr, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String formatCryptoAmount(String amount) {
|
||||||
|
return moneroAmountToString(amount: int.parse(amount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -770,4 +770,9 @@ abstract class WowneroWalletBase
|
||||||
|
|
||||||
return wownero_wallet.verifyMessage(message, address, signature);
|
return wownero_wallet.verifyMessage(message, address, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String formatCryptoAmount(String amount) {
|
||||||
|
return wowneroAmountToString(amount: int.parse(amount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
currencyValueValidator: output.sendAll
|
currencyValueValidator: output.sendAll
|
||||||
? sendViewModel.allAmountValidator
|
? sendViewModel.allAmountValidator
|
||||||
: sendViewModel.amountValidator,
|
: sendViewModel.amountValidator,
|
||||||
allAmountCallback: () async => output.setSendAll(sendViewModel.balance)),
|
allAmountCallback: () async => output.setSendAll(sendViewModel.sendingBalance)),
|
||||||
Divider(
|
Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
||||||
|
@ -266,7 +266,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
sendViewModel.balance,
|
sendViewModel.sendingBalance,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
|
@ -384,10 +384,16 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
padding: EdgeInsets.only(top: 6),
|
padding: EdgeInsets.only(top: 6),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
key: ValueKey('send_page_unspent_coin_button_key'),
|
key: ValueKey('send_page_unspent_coin_button_key'),
|
||||||
onTap: () => Navigator.of(context).pushNamed(
|
onTap: () async {
|
||||||
Routes.unspentCoinsList,
|
await Navigator.of(context).pushNamed(
|
||||||
arguments: widget.sendViewModel.coinTypeToSpendFrom,
|
Routes.unspentCoinsList,
|
||||||
),
|
arguments: widget.sendViewModel.coinTypeToSpendFrom,
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
// we just got back from the unspent coins list screen, so we need to recompute the sending balance:
|
||||||
|
sendViewModel.updateSendingBalance();
|
||||||
|
}
|
||||||
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -505,7 +511,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
||||||
|
|
||||||
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) {
|
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) {
|
||||||
if (output.sendAll) {
|
if (output.sendAll) {
|
||||||
output.setSendAll(sendViewModel.balance);
|
output.setSendAll(sendViewModel.sendingBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.setCryptoAmount(cryptoAmountController.text);
|
output.setCryptoAmount(cryptoAmountController.text);
|
||||||
|
|
|
@ -225,6 +225,42 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
return wallet.balance[selectedCryptoCurrency]!.formattedFullAvailableBalance;
|
return wallet.balance[selectedCryptoCurrency]!.formattedFullAvailableBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> updateSendingBalance() async {
|
||||||
|
// force the sendingBalance to recompute since unspent coins aren't observable
|
||||||
|
// or at least mobx can't detect the changes
|
||||||
|
|
||||||
|
final currentType = coinTypeToSpendFrom;
|
||||||
|
|
||||||
|
if (currentType == UnspentCoinType.any) {
|
||||||
|
coinTypeToSpendFrom = UnspentCoinType.nonMweb;
|
||||||
|
} else if (currentType == UnspentCoinType.nonMweb) {
|
||||||
|
coinTypeToSpendFrom = UnspentCoinType.any;
|
||||||
|
} else if (currentType == UnspentCoinType.mweb) {
|
||||||
|
coinTypeToSpendFrom = UnspentCoinType.nonMweb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set it back to the original value:
|
||||||
|
coinTypeToSpendFrom = currentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
String get sendingBalance {
|
||||||
|
// only for electrum, monero, wownero, decred wallets atm:
|
||||||
|
switch (wallet.type) {
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
case WalletType.monero:
|
||||||
|
case WalletType.wownero:
|
||||||
|
case WalletType.decred:
|
||||||
|
return wallet.formatCryptoAmount(
|
||||||
|
unspentCoinsListViewModel.getSendingBalance(coinTypeToSpendFrom).toString());
|
||||||
|
default:
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
|
bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
|
||||||
|
|
||||||
|
@ -502,14 +538,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||||
return bitcoin!.createBitcoinTransactionCredentials(
|
return bitcoin!.createBitcoinTransactionCredentials(
|
||||||
outputs,
|
outputs,
|
||||||
priority: priority!,
|
priority: priority!,
|
||||||
feeRate:feesViewModel. customBitcoinFeeRate,
|
feeRate: feesViewModel.customBitcoinFeeRate,
|
||||||
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
||||||
);
|
);
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
return bitcoin!.createBitcoinTransactionCredentials(
|
return bitcoin!.createBitcoinTransactionCredentials(
|
||||||
outputs,
|
outputs,
|
||||||
priority: priority!,
|
priority: priority!,
|
||||||
feeRate:feesViewModel. customBitcoinFeeRate,
|
feeRate: feesViewModel.customBitcoinFeeRate,
|
||||||
// if it's an exchange flow then disable sending from mweb coins
|
// if it's an exchange flow then disable sending from mweb coins
|
||||||
coinTypeToSpendFrom: provider != null ? UnspentCoinType.nonMweb : coinTypeToSpendFrom,
|
coinTypeToSpendFrom: provider != null ? UnspentCoinType.nonMweb : coinTypeToSpendFrom,
|
||||||
);
|
);
|
||||||
|
|
|
@ -131,6 +131,36 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Unspent> _getSpecificUnspents(UnspentCoinType overrideCoinTypeToSpendFrom) {
|
||||||
|
switch (wallet.type) {
|
||||||
|
case WalletType.monero:
|
||||||
|
return monero!.getUnspents(wallet);
|
||||||
|
case WalletType.wownero:
|
||||||
|
return wownero!.getUnspents(wallet);
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
return bitcoin!.getUnspents(wallet, coinTypeToSpendFrom: overrideCoinTypeToSpendFrom);
|
||||||
|
case WalletType.decred:
|
||||||
|
return decred!.getUnspents(wallet);
|
||||||
|
default:
|
||||||
|
return List.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
int getSendingBalance(UnspentCoinType overrideCoinTypeToSpendFrom) {
|
||||||
|
// return items.where((element) => element.isSending).fold(0, (previousValue, element) => previousValue + element.value);
|
||||||
|
// go through all unspent coins and add up the value minus frozen and non sending:
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
for (final item in _getSpecificUnspents(overrideCoinTypeToSpendFrom)) {
|
||||||
|
if (item.isFrozen || !item.isSending) continue;
|
||||||
|
total += item.value;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void _updateUnspentCoinsInfo() {
|
void _updateUnspentCoinsInfo() {
|
||||||
items.clear();
|
items.clear();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue