import 'dart:convert'; import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart'; import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; import 'package:cake_wallet/entities/balance.dart'; import 'package:cake_wallet/entities/find_order_by_id.dart'; import 'package:cake_wallet/entities/order.dart'; import 'package:cake_wallet/entities/transaction_history.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/monero/account.dart'; import 'package:cake_wallet/monero/monero_balance.dart'; import 'package:cake_wallet/monero/monero_transaction_history.dart'; import 'package:cake_wallet/monero/monero_transaction_info.dart'; import 'package:cake_wallet/monero/monero_wallet.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/transaction_direction.dart'; import 'package:cake_wallet/entities/transaction_info.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; import 'package:cake_wallet/utils/mobx.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/filter_item.dart'; import 'package:cake_wallet/view_model/dashboard/order_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; import 'package:http/http.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/wallet_base.dart'; import 'package:cake_wallet/entities/sync_status.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:convert/convert.dart'; part 'dashboard_view_model.g.dart'; class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel; abstract class DashboardViewModelBase with Store { DashboardViewModelBase( {this.balanceViewModel, this.appStore, this.tradesStore, this.tradeFilterStore, this.transactionFilterStore, this.ordersSource, this.ordersStore}) { filterItems = { S.current.transactions: [ FilterItem( value: () => transactionFilterStore.displayIncoming, caption: S.current.incoming, onChanged: (value) => transactionFilterStore.toggleIncoming()), FilterItem( value: () => transactionFilterStore.displayOutgoing, caption: S.current.outgoing, onChanged: (value) => transactionFilterStore.toggleOutgoing()), // FilterItem( // value: () => false, // caption: S.current.transactions_by_date, // onChanged: null), ], S.current.trades: [ FilterItem( value: () => tradeFilterStore.displayXMRTO, caption: 'XMR.TO', onChanged: (value) => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.xmrto)), FilterItem( value: () => tradeFilterStore.displayChangeNow, caption: 'Change.NOW', onChanged: (value) => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.changeNow)), FilterItem( value: () => tradeFilterStore.displayMorphToken, caption: 'MorphToken', onChanged: (value) => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.morphToken)), ] }; name = appStore.wallet?.name; wallet ??= appStore.wallet; type = wallet.type; _reaction = reaction((_) => appStore.wallet, _onWalletChange); final _wallet = wallet; if (_wallet is MoneroWallet) { subname = _wallet.account?.label; _onMoneroAccountChangeReaction = reaction((_) => _wallet.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) .toList(); transactions = ObservableList.of(_accountTransactions.map((transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore))); } else { transactions = ObservableList.of(wallet .transactionHistory.transactions.values .map((transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore))); } connectMapToListWithTransform( appStore.wallet.transactionHistory.transactions, transactions, (TransactionInfo val) => TransactionListItem( transaction: val, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore), filter: (TransactionInfo tx) { final wallet = _wallet; if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { return tx.accountIndex == wallet.account.id; } return true; }); dataChannel.setMessageHandler((ByteData message) async { final type = ByteData.view(message.buffer, 0, 4).getInt32(0); switch (type) { case _dataExists: print('Wyre: Data exists'); break; case _dataNotExists: print('Wyre: Data not exists'); break; } return ByteData(0); }); } static const dataChannel = BasicMessageChannel('data_change', BinaryCodec()); static const _dataExists = 1; static const _dataNotExists = 0; @observable WalletType type; @observable String name; @observable ObservableList transactions; @observable String subname; @computed String get address => wallet.address; @computed SyncStatus get status => wallet.syncStatus; @computed String get syncStatusText { var statusText = ''; if (status is SyncingSyncStatus) { statusText = S.current.Blocks_remaining(status.toString()); } if (status is FailedSyncStatus || status is LostConnectionSyncStatus) { statusText = S.current.please_try_to_connect_to_another_node; } return statusText; } @computed BalanceDisplayMode get balanceDisplayMode => appStore.settingsStore.balanceDisplayMode; @computed List get trades => tradesStore.trades .where((trade) => trade.trade.walletId == wallet.id) .toList(); @computed List get orders => ordersStore.orders .where((item) => item.order.walletId == wallet.id) .toList(); @computed double get price => balanceViewModel.price; @computed List get items { final _items = []; _items.addAll(transactionFilterStore.filtered(transactions: transactions)); _items.addAll(tradeFilterStore.filtered(trades: trades, wallet: wallet)); _items.addAll(orders); return formattedItemsList(_items); } @observable WalletBase wallet; bool get hasRescan => wallet.type == WalletType.monero; Box ordersSource; BalanceViewModel balanceViewModel; AppStore appStore; TradesStore tradesStore; OrdersStore ordersStore; TradeFilterStore tradeFilterStore; TransactionFilterStore transactionFilterStore; Map> filterItems; ReactionDisposer _reaction; ReactionDisposer _onMoneroAccountChangeReaction; ReactionDisposer _onMoneroBalanceChangeReaction; Future reconnect() async { final node = appStore.settingsStore.getCurrentNode(wallet.type); await wallet.connectToNode(node: node); } @action void _onWalletChange(WalletBase wallet) { this.wallet = wallet; type = wallet.type; name = wallet.name; if (wallet is MoneroWallet) { subname = wallet.account?.label; _onMoneroAccountChangeReaction?.reaction?.dispose(); _onMoneroBalanceChangeReaction?.reaction?.dispose(); _onMoneroAccountChangeReaction = reaction((_) => wallet.account, (Account account) => _onMoneroAccountChange(wallet)); _onMoneroBalanceChangeReaction = reaction((_) => wallet.balance, (MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet)); _onMoneroTransactionsUpdate(wallet); } else { subname = null; transactions.clear(); transactions.addAll(wallet.transactionHistory.transactions.values.map( (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore))); } connectMapToListWithTransform( appStore.wallet.transactionHistory.transactions, transactions, (TransactionInfo val) => TransactionListItem( transaction: val, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore), filter: (TransactionInfo tx) { if (tx is MoneroTransactionInfo && wallet is MoneroWallet) { return tx.accountIndex == wallet.account.id; } return true; }); } @action void _onMoneroAccountChange(MoneroWallet wallet) { subname = wallet.account?.label; _onMoneroTransactionsUpdate(wallet); } @action void _onMoneroTransactionsUpdate(MoneroWallet wallet) { transactions.clear(); final _accountTransactions = wallet.transactionHistory.transactions.values .where((tx) => tx.accountIndex == wallet.account.id) .toList(); transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, settingsStore: appStore.settingsStore))); } Future getWyreUrl() async { final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); final url = 'https://api.testwyre.com/v3/orders/reserve' + '?timestamp=' + timestamp; final apiKey = secrets.wyreApiKey; final secretKey = secrets.wyreSecretKey; final accountId = secrets.wyreAccountId; final body = { //'destCurrency' : walletTypeToCryptoCurrency(type).title, //'dest' : walletTypeToString(type).toLowerCase() + ':' + address, 'referrerAccountId' : accountId, //'lockFields' : ['destCurrency', 'dest'] }; final response = await post(url, headers: { 'Authorization': 'Bearer $secretKey', 'Content-Type': 'application/json', 'cache-control': 'no-cache' }, body: json.encode(body) ); if (response.statusCode == 200) { final responseJSON = json.decode(response.body) as Map; final urlFromResponse = responseJSON['url'] as String; return urlFromResponse; } else { return ''; } } Future saveOrder(String orderId) async { final order = await findOrderById(orderId); order.receiveAddress = address; order.walletId = wallet.id; await ordersSource.add(order); ordersStore.setOrder(order); } }