dev
dart 233 lines 9.02 KB
Raw
1 import 'dart:async';
2
3 import 'package:cake_wallet/exchange/exchange_provider_description.dart';
4 import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
5 import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart';
6 import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
7 import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart';
8 import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart';
9 import 'package:cake_wallet/exchange/provider/jupiter_exchange_provider.dart';
10 import 'package:cake_wallet/exchange/provider/near_Intents_exchange_provider.dart';
11 import 'package:cake_wallet/exchange/provider/swapsxyz_exchange_provider.dart';
12 import 'package:cake_wallet/exchange/provider/swaptrade_exchange_provider.dart';
13 import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
14 import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart';
15 import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
16 import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
17 import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
18 import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
19 import 'package:cake_wallet/exchange/trade.dart';
20 import 'package:cake_wallet/generated/i18n.dart';
21 import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart';
22 import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart';
23 import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart';
24 import 'package:cake_wallet/src/screens/trade_details/trade_provider_unsupported_item.dart';
25 import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
26 import 'package:cake_wallet/store/app_store.dart';
27 import 'package:cake_wallet/utils/date_formatter.dart';
28 import 'package:cake_wallet/utils/show_bar.dart';
29 import 'package:cw_core/currencies_with_memo.dart';
30 import 'package:cw_core/utils/print_verbose.dart';
31 import 'package:flutter/services.dart';
32 import 'package:mobx/mobx.dart';
33 import 'package:url_launcher/url_launcher.dart';
34
35 part 'trade_details_view_model.g.dart';
36
37 class TradeDetailsViewModel = TradeDetailsViewModelBase with _$TradeDetailsViewModel;
38
39 abstract class TradeDetailsViewModelBase with Store {
40 TradeDetailsViewModelBase({
41 required Trade tradeForDetails,
42 required this.appStore,
43 }) : items = ObservableList<StandartListItem>(),
44 trade = tradeForDetails {
45 switch (trade.provider) {
46 case ExchangeProviderDescription.changeNow:
47 _provider = ChangeNowExchangeProvider(settingsStore: appStore.settingsStore);
48 break;
49 case ExchangeProviderDescription.sideShift:
50 _provider = SideShiftExchangeProvider();
51 break;
52 case ExchangeProviderDescription.simpleSwap:
53 _provider = SimpleSwapExchangeProvider();
54 break;
55 case ExchangeProviderDescription.trocador:
56 _provider = TrocadorExchangeProvider();
57 break;
58 case ExchangeProviderDescription.exolix:
59 _provider = ExolixExchangeProvider();
60 break;
61 case ExchangeProviderDescription.thorChain:
62 _provider = ThorChainExchangeProvider();
63 break;
64 case ExchangeProviderDescription.swapTrade:
65 _provider = SwapTradeExchangeProvider();
66 case ExchangeProviderDescription.letsExchange:
67 _provider = LetsExchangeExchangeProvider();
68 break;
69 case ExchangeProviderDescription.stealthEx:
70 _provider = StealthExExchangeProvider();
71 break;
72 case ExchangeProviderDescription.chainflip:
73 _provider = ChainflipExchangeProvider();
74 break;
75 case ExchangeProviderDescription.xoSwap:
76 _provider = XOSwapExchangeProvider();
77 break;
78 case ExchangeProviderDescription.swapsXyz:
79 _provider = SwapsXyzExchangeProvider();
80 break;
81 case ExchangeProviderDescription.jupiter:
82 _provider = JupiterExchangeProvider();
83 break;
84 case ExchangeProviderDescription.nearIntents:
85 _provider = NearIntentsExchangeProvider();
86 break;
87 }
88
89 _updateItems();
90
91 if (_provider != null) {
92 _updateTrade();
93 timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade());
94 }
95 }
96
97 static String? getTrackUrl(ExchangeProviderDescription provider, Trade trade) {
98 switch (provider) {
99 case ExchangeProviderDescription.changeNow:
100 return 'https://changenow.io/exchange/txs/${trade.id}';
101 case ExchangeProviderDescription.sideShift:
102 return 'https://sideshift.ai/orders/${trade.id}';
103 case ExchangeProviderDescription.simpleSwap:
104 return 'https://simpleswap.io/exchange?id=${trade.id}';
105 case ExchangeProviderDescription.trocador:
106 return 'https://trocador.app/en/checkout/${trade.id}';
107 case ExchangeProviderDescription.exolix:
108 return 'https://exolix.com/transaction/${trade.id}';
109 case ExchangeProviderDescription.thorChain:
110 return 'https://track.ninerealms.com/${trade.id}';
111 case ExchangeProviderDescription.swapTrade:
112 return 'https://swaptrade.io/send/${trade.id}';
113 case ExchangeProviderDescription.letsExchange:
114 return 'https://letsexchange.io/?transactionId=${trade.id}';
115 case ExchangeProviderDescription.stealthEx:
116 return 'https://stealthex.io/exchange/?id=${trade.id}';
117 case ExchangeProviderDescription.chainflip:
118 return 'https://scan.chainflip.io/channels/${trade.id}';
119 case ExchangeProviderDescription.xoSwap:
120 return 'https://orders.xoswap.com/${trade.id}';
121 case ExchangeProviderDescription.swapsXyz:
122 return 'https://scan.swaps.xyz/transactions/${trade.id}';
123 case ExchangeProviderDescription.jupiter:
124 return 'https://solscan.io/tx/${trade.txId}';
125 case ExchangeProviderDescription.nearIntents:
126 return 'https://explorer.near-intents.org/transactions/${trade.id}';
127 }
128 return null;
129 }
130
131 @observable
132 Trade trade;
133
134 @observable
135 ObservableList<StandartListItem> items;
136
137 ExchangeProvider? _provider;
138
139 Timer? timer;
140
141 final AppStore appStore;
142
143 @action
144 Future<void> _updateTrade() async {
145 try {
146 final updatedTrade = await _provider!.findTradeById(id: trade.id);
147
148 trade.mergeFindTradeByIdResult(updatedTrade);
149 await trade.save();
150
151 _updateItems();
152 } catch (e) {
153 printV(e.toString());
154 }
155 }
156
157 void _updateItems() {
158 final dateFormat = DateFormatter.withCurrentLocal(reverse: true);
159
160 items.clear();
161
162 if (_provider == null)
163 items.add(TradeProviderUnsupportedItem(
164 error: S.current.exchange_provider_unsupported(trade.provider.title)));
165
166 items.add(
167 DetailsListStatusItem(title: S.current.trade_details_state, value: trade.state.toString()));
168
169 final tradeFrom = trade.from;
170 final tradeTo = trade.to;
171
172 if (tradeFrom != null && tradeTo != null) {
173 items.add(TradeDetailsListCardItem.tradeDetails(
174 id: trade.id,
175 extraId: trade.extraId,
176 createdAt: trade.createdAt != null ? dateFormat.format(trade.createdAt!) : '',
177 from: tradeFrom,
178 to: tradeTo,
179 onTap: (context) {
180 Clipboard.setData(ClipboardData(text: trade.id));
181 showBar<void>(context, S.of(context).copied_to_clipboard);
182 },
183 ));
184 }
185
186 final destinationMemo = trade.toAddressExtraId;
187 final destinationCurrency = trade.to;
188 if (destinationMemo != null && destinationMemo.isNotEmpty && destinationCurrency != null) {
189 final isDestinationTag =
190 memoLabelTypeFor(destinationCurrency) == MemoLabelType.destinationTag;
191 items.add(StandartListItem(
192 title: isDestinationTag ? S.current.destination_tag : S.current.memo,
193 value: destinationMemo));
194 }
195
196 items.add(StandartListItem(
197 title: S.current.trade_details_provider, value: trade.provider.toString()));
198
199 final trackUrl = TradeDetailsViewModelBase.getTrackUrl(trade.provider, trade);
200 if (trackUrl != null) {
201 items.add(TrackTradeListItem(
202 title: S.current.track, value: trackUrl, onTap: () => _launchUrl(trackUrl)));
203 }
204
205 if (trade.isRefund == true) {
206 items.add(StandartListItem(title: 'Refund', value: trade.refundAddress ?? ''));
207 }
208
209 if (trade.provider == ExchangeProviderDescription.trocador) {
210 items.add(StandartListItem(
211 title: '${trade.providerName} ${S.current.id.toUpperCase()}',
212 value: trade.providerId ?? ''));
213
214 if (trade.password != null && trade.password!.isNotEmpty) {
215 items.add(StandartListItem(
216 title: '${trade.providerName} ${S.current.password}', value: trade.password ?? ''));
217 }
218 }
219
220 if (trade.provider == ExchangeProviderDescription.swapsXyz &&
221 trade.txId != null &&
222 trade.txId!.isNotEmpty) {
223 items.add(StandartListItem(title: 'Transaction ID', value: trade.txId!));
224 }
225 }
226
227 void _launchUrl(String url) {
228 final uri = Uri.parse(url);
229 try {
230 launchUrl(uri, mode: LaunchMode.externalApplication);
231 } catch (e) {}
232 }
233 }