diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index a2b38c708..ddcdb5856 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -23,7 +23,8 @@ class CryptoCurrency extends EnumerableItem with Serializable { CryptoCurrency.usdt, CryptoCurrency.usdterc20, CryptoCurrency.xlm, - CryptoCurrency.xrp + CryptoCurrency.xrp, + CryptoCurrency.xhv ]; static const xmr = CryptoCurrency(title: 'XMR', raw: 0); static const ada = CryptoCurrency(title: 'ADA', raw: 1); diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 449b15b4b..6a39fa63f 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -98,7 +98,7 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { case WalletType.litecoin: return CryptoCurrency.ltc; case WalletType.haven: - return CryptoCurrency.xmr; + return CryptoCurrency.xhv; default: return null; } diff --git a/cw_haven/lib/haven_wallet.dart b/cw_haven/lib/haven_wallet.dart index 29dfcd589..220d20fc2 100644 --- a/cw_haven/lib/haven_wallet.dart +++ b/cw_haven/lib/haven_wallet.dart @@ -353,7 +353,7 @@ abstract class HavenWalletBase extends WalletBase { return getBitcoinWordList(language); case WalletType.monero: return monero.getMoneroWordList(language); + case WalletType.haven: + return haven.getMoneroWordList(language); default: return []; } diff --git a/lib/entities/update_haven_rate.dart b/lib/entities/update_haven_rate.dart index b6221f5f1..0fe0078d1 100644 --- a/lib/entities/update_haven_rate.dart +++ b/lib/entities/update_haven_rate.dart @@ -10,6 +10,12 @@ Future updateHavenRate(FiatConversionStore fiatConversionStore) async { final cur = CryptoCurrency.fromString(row.getAssetType()); final baseRate = moneroAmountToDouble(amount: base.getRate()); final rowRate = moneroAmountToDouble(amount: row.getRate()); + + if (cur == CryptoCurrency.xusd) { + fiatConversionStore.prices[cur] = rowRate; + return; + } + fiatConversionStore.prices[cur] = baseRate * rowRate; }); } \ No newline at end of file diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index ee014f321..ab1838d58 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -53,7 +53,7 @@ void startCurrentWalletChangeReaction(AppStore appStore, wallet) async { try { final node = settingsStore.getCurrentNode(wallet.type); - startWalletSyncStatusChangeReaction(wallet); + startWalletSyncStatusChangeReaction(wallet, fiatConversionStore); startCheckConnectionReaction(wallet, settingsStore); await getIt .get() diff --git a/lib/reactions/on_wallet_sync_status_change.dart b/lib/reactions/on_wallet_sync_status_change.dart index bb245898c..4ee5821e3 100644 --- a/lib/reactions/on_wallet_sync_status_change.dart +++ b/lib/reactions/on_wallet_sync_status_change.dart @@ -1,5 +1,8 @@ import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/entities/wake_lock.dart'; +import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_base.dart'; @@ -12,14 +15,18 @@ ReactionDisposer _onWalletSyncStatusChangeReaction; void startWalletSyncStatusChangeReaction( WalletBase, - TransactionInfo> - wallet) { + TransactionInfo> wallet, + FiatConversionStore fiatConversionStore) { final _wakeLock = getIt.get(); _onWalletSyncStatusChangeReaction?.reaction?.dispose(); _onWalletSyncStatusChangeReaction = reaction((_) => wallet.syncStatus, (SyncStatus status) async { if (status is ConnectedSyncStatus) { await wallet.startSync(); + + if (wallet.type == WalletType.haven) { + await updateHavenRate(fiatConversionStore); + } } if (status is SyncingSyncStatus) { await _wakeLock.enableWake(); diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index e29b78a1e..dca2afdf8 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -224,6 +224,9 @@ class ContactListPage extends BasePage { case CryptoCurrency.xrp: image = Image.asset('assets/images/xrp.png', height: 24, width: 24); break; + case CryptoCurrency.xhv: + image = Image.asset('assets/images/haven_logo.png', height: 24, width: 24); + break; default: image = null; } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 1b8de7b1a..d27c83a7e 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -146,13 +146,13 @@ class DashboardPage extends BasePage { image: exchangeImage, title: S.of(context).exchange, route: Routes.exchange), - if (!isMoneroOnly) + if (!isMoneroOnly && !isHaven) ActionButton( image: buyImage, title: S.of(context).buy, onClick: () async => await _onClickBuyButton(context), ), - if (!isMoneroOnly) + if (!isMoneroOnly && !isHaven) ActionButton( image: sellImage, title: S.of(context).sell, diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index a0d314ec2..a54d48ee7 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -130,7 +130,8 @@ class WalletRestoreFromSeedFormState extends State { BlockchainHeightWidget( focusNode: widget.blockHeightFocusNode, key: blockchainHeightKey, - onHeightOrDateEntered: widget.onHeightOrDateEntered) + onHeightOrDateEntered: widget.onHeightOrDateEntered, + hasDatePicker: widget.type == WalletType.monero) ])); } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 1dbb1b8b7..65b6c03ec 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -215,7 +215,7 @@ class WalletRestorePage extends BasePage { .text .split(' '); - if (walletRestoreViewModel.type == WalletType.monero && + if ((walletRestoreViewModel.type == WalletType.monero || walletRestoreViewModel.type == WalletType.haven) && seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) { return false; } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index c04d7cdb3..2d2200c9f 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -255,7 +255,7 @@ class SendPage extends BasePage { padding: EdgeInsets.only(bottom: 12), child: PrimaryButton( onPressed: () => presentCurrencyPicker(context), - text: 'Change currency (${sendViewModel.selectedCryptoCurrency})', + text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})', color: Colors.transparent, textColor: Theme.of(context) .accentTextTheme diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index a341ff82d..7782524f2 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -391,7 +391,7 @@ class SendCardState extends State .toString() + ' ' + sendViewModel - .currency.title, + .selectedCryptoCurrency.toString(), style: TextStyle( fontSize: 12, fontWeight: diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart index b87e83bc5..dab3fdd26 100644 --- a/lib/src/widgets/blockchain_height_widget.dart +++ b/lib/src/widgets/blockchain_height_widget.dart @@ -7,12 +7,13 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class BlockchainHeightWidget extends StatefulWidget { BlockchainHeightWidget({GlobalKey key, this.onHeightChange, this.focusNode, - this.onHeightOrDateEntered}) + this.onHeightOrDateEntered, this.hasDatePicker}) : super(key: key); final Function(int) onHeightChange; final Function(bool) onHeightOrDateEntered; final FocusNode focusNode; + final bool hasDatePicker; @override State createState() => BlockchainHeightState(); @@ -67,43 +68,45 @@ class BlockchainHeightState extends State { ))) ], ), - Padding( - padding: EdgeInsets.only(top: 15, bottom: 15), - child: Text( - S.of(context).widgets_or, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.title.color), - ), - ), - Row( - children: [ - Flexible( - child: Container( - child: InkWell( - onTap: () => _selectDate(context), - child: IgnorePointer( - child: BaseTextFormField( - controller: dateController, - hintText: S.of(context).widgets_restore_from_date, - )), - ), - )) - ], - ), - Padding( - padding: EdgeInsets.only(left: 40, right: 40, top: 24), - child: Text( - S.of(context).restore_from_date_or_blockheight, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.normal, - color: Theme.of(context).hintColor + if (widget.hasDatePicker) ...[ + Padding( + padding: EdgeInsets.only(top: 15, bottom: 15), + child: Text( + S.of(context).widgets_or, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w500, + color: Theme.of(context).primaryTextTheme.title.color), ), ), - ) + Row( + children: [ + Flexible( + child: Container( + child: InkWell( + onTap: () => _selectDate(context), + child: IgnorePointer( + child: BaseTextFormField( + controller: dateController, + hintText: S.of(context).widgets_restore_from_date, + )), + ), + )) + ], + ), + Padding( + padding: EdgeInsets.only(left: 40, right: 40, top: 24), + child: Text( + S.of(context).restore_from_date_or_blockheight, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: Theme.of(context).hintColor + ), + ), + ) + ] ], ); } diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index a097e59cf..ef7e03189 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -41,7 +41,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get isReady => (address?.isNotEmpty ?? false) && (port?.isNotEmpty ?? false); - bool get hasAuthCredentials => _wallet.type == WalletType.monero; + bool get hasAuthCredentials => _wallet.type == WalletType.monero || + _wallet.type == WalletType.haven; String get uri { var uri = address; diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 04ef9da07..8dfa3303e 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; +import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; @@ -77,6 +78,9 @@ abstract class OutputBase with Store { _amount = bitcoin.formatterStringDoubleToBitcoinAmount(_cryptoAmount); break; + case WalletType.haven: + _amount = haven.formatterMoneroParseAmount(amount: _cryptoAmount); + break; default: break; } @@ -106,6 +110,10 @@ abstract class OutputBase with Store { if (_wallet.type == WalletType.monero) { return monero.formatterMoneroAmountToDouble(amount: fee); } + + if (_wallet.type == WalletType.haven) { + return haven.formatterMoneroAmountToDouble(amount: fee); + } } catch (e) { print(e.toString()); } @@ -208,6 +216,9 @@ abstract class OutputBase with Store { case WalletType.litecoin: maximumFractionDigits = 8; break; + case WalletType.haven: + maximumFractionDigits = 12; + break; default: break; } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index da9543b43..4acf9f3d5 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -24,6 +24,7 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/haven/haven.dart'; part 'send_view_model.g.dart'; @@ -225,6 +226,11 @@ abstract class SendViewModelBase with Store { return monero.createMoneroTransactionCreationCredentials( outputs: outputs, priority: priority); + case WalletType.haven: + final priority = _settingsStore.priority[_wallet.type]; + + return haven.createHavenTransactionCreationCredentials( + outputs: outputs, priority: priority); default: return null; } diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index b2c4f80ae..34f4ea2b6 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -5,6 +5,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/haven/haven.dart'; part 'wallet_keys_view_model.g.dart'; @@ -29,6 +30,22 @@ abstract class WalletKeysViewModelBase with Store { ]); } + if (wallet.type == WalletType.haven) { + final keys = haven.getKeys(wallet); + + items.addAll([ + StandartListItem( + title: S.current.spend_key_public, value: keys['publicSpendKey']), + StandartListItem( + title: S.current.spend_key_private, value: keys['privateSpendKey']), + StandartListItem( + title: S.current.view_key_public, value: keys['publicViewKey']), + StandartListItem( + title: S.current.view_key_private, value: keys['privateViewKey']), + StandartListItem(title: S.current.wallet_seed, value: wallet.seed), + ]); + } + if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) { final keys = bitcoin.getWalletKeys(wallet); diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 9e47fd8d5..1943f76b9 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -65,7 +65,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.monero: return monero.createMoneroRestoreWalletFromSeedCredentials( name: name, - height: height, + height: height ?? 0, mnemonic: seed, password: password); case WalletType.bitcoin: @@ -81,7 +81,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.haven: return haven.createHavenRestoreWalletFromSeedCredentials( name: name, - height: height, + height: height ?? 0, mnemonic: seed, password: password); default: @@ -94,14 +94,27 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { final spendKey = options['spendKey'] as String; final address = options['address'] as String; - return monero.createMoneroRestoreWalletFromKeysCredentials( - name: name, - height: height, - spendKey: spendKey, - viewKey: viewKey, - address: address, - password: password, - language: 'English'); + if (type == WalletType.monero) { + return monero.createMoneroRestoreWalletFromKeysCredentials( + name: name, + height: height, + spendKey: spendKey, + viewKey: viewKey, + address: address, + password: password, + language: 'English'); + } + + if (type == WalletType.haven) { + return haven.createHavenRestoreWalletFromKeysCredentials( + name: name, + height: height, + spendKey: spendKey, + viewKey: viewKey, + address: address, + password: password, + language: 'English'); + } } return null;