diff --git a/class/wallets/abstract-hd-electrum-wallet.js b/class/wallets/abstract-hd-electrum-wallet.js index 7867227f9..201a17602 100644 --- a/class/wallets/abstract-hd-electrum-wallet.js +++ b/class/wallets/abstract-hd-electrum-wallet.js @@ -1034,4 +1034,12 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet { return ret; } + + // check if address is a Change address. Needed for Coin control + addressIsChange(address) { + for (let c = 0; c < this.next_free_change_address_index + 1; c++) { + if (address === this._getInternalAddressByIndex(c)) return true; + } + return false; + } } diff --git a/class/wallets/legacy-wallet.js b/class/wallets/legacy-wallet.js index 3dc9a16e9..c66b02b23 100644 --- a/class/wallets/legacy-wallet.js +++ b/class/wallets/legacy-wallet.js @@ -404,4 +404,10 @@ export class LegacyWallet extends AbstractWallet { allowSendMax() { return true; } + + // Check if address is a Change address. Needed for Coin control. + // Useless for Legacy wallets, so it is always false + addressIsChange(address) { + return true; + } } diff --git a/class/wallets/watch-only-wallet.js b/class/wallets/watch-only-wallet.js index ae4b38eea..7d1313313 100644 --- a/class/wallets/watch-only-wallet.js +++ b/class/wallets/watch-only-wallet.js @@ -252,4 +252,9 @@ export class WatchOnlyWallet extends LegacyWallet { return false; } + + addressIsChange(...args) { + if (this._hdWalletInstance) return this._hdWalletInstance.addressIsChange(...args); + return super.getAllExternalAddresses(...args); + } } diff --git a/loc/en.json b/loc/en.json index 347742e5f..7739ffafd 100644 --- a/loc/en.json +++ b/loc/en.json @@ -403,6 +403,7 @@ "co_sign_transaction": "Co-sign QR-airgapped transaction" }, "cc": { + "change": "change", "empty": "Wallet UTXO set is empty", "freeze": "freeze", "header": "Coin control", diff --git a/screen/send/coinControl.js b/screen/send/coinControl.js index 92818b9dd..aba799f61 100644 --- a/screen/send/coinControl.js +++ b/screen/send/coinControl.js @@ -13,6 +13,7 @@ import { TextInput, TouchableWithoutFeedback, View, + useColorScheme, } from 'react-native'; import { useRoute, useTheme, useNavigation } from '@react-navigation/native'; @@ -27,14 +28,21 @@ const oStyles = StyleSheet.create({ avatar: { borderColor: 'white', borderWidth: 1 }, amount: { fontWeight: 'bold' }, memo: { fontSize: 13, marginTop: 3 }, + changeLight: { backgroundColor: '#EEF0F4' }, + changeDark: { backgroundColor: '#3b3b3c', borderWidth: 0 }, + changeText: { color: '#9BA0A9' }, + freezeLight: { backgroundColor: '#F2D3D3' }, + freezeDark: { backgroundColor: '#5a4e4e', borderWidth: 0 }, + freezeText: { color: '#FC6D6D' }, }); -const Output = ({ item: { address, txid, value, vout }, oMemo, frozen, full = false, onPress }) => { +const Output = ({ item: { address, txid, value, vout }, oMemo, frozen, change = false, full = false, onPress }) => { const { colors } = useTheme(); const { txMetadata } = useContext(BlueStorageContext); + const cs = useColorScheme(); const memo = oMemo || txMetadata[txid]?.memo || ''; const fullId = `${txid}:${vout}`; - const shortId = `${address.substring(0, 10)}...${address.substr(address.length - 10)}`; + const shortId = `${address.substring(0, 9)}...${address.substr(address.length - 9)}`; const color = `#${txid.substring(0, 6)}`; const amount = formatBalanceWithoutSuffix(value, BitcoinUnit.BTC, true); @@ -61,7 +69,12 @@ const Output = ({ item: { address, txid, value, vout }, oMemo, frozen, full = fa )} - {frozen && } + {change && ( + + )} + {frozen && ( + + )} ); }; @@ -75,6 +88,7 @@ Output.propTypes = { }), oMemo: PropTypes.string, frozen: PropTypes.bool, + change: PropTypes.bool, full: PropTypes.bool, onPress: PropTypes.func, }; @@ -167,7 +181,8 @@ const CoinControl = () => { const renderItem = p => { const { memo, frozen } = wallet.getUTXOMetadata(p.item.txid, p.item.vout); - return handleChoose(p.item)} />; + const change = wallet.addressIsChange(p.item.address); + return handleChoose(p.item)} />; }; return (