diff --git a/lib/bitcoin/bitcoin_wallet.dart b/lib/bitcoin/bitcoin_wallet.dart index fd8402887..02af295fc 100644 --- a/lib/bitcoin/bitcoin_wallet.dart +++ b/lib/bitcoin/bitcoin_wallet.dart @@ -1,12 +1,12 @@ import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cake_wallet/bitcoin/utils.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet_snapshot.dart'; import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; import 'package:cake_wallet/bitcoin/electrum_balance.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_wallet_addresses.dart'; part 'bitcoin_wallet.g.dart'; @@ -26,8 +26,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { walletInfo: walletInfo, networkType: bitcoin.bitcoin, initialAddresses: initialAddresses, - initialBalance: initialBalance, - accountIndex: accountIndex); + initialBalance: initialBalance) { + walletAddresses = BitcoinWalletAddresses( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd, + networkType: networkType); + } static Future open({ @required String name, @@ -44,8 +50,4 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: snp.balance, accountIndex: snp.accountIndex); } - - @override - String getAddress({@required int index, @required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); } diff --git a/lib/bitcoin/bitcoin_wallet_addresses.dart b/lib/bitcoin/bitcoin_wallet_addresses.dart new file mode 100644 index 000000000..ecded3cb8 --- /dev/null +++ b/lib/bitcoin/bitcoin_wallet_addresses.dart @@ -0,0 +1,33 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cake_wallet/bitcoin/utils.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; + +part 'bitcoin_wallet_addresses.g.dart'; + +class BitcoinWalletAddresses = BitcoinWalletAddressesBase + with _$BitcoinWalletAddresses; + +abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses + with Store { + BitcoinWalletAddressesBase( + WalletInfo walletInfo, + {@required List initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd, + @required this.networkType}) + : super( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd); + + bitcoin.NetworkType networkType; + + @override + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => + generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); +} \ No newline at end of file diff --git a/lib/bitcoin/electrum_wallet.dart b/lib/bitcoin/electrum_wallet.dart index bf3dfd542..38fc192de 100644 --- a/lib/bitcoin/electrum_wallet.dart +++ b/lib/bitcoin/electrum_wallet.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; import 'package:flutter/foundation.dart'; @@ -42,18 +43,14 @@ abstract class ElectrumWalletBase extends WalletBase.of( - (initialAddresses ?? []).toSet()), syncStatus = NotConnectedSyncStatus(), _password = password, - _accountIndex = accountIndex, _feeRates = [], _isTransactionUpdating = false, super(walletInfo) { @@ -74,8 +71,7 @@ abstract class ElectrumWalletBase extends WalletBase addresses; - - List get scriptHashes => addresses + List get scriptHashes => walletAddresses.addresses .map((addr) => scriptHash(addr.address, networkType: networkType)) .toList(); @@ -105,80 +99,21 @@ abstract class ElectrumWalletBase extends WalletBase _unspent; List _feeRates; - int _accountIndex; Map> _scripthashesUpdateSubject; bool _isTransactionUpdating; Future init() async { - await generateAddresses(); - address = addresses[_accountIndex].address; + await walletAddresses.init(); await transactionHistory.init(); - } - - @action - Future nextAddress() async { - _accountIndex += 1; - - if (_accountIndex >= addresses.length) { - _accountIndex = 0; - } - - address = addresses[_accountIndex].address; - await save(); } - Future generateAddresses() async { - if (addresses.length < 33) { - final addressesCount = 33 - addresses.length; - await generateNewAddresses(addressesCount, - startIndex: addresses.length, hd: hd); - } - } - - Future generateNewAddress( - {bool isHidden = false, bitcoin.HDWallet hd}) async { - _accountIndex += 1; - final _hd = hd ?? this.hd; - final address = BitcoinAddressRecord( - getAddress(index: _accountIndex, hd: _hd), - index: _accountIndex, - isHidden: isHidden); - addresses.add(address); - await save(); - return address; - } - - Future> generateNewAddresses(int count, - {int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async { - final list = []; - - for (var i = startIndex; i < count + startIndex; i++) { - final address = BitcoinAddressRecord(getAddress(index: i, hd: hd), - index: i, isHidden: isHidden); - list.add(address); - } - - addresses.addAll(list); - await save(); - return list; - } - - Future updateAddress(String address) async { - for (final addr in addresses) { - if (addr.address == address) { - await save(); - break; - } - } - } - @action @override Future startSync() async { try { syncStatus = StartingSyncStatus(); - updateTransactions(); + await updateTransactions(); _subscribeForUpdates(); await _updateBalance(); await _updateUnspent(); @@ -230,7 +165,7 @@ abstract class ElectrumWalletBase extends WalletBase json.encode({ 'mnemonic': mnemonic, - 'account_index': _accountIndex.toString(), - 'addresses': addresses.map((addr) => addr.toJSON()).toList(), + 'account_index': walletAddresses.accountIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), 'balance': balance?.toJSON() }); @@ -377,13 +312,12 @@ abstract class ElectrumWalletBase extends WalletBase ''; - Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future _updateUnspent() async { - final unspent = await Future.wait(addresses.map((address) => electrumClient + final unspent = await Future.wait(walletAddresses + .addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) .then((unspent) => unspent .map((unspent) => BitcoinUnspent.fromJSON(address, unspent))))); @@ -394,7 +328,7 @@ abstract class ElectrumWalletBase extends WalletBase initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd}) + : super(walletInfo) { + this.hd = hd; + this.accountIndex = accountIndex; + addresses = ObservableList.of( + (initialAddresses ?? []).toSet()); + } + + @override + @observable + String address; + + bitcoin.HDWallet hd; + + ObservableList addresses; + + int accountIndex; + + @override + Future init() async { + await generateAddresses(); + address = addresses[accountIndex].address; + await updateAddressesInBox(); + } + + @action + Future nextAddress() async { + accountIndex += 1; + + if (accountIndex >= addresses.length) { + accountIndex = 0; + } + + address = addresses[accountIndex].address; + + await updateAddressesInBox(); + } + + Future generateAddresses() async { + if (addresses.length < 33) { + final addressesCount = 33 - addresses.length; + await generateNewAddresses(addressesCount, + startIndex: addresses.length, hd: hd); + } + } + + Future generateNewAddress( + {bool isHidden = false, bitcoin.HDWallet hd}) async { + accountIndex += 1; + final _hd = hd ?? this.hd; + final address = BitcoinAddressRecord( + getAddress(index: accountIndex, hd: _hd), + index: accountIndex, + isHidden: isHidden); + addresses.add(address); + return address; + } + + Future> generateNewAddresses(int count, + {int startIndex = 0, bitcoin.HDWallet hd, bool isHidden = false}) async { + final list = []; + + for (var i = startIndex; i < count + startIndex; i++) { + final address = BitcoinAddressRecord(getAddress(index: i, hd: hd), + index: i, isHidden: isHidden); + list.add(address); + } + + addresses.addAll(list); + return list; + } + + /*Future updateAddress(String address) async { + for (final addr in addresses) { + if (addr.address == address) { + await save(); + break; + } + } + }*/ + + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => ''; + + @override + Future updateAddressesInBox() async { + try { + addressesMap.clear(); + addressesMap[address] = ''; + + await saveAddressesInBox(); + } catch (e) { + print(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/bitcoin/litecoin_wallet.dart b/lib/bitcoin/litecoin_wallet.dart index 209d1904e..bfb7da6d6 100644 --- a/lib/bitcoin/litecoin_wallet.dart +++ b/lib/bitcoin/litecoin_wallet.dart @@ -1,6 +1,5 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart'; import 'package:cake_wallet/bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cake_wallet/bitcoin/litecoin_wallet_addresses.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; @@ -10,7 +9,6 @@ import 'package:cake_wallet/bitcoin/electrum_wallet.dart'; import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; import 'package:cake_wallet/bitcoin/electrum_balance.dart'; import 'package:cake_wallet/bitcoin/litecoin_network.dart'; -import 'package:cake_wallet/bitcoin/utils.dart'; part 'litecoin_wallet.g.dart'; @@ -30,8 +28,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { walletInfo: walletInfo, networkType: litecoinNetwork, initialAddresses: initialAddresses, - initialBalance: initialBalance, - accountIndex: accountIndex); + initialBalance: initialBalance) { + walletAddresses = LitecoinWalletAddresses( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd, + networkType: networkType, + mnemonic: mnemonic); + } static Future open({ @required String name, @@ -49,27 +54,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { accountIndex: snp.accountIndex); } - @override - String getAddress({@required int index, @required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); - - @override - Future generateAddresses() async { - if (addresses.length < 33) { - final addressesCount = 22 - addresses.length; - await generateNewAddresses(addressesCount, - hd: hd, startIndex: addresses.length); - - final changeRoot = bitcoin.HDWallet.fromSeed( - mnemonicToSeedBytes(mnemonic), - network: networkType) - .derivePath("m/0'/1"); - - await generateNewAddresses(11, - startIndex: 0, hd: changeRoot, isHidden: true); - } - } - @override int feeRate(TransactionPriority priority) { if (priority is LitecoinTransactionPriority) { diff --git a/lib/bitcoin/litecoin_wallet_addresses.dart b/lib/bitcoin/litecoin_wallet_addresses.dart new file mode 100644 index 000000000..19ade7566 --- /dev/null +++ b/lib/bitcoin/litecoin_wallet_addresses.dart @@ -0,0 +1,54 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cake_wallet/bitcoin/bitcoin_mnemonic.dart'; +import 'package:cake_wallet/bitcoin/utils.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart'; +import 'package:cake_wallet/bitcoin/electrum_wallet_addresses.dart'; +import 'package:cake_wallet/entities/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:mobx/mobx.dart'; + +part 'litecoin_wallet_addresses.g.dart'; + +class LitecoinWalletAddresses = LitecoinWalletAddressesBase + with _$LitecoinWalletAddresses; + +abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses + with Store { + LitecoinWalletAddressesBase( + WalletInfo walletInfo, + {@required List initialAddresses, + int accountIndex = 0, + @required bitcoin.HDWallet hd, + @required this.networkType, + @required this.mnemonic}) + : super( + walletInfo, + initialAddresses: initialAddresses, + accountIndex: accountIndex, + hd: hd); + + bitcoin.NetworkType networkType; + + final String mnemonic; + + @override + String getAddress({@required int index, @required bitcoin.HDWallet hd}) => + generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); + + @override + Future generateAddresses() async { + if (addresses.length < 33) { + final addressesCount = 22 - addresses.length; + await generateNewAddresses(addressesCount, + hd: hd, startIndex: addresses.length); + + final changeRoot = bitcoin.HDWallet.fromSeed( + mnemonicToSeedBytes(mnemonic), + network: networkType) + .derivePath("m/0'/1"); + + await generateNewAddresses(11, + startIndex: 0, hd: changeRoot, isHidden: true); + } + } +} \ No newline at end of file diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index b908d7bc5..dc450ad7e 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -15,7 +15,7 @@ abstract class BuyProvider { String get trackUrl; WalletType get walletType => wallet.type; - String get walletAddress => wallet.address; + String get walletAddress => wallet.walletAddresses.address; String get walletId => wallet.id; @override diff --git a/lib/core/wallet_base.dart b/lib/core/wallet_base.dart index ced918342..edcb05466 100644 --- a/lib/core/wallet_base.dart +++ b/lib/core/wallet_base.dart @@ -1,12 +1,12 @@ import 'package:cake_wallet/entities/balance.dart'; import 'package:cake_wallet/entities/transaction_info.dart'; import 'package:cake_wallet/entities/transaction_priority.dart'; +import 'package:cake_wallet/entities/wallet_addresses.dart'; import 'package:flutter/foundation.dart'; import 'package:cake_wallet/entities/wallet_info.dart'; import 'package:cake_wallet/core/pending_transaction.dart'; import 'package:cake_wallet/core/transaction_history.dart'; import 'package:cake_wallet/entities/currency_for_wallet_type.dart'; -import 'package:cake_wallet/entities/monero_transaction_priority.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/node.dart'; @@ -31,9 +31,9 @@ abstract class WalletBase< String get name => walletInfo.name; - String get address; + //String get address; - set address(String address); + //set address(String address); BalanceType get balance; @@ -45,6 +45,8 @@ abstract class WalletBase< Object get keys; + WalletAddresses get walletAddresses; + HistoryType transactionHistory; Future connectToNode({@required Node node}); diff --git a/lib/di.dart b/lib/di.dart index 37b6c5968..3b709d707 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -361,7 +361,8 @@ Future setup( getIt.registerFactoryParam( (AccountListItem account, _) => MoneroAccountEditOrCreateViewModel( - (getIt.get().wallet as MoneroWallet).accountList, + (getIt.get().wallet as MoneroWallet).walletAddresses.accountList, + wallet: getIt.get().wallet, accountListItem: account)); getIt.registerFactoryParam addressesMap; + + Future init(); + + Future updateAddressesInBox(); + + Future saveAddressesInBox() async { + try { + if (walletInfo == null) { + return; + } + + walletInfo.address = address; + walletInfo.addresses = addressesMap; + + if (walletInfo.isInBox) { + await walletInfo.save(); + } + } catch (e) { + print(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/entities/wallet_info.dart b/lib/entities/wallet_info.dart index e29f60528..9dfb2011b 100644 --- a/lib/entities/wallet_info.dart +++ b/lib/entities/wallet_info.dart @@ -53,5 +53,8 @@ class WalletInfo extends HiveObject { @HiveField(8) String address; + @HiveField(10) + Map addresses; + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp); } diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index b51c94edf..36f2e4bc8 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:cake_wallet/monero/monero_amount_format.dart'; import 'package:cake_wallet/monero/monero_transaction_creation_exception.dart'; import 'package:cake_wallet/monero/monero_transaction_info.dart'; +import 'package:cake_wallet/monero/monero_wallet_addresses.dart'; import 'package:cake_wallet/monero/monero_wallet_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; @@ -16,10 +17,7 @@ import 'package:cake_wallet/monero/pending_monero_transaction.dart'; import 'package:cake_wallet/monero/monero_wallet_keys.dart'; import 'package:cake_wallet/monero/monero_balance.dart'; import 'package:cake_wallet/monero/monero_transaction_history.dart'; -import 'package:cake_wallet/monero/monero_subaddress_list.dart'; -import 'package:cake_wallet/monero/monero_account_list.dart'; import 'package:cake_wallet/monero/account.dart'; -import 'package:cake_wallet/monero/subaddress.dart'; import 'package:cake_wallet/core/pending_transaction.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/entities/sync_status.dart'; @@ -36,9 +34,7 @@ class MoneroWallet = MoneroWalletBase with _$MoneroWallet; abstract class MoneroWalletBase extends WalletBase with Store { MoneroWalletBase({WalletInfo walletInfo}) - : accountList = MoneroAccountList(), - subaddressList = MoneroSubaddressList(), - super(walletInfo) { + : super(walletInfo) { transactionHistory = MoneroTransactionHistory(); balance = MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: 0), @@ -48,33 +44,26 @@ abstract class MoneroWalletBase extends WalletBase account, (Account account) { + walletAddresses = MoneroWalletAddresses(walletInfo); + _onAccountChangeReaction = reaction((_) => walletAddresses.account, + (Account account) { balance = MoneroBalance( fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id)); - subaddressList.update(accountIndex: account.id); - subaddress = subaddressList.subaddresses.first; - address = subaddress.address; + walletAddresses.updateSubaddressList(accountIndex: account.id); }); } static const int _autoAfterSyncSaveInterval = 60000; - @observable - Account account; - - @observable - Subaddress subaddress; + @override + MoneroWalletAddresses walletAddresses; @override @observable SyncStatus syncStatus; - @override - @observable - String address; - @override @observable MoneroBalance balance; @@ -89,10 +78,6 @@ abstract class MoneroWalletBase extends WalletBase init() async { - accountList.update(); - account = accountList.accounts.first; - subaddressList.update(accountIndex: account.id ?? 0); - subaddress = subaddressList.getAll().first; + await walletAddresses.init(); balance = MoneroBalance( - fullBalance: monero_wallet.getFullBalance(accountIndex: account.id), + fullBalance: monero_wallet.getFullBalance(accountIndex: walletAddresses.account.id), unlockedBalance: - monero_wallet.getUnlockedBalance(accountIndex: account.id)); - address = subaddress.address; + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account.id)); _setListeners(); await updateTransactions(); @@ -130,24 +111,6 @@ abstract class MoneroWalletBase extends WalletBase connectToNode({@required Node node}) async { try { @@ -190,7 +153,7 @@ abstract class MoneroWalletBase extends WalletBase save() async { + await walletAddresses.updateAddressesInBox(); + final now = DateTime.now().millisecondsSinceEpoch; if (now - _lastSaveTimestamp < Duration(seconds: 10).inMilliseconds) { @@ -267,7 +232,7 @@ abstract class MoneroWalletBase extends WalletBase - monero_wallet.getFullBalance(accountIndex: account.id); + monero_wallet.getFullBalance(accountIndex: walletAddresses.account.id); int _getUnlockedBalance() => - monero_wallet.getUnlockedBalance(accountIndex: account.id); + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account.id); Future _afterSyncSave() async { try { @@ -416,13 +381,13 @@ abstract class MoneroWalletBase extends WalletBase init() async { + accountList.update(); + account = accountList.accounts.first; + updateSubaddressList(accountIndex: account.id ?? 0); + await updateAddressesInBox(); + } + + @override + Future updateAddressesInBox() async { + try { + final _subaddressList = MoneroSubaddressList(); + + addressesMap.clear(); + + accountList.accounts.forEach((account) { + _subaddressList.update(accountIndex: account.id); + _subaddressList.subaddresses.forEach((subaddress) { + addressesMap[subaddress.address] = subaddress.label; + }); + }); + + await saveAddressesInBox(); + } catch (e) { + print(e.toString()); + } + } + + bool validate() { + accountList.update(); + final accountListLength = accountList.accounts?.length ?? 0; + + if (accountListLength <= 0) { + return false; + } + + subaddressList.update(accountIndex: accountList.accounts.first.id); + final subaddressListLength = subaddressList.subaddresses?.length ?? 0; + + if (subaddressListLength <= 0) { + return false; + } + + return true; + } + + void updateSubaddressList({int accountIndex}) { + subaddressList.update(accountIndex: accountIndex); + subaddress = subaddressList.subaddresses.first; + address = subaddress.address; + } +} \ No newline at end of file diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index 824daf41a..e3ec51a15 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -109,7 +109,7 @@ class MoneroWalletService extends WalletService< (info) => info.id == WalletBase.idFor(name, getType()), orElse: () => null); final wallet = MoneroWallet(walletInfo: walletInfo); - final isValid = wallet.validate(); + final isValid = wallet.walletAddresses.validate(); if (!isValid) { await restoreOrResetWalletFiles(name); diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index 428f2703e..5c702b0af 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -37,7 +37,7 @@ void startCurrentWalletChangeReaction(AppStore appStore, await wallet.connectToNode(node: node); if (wallet.walletInfo.address?.isEmpty ?? true) { - wallet.walletInfo.address = wallet.address; + wallet.walletInfo.address = wallet.walletAddresses.address; if (wallet.walletInfo.isInBox) { await wallet.walletInfo.save(); diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index bf2b593ee..fd126981a 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -151,17 +151,19 @@ class ContactListPage extends BasePage { crossAxisAlignment: CrossAxisAlignment.center, children: [ image ?? Offstage(), - Padding( - padding: image != null - ? EdgeInsets.only(left: 12) - : EdgeInsets.only(left: 0), - child: Text( - contact.name, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).primaryTextTheme.title.color), - ), + Expanded( + child: Padding( + padding: image != null + ? EdgeInsets.only(left: 12) + : EdgeInsets.only(left: 0), + child: Text( + contact.name, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).primaryTextTheme.title.color), + ), + ) ) ], ), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 3eb23da3a..6b4e9e3cb 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -179,7 +179,7 @@ class ExchangePage extends BasePage { initialAddress: exchangeViewModel.depositCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.depositAddress, initialIsAmountEditable: true, initialIsAddressEditable: @@ -240,7 +240,7 @@ class ExchangePage extends BasePage { initialAddress: exchangeViewModel .receiveCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel .isReceiveAmountEditable, @@ -646,7 +646,8 @@ class ExchangePage extends BasePage { } }); - reaction((_) => exchangeViewModel.wallet.address, (String address) { + reaction((_) => exchangeViewModel.wallet.walletAddresses.address, + (String address) { if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState.changeAddress(address: address); } @@ -707,7 +708,8 @@ class ExchangePage extends BasePage { isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); key.currentState.changeAddress( - address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + address: isCurrentTypeWallet + ? exchangeViewModel.wallet.walletAddresses.address : ''); key.currentState.changeAmount(amount: ''); } @@ -719,9 +721,9 @@ class ExchangePage extends BasePage { if (isCurrentTypeWallet) { key.currentState.changeWalletName(exchangeViewModel.wallet.name); key.currentState.addressController.text = - exchangeViewModel.wallet.address; + exchangeViewModel.wallet.walletAddresses.address; } else if (key.currentState.addressController.text == - exchangeViewModel.wallet.address) { + exchangeViewModel.wallet.walletAddresses.address) { key.currentState.changeWalletName(null); key.currentState.addressController.text = null; } diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 7df55f320..c978a535f 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -129,7 +129,7 @@ class ExchangeTemplatePage extends BasePage { initialAddress: exchangeViewModel .depositCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.depositAddress, initialIsAmountEditable: true, initialIsAddressEditable: exchangeViewModel @@ -168,7 +168,7 @@ class ExchangeTemplatePage extends BasePage { initialAddress: exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address + ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel.provider is @@ -383,7 +383,8 @@ class ExchangeTemplatePage extends BasePage { } }); - reaction((_) => exchangeViewModel.wallet.address, (String address) { + reaction((_) => exchangeViewModel.wallet.walletAddresses.address, + (String address) { if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState.changeAddress(address: address); } @@ -405,7 +406,8 @@ class ExchangeTemplatePage extends BasePage { isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); key.currentState.changeAddress( - address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + address: isCurrentTypeWallet + ? exchangeViewModel.wallet.walletAddresses.address : ''); key.currentState.changeAmount(amount: ''); } @@ -417,9 +419,9 @@ class ExchangeTemplatePage extends BasePage { if (isCurrentTypeWallet) { key.currentState.changeWalletName(exchangeViewModel.wallet.name); key.currentState.addressController.text = - exchangeViewModel.wallet.address; + exchangeViewModel.wallet.walletAddresses.address; } else if (key.currentState.addressController.text == - exchangeViewModel.wallet.address) { + exchangeViewModel.wallet.walletAddresses.address) { key.currentState.changeWalletName(null); key.currentState.addressController.text = null; } diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index 17083efe2..1a8bbc021 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -16,11 +16,22 @@ class ContactListViewModel = ContactListViewModelBase abstract class ContactListViewModelBase with Store { ContactListViewModelBase(this.contactSource, this.walletInfoSource) : contacts = ObservableList(), - walletContacts = walletInfoSource.values - .where((info) => info.address?.isNotEmpty ?? false) - .map((info) => WalletContact( - info.address, info.name, walletTypeToCryptoCurrency(info.type))) - .toList() { + walletContacts = [] { + walletInfoSource.values.forEach((info) { + if (info.addresses?.isNotEmpty ?? false) { + info.addresses?.forEach((address, label) { + final name = label.isNotEmpty + ? info.name + ' ($label)' + : info.name; + + walletContacts.add(WalletContact( + address, + name, + walletTypeToCryptoCurrency(info.type))); + }); + } + }); + _subscription = contactSource.bindToListWithTransform( contacts, (Contact contact) => ContactRecord(contactSource, contact), initialFire: true); diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index e35316d11..0777d3ecd 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -92,17 +92,17 @@ abstract class DashboardViewModelBase with Store { final _wallet = wallet; if (_wallet is MoneroWallet) { - subname = _wallet.account?.label; + subname = _wallet.walletAddresses.account?.label; - _onMoneroAccountChangeReaction = reaction((_) => _wallet.account, - (Account account) => _onMoneroAccountChange(_wallet)); + _onMoneroAccountChangeReaction = reaction((_) => _wallet.walletAddresses + .account, (Account account) => _onMoneroAccountChange(_wallet)); _onMoneroBalanceChangeReaction = reaction((_) => _wallet.balance, (MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet)); final _accountTransactions = _wallet .transactionHistory.transactions.values - .where((tx) => tx.accountIndex == _wallet.account.id) + .where((tx) => tx.accountIndex == _wallet.walletAddresses.account.id) .toList(); transactions = ObservableList.of(_accountTransactions.map((transaction) => @@ -131,7 +131,7 @@ abstract class DashboardViewModelBase with Store { filter: (TransactionInfo tx) { final wallet = _wallet; if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { - return tx.accountIndex == wallet.account.id; + return tx.accountIndex == wallet.walletAddresses.account.id; } return true; @@ -153,7 +153,7 @@ abstract class DashboardViewModelBase with Store { String subname; @computed - String get address => wallet.address; + String get address => wallet.walletAddresses.address; @computed SyncStatus get status => wallet.syncStatus; @@ -251,13 +251,13 @@ abstract class DashboardViewModelBase with Store { wallet.type == WalletType.bitcoin && wallet.seed.split(' ').length < 24; if (wallet is MoneroWallet) { - subname = wallet.account?.label; + subname = wallet.walletAddresses.account?.label; _onMoneroAccountChangeReaction?.reaction?.dispose(); _onMoneroBalanceChangeReaction?.reaction?.dispose(); - _onMoneroAccountChangeReaction = reaction((_) => wallet.account, - (Account account) => _onMoneroAccountChange(wallet)); + _onMoneroAccountChangeReaction = reaction((_) => wallet.walletAddresses + .account, (Account account) => _onMoneroAccountChange(wallet)); _onMoneroBalanceChangeReaction = reaction((_) => wallet.balance, (MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet)); @@ -284,7 +284,7 @@ abstract class DashboardViewModelBase with Store { settingsStore: appStore.settingsStore), filter: (TransactionInfo tx) { if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { - return tx.accountIndex == wallet.account.id; + return tx.accountIndex == wallet.walletAddresses.account.id; } return true; @@ -293,7 +293,7 @@ abstract class DashboardViewModelBase with Store { @action void _onMoneroAccountChange(MoneroWallet wallet) { - subname = wallet.account?.label; + subname = wallet.walletAddresses.account?.label; _onMoneroTransactionsUpdate(wallet); } @@ -302,7 +302,7 @@ abstract class DashboardViewModelBase with Store { transactions.clear(); final _accountTransactions = wallet.transactionHistory.transactions.values - .where((tx) => tx.accountIndex == wallet.account.id) + .where((tx) => tx.accountIndex == wallet.walletAddresses.account.id) .toList(); transactions.addAll(_accountTransactions.map((transaction) => diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index f3f00cd77..01246542b 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -41,7 +41,8 @@ abstract class ExchangeViewModelBase with Store { depositAmount = ''; receiveAmount = ''; receiveAddress = ''; - depositAddress = depositCurrency == wallet.currency ? wallet.address : ''; + depositAddress = depositCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; limitsState = LimitsInitialState(); tradeState = ExchangeTradeStateInitial(); _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12; @@ -308,8 +309,10 @@ abstract class ExchangeViewModelBase with Store { isReceiveAmountEntered = false; depositAmount = ''; receiveAmount = ''; - depositAddress = depositCurrency == wallet.currency ? wallet.address : ''; - receiveAddress = receiveCurrency == wallet.currency ? wallet.address : ''; + depositAddress = depositCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; + receiveAddress = receiveCurrency == wallet.currency + ? wallet.walletAddresses.address : ''; isDepositAddressEnabled = !(depositCurrency == wallet.currency); isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); isFixedRateMode = false; diff --git a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart index d32f8eadd..a86fa2773 100644 --- a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/monero/monero_account_list.dart'; @@ -10,11 +12,12 @@ class MoneroAccountEditOrCreateViewModel = MoneroAccountEditOrCreateViewModelBas abstract class MoneroAccountEditOrCreateViewModelBase with Store { MoneroAccountEditOrCreateViewModelBase(this._moneroAccountList, - {AccountListItem accountListItem}) + {@required WalletBase wallet, AccountListItem accountListItem}) : state = InitialExecutionState(), isEdit = accountListItem != null, label = accountListItem?.label??'', - _accountListItem = accountListItem; + _accountListItem = accountListItem, + _wallet = wallet; final bool isEdit; @@ -26,6 +29,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { final MoneroAccountList _moneroAccountList; final AccountListItem _accountListItem; + final WalletBase _wallet; Future save() async { try { @@ -38,6 +42,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { await _moneroAccountList.addAccount(label: label); } + await _wallet.save(); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); diff --git a/lib/view_model/monero_account_list/monero_account_list_view_model.dart b/lib/view_model/monero_account_list/monero_account_list_view_model.dart index c6d6aa686..ca0eb67ef 100644 --- a/lib/view_model/monero_account_list/monero_account_list_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_list_view_model.dart @@ -20,15 +20,16 @@ abstract class MoneroAccountListViewModelBase with Store { } @computed - List get accounts => _moneroWallet.accountList.accounts - .map((acc) => AccountListItem( + List get accounts => _moneroWallet.walletAddresses + .accountList.accounts.map((acc) => AccountListItem( label: acc.label, id: acc.id, - isSelected: acc.id == _moneroWallet.account.id)) + isSelected: acc.id == _moneroWallet.walletAddresses.account.id)) .toList(); final MoneroWallet _moneroWallet; void select(AccountListItem item) => - _moneroWallet.account = Account(id: item.id, label: item.label); + _moneroWallet.walletAddresses.account = + Account(id: item.id, label: item.label); } diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index b018c542d..3676b3bf6 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -64,12 +64,15 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { final wallet = _wallet; if (wallet is ElectrumWallet) { - await wallet.generateNewAddress(); + await wallet.walletAddresses.generateNewAddress(); + await wallet.save(); } if (wallet is MoneroWallet) { - await wallet.subaddressList - .addSubaddress(accountIndex: wallet.account.id, label: label); + await wallet.walletAddresses.subaddressList + .addSubaddress( + accountIndex: wallet.walletAddresses.account.id, + label: label); await wallet.save(); } } @@ -77,13 +80,14 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { Future _update() async { final wallet = _wallet; - if (wallet is BitcoinWallet) { - await wallet.updateAddress(_item.address as String); - } + /*if (wallet is BitcoinWallet) { + await wallet.walletAddresses.updateAddress(_item.address as String); + await wallet.save(); + }*/ if (wallet is MoneroWallet) { - await wallet.subaddressList.setLabelSubaddress( - accountIndex: wallet.account.id, + await wallet.walletAddresses.subaddressList.setLabelSubaddress( + accountIndex: wallet.walletAddresses.account.id, addressIndex: _item.id as int, label: label); await wallet.save(); diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index b15443222..a4d6eff66 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -80,7 +80,7 @@ abstract class WalletAddressListViewModelBase with Store { @computed WalletAddressListItem get address => - WalletAddressListItem(address: _wallet.address); + WalletAddressListItem(address: _wallet.walletAddresses.address); @computed PaymentURI get uri { @@ -105,8 +105,10 @@ abstract class WalletAddressListViewModelBase with Store { final addressList = ObservableList(); if (wallet is MoneroWallet) { - final primaryAddress = wallet.subaddressList.subaddresses.first; - addressList.addAll(wallet.subaddressList.subaddresses.map((subaddress) { + final primaryAddress = + wallet.walletAddresses.subaddressList.subaddresses.first; + addressList.addAll(wallet.walletAddresses.subaddressList.subaddresses + .map((subaddress) { final isPrimary = subaddress == primaryAddress; return WalletAddressListItem( @@ -118,8 +120,8 @@ abstract class WalletAddressListViewModelBase with Store { } if (wallet is BitcoinWallet) { - final primaryAddress = wallet.addresses.first; - final bitcoinAddresses = wallet.addresses.map((addr) { + final primaryAddress = wallet.walletAddresses.addresses.first; + final bitcoinAddresses = wallet.walletAddresses.addresses.map((addr) { final isPrimary = addr == primaryAddress; return WalletAddressListItem( @@ -139,7 +141,7 @@ abstract class WalletAddressListViewModelBase with Store { final wallet = _wallet; if (wallet is MoneroWallet) { - return wallet.account.label; + return wallet.walletAddresses.account.label; } return null; @@ -160,7 +162,7 @@ abstract class WalletAddressListViewModelBase with Store { @action void setAddress(WalletAddressListItem address) => - _wallet.address = address.address; + _wallet.walletAddresses.address = address.address; void _init() { _baseItems = []; @@ -177,7 +179,8 @@ abstract class WalletAddressListViewModelBase with Store { final wallet = _wallet; if (wallet is ElectrumWallet) { - wallet.nextAddress(); + wallet.walletAddresses.nextAddress(); + wallet.save(); } } } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 58ee24087..402d3be8f 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -50,7 +50,7 @@ abstract class WalletCreationVMBase with Store { dirPath: dirPath); credentials.walletInfo = walletInfo; final wallet = await process(credentials); - walletInfo.address = wallet.address; + walletInfo.address = wallet.walletAddresses.address; await _walletInfoSource.add(walletInfo); _appStore.changeCurrentWallet(wallet); _appStore.authenticationStore.allowed();