feat: migrate Trade data to SQLite with TradeLegacy for backward compatibility (#3106)
What changed, and why it matters
This commit replaces the app's old storage system for swap/exchange records (called 'Trades') with a new SQLite database. It also adds a one-time migration that reads old records out of the encrypted Hive file and copies them into the new SQLite table. The change is a routine data-layer refactor with backward-compatibility logic. There is no direct evidence in the commit that this introduces theft of funds or private-key leaks, but any storage migration can carry risks of data loss, downgrade/replay issues, or subtle bugs if currency information is not preserved correctly.
Treat this as a high-touch migration change requiring QA, not as an active vulnerability. Verify that: (1) the legacy Hive migration runs exactly once and does not duplicate or overwrite trades; (2) the SQLite table is created with the same encryption/protection expectations as the legacy Hive box; (3) currency reconstruction from title/tag fallback does not misidentify assets; (4) the ConflictAlgorithm.replace behavior on 'id' cannot be abused to corrupt another user's trade record; (5) backup/restore logic correctly handles both legacy and new trade formats. No immediate patch for a security flaw is evident from the diff alone.
Security signals we found
Storage migration from encrypted Hive to SQLite for sensitive trade metadata
New SQLite table stores trade details including input/output addresses, refund addresses, payout addresses, memos, txIds, amounts, and provider identifiers
Migration code catches and logs per-record errors but continues migration, which could leave some records unconverted
SQLite save() uses ConflictAlgorithm.replace on the 'id' column, so duplicate trade IDs will overwrite existing rows
Legacy encrypted Hive box is opened with the same encryption key during migration
Currency reconstruction now relies on stored title/tag fallback when raw id deserialization fails
No parameterized query issues visible; queries use sqflite's whereArgs binding
Evidence from the diff
The patch migrates the Trade model from Hive (an encrypted key-value/binary store) to SQLite via sqflite. A new TradeLegacy Hive adapter preserves the old binary schema so existing boxes can still be read, and performTradeHiveMigration() decrypts and copies each legacy Trade into the new Trade SQLite table. The Trade class is rewritten as a plain Dart class with CRUD methods (save, getAll, getByTradeId, deleteTrade) and a toSqliteMap/fromSqliteRow serializer. Currency snapshots are now stored as denormalized columns (title, tag, name, decimals, icon paths, raw id) instead of only a raw integer. The database version is bumped from 5 to 6 and a _createTradeTable migration is added. All call sites that previously passed a Hive Box
Changed components
cw_core/lib/db/sqlite.dartlib/exchange/trade.dartlib/exchange/trade_legacy.dartlib/exchange/trade_legacy.part.dartlib/exchange/trade_currency_snapshot.dartlib/core/backup_service.dartlib/core/trade_monitor.dartlib/store/dashboard/trades_store.dartlib/view_model/exchange/exchange_view_model.dartlib/view_model/exchange/exchange_trade_view_model.dartlib/view_model/trade_details_view_model.dartlib/entities/fs_migration.dartlib/main.dartAll exchange provider implementations under lib/exchange/provider/Inspect captured patch +1003 / −825
diff --git a/cw_core/lib/db/sqlite.dart b/cw_core/lib/db/sqlite.dart
index 8d716c44..311344a9 100644
--- a/cw_core/lib/db/sqlite.dart
+++ b/cw_core/lib/db/sqlite.dart
@@ -41,7 +41,7 @@ Future<void> initDb({String? pathOverride}) async {
}
}
await db?.close();
- db = await openDatabase(dbFile.path, version: 5,
+ db = await openDatabase(dbFile.path, version: 6,
onUpgrade: (Database db, int oldVersion, int newVersion) async {
printV("migrating: $oldVersion, $newVersion");
if (oldVersion <= 1) {
@@ -93,6 +93,9 @@ CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
if (oldVersion <= 4) {
await _createBridgeTransferTable(db);
}
+ if (oldVersion <= 5) {
+ await _createTradeTable(db);
+ }
},
onCreate: (Database db, int version) async {
await db.execute(
@@ -191,10 +194,73 @@ CREATE TABLE BalanceCardStyleSettings (
);
''');
await _createBridgeTransferTable(db);
+ await _createTradeTable(db);
}
);
}
+Future<void> _createTradeTable(Database db) async {
+ await db.execute('''
+CREATE TABLE IF NOT EXISTS Trade (
+ tradeId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ id TEXT NOT NULL,
+ providerRaw INTEGER NOT NULL DEFAULT 0,
+ fromTitle TEXT,
+ fromName TEXT,
+ fromTag TEXT,
+ fromFullName TEXT,
+ fromDecimals INTEGER,
+ fromRaw INTEGER,
+ fromIconPath TEXT,
+ fromFlatIconPath TEXT,
+ fromChainIconPath TEXT,
+ toTitle TEXT,
+ toName TEXT,
+ toTag TEXT,
+ toFullName TEXT,
+ toDecimals INTEGER,
+ toRaw INTEGER,
+ toIconPath TEXT,
+ toFlatIconPath TEXT,
+ toChainIconPath TEXT,
+ stateRaw TEXT NOT NULL DEFAULT '',
+ createdAt INTEGER,
+ expiredAt INTEGER,
+ amount TEXT NOT NULL DEFAULT '',
+ receiveAmount TEXT,
+ inputAddress TEXT,
+ extraId TEXT,
+ outputTransaction TEXT,
+ refundAddress TEXT,
+ walletId TEXT,
+ payoutAddress TEXT,
+ password TEXT,
+ providerId TEXT,
+ providerName TEXT,
+ fromWalletAddress TEXT,
+ memo TEXT,
+ txId TEXT,
+ isRefund INTEGER DEFAULT 0,
+ isSendAll INTEGER DEFAULT 0,
+ router TEXT,
+ needToRegisterInSwapXyz INTEGER DEFAULT 0,
+ sourceTokenAddress TEXT,
+ sourceTokenDecimals INTEGER,
+ routerData TEXT,
+ routerValue TEXT,
+ routerChainId INTEGER,
+ sourceTokenAmountRaw TEXT,
+ requiresTokenApproval INTEGER DEFAULT 0,
+ chainId INTEGER,
+ fee REAL
+);
+''');
+ await db.execute('''
+CREATE UNIQUE INDEX IF NOT EXISTS idx_trade_id_unique
+ON Trade (id);
+''');
+}
+
Future<Map<String, dynamic>> dumpDb() async {
try {
return await _dumpDb();
diff --git a/cw_core/lib/wallet_info_legacy.dart b/cw_core/lib/wallet_info_legacy.dart
index a7e6bc31..4c665124 100644
--- a/cw_core/lib/wallet_info_legacy.dart
+++ b/cw_core/lib/wallet_info_legacy.dart
@@ -246,35 +246,35 @@ class WalletInfo extends HiveObject {
Future<void> migrateToSqlite() async {
final di = newWi.DerivationInfo(
id: 0,
- derivationType: derivationInfo?.derivationType ?? derivationType ?? newWi.DerivationType.unknown,
+ derivationType:
+ derivationInfo?.derivationType ?? derivationType ?? newWi.DerivationType.unknown,
derivationPath: derivationInfo?.derivationPath ?? derivationPath ?? '',
);
final derivationInfoId = await di.save();
final walletInfo = newWi.WalletInfo(
- 0,
- id,
- name,
- type,
- isRecovery,
- restoreHeight,
- timestamp,
- dirPath,
- path,
- address,
- yatEid,
- yatLastUsedAddressRaw,
- showIntroCakePayCard,
- derivationInfoId,
- hardwareWalletType,
- parentAddress,
- hashedWalletIdentifier,
- isNonSeedWallet,
- 0,
- addressPageType,
- false,
- true,
- null
- );
+ 0,
+ id,
+ name,
+ type,
+ isRecovery,
+ restoreHeight,
+ timestamp,
+ dirPath,
+ path,
+ address,
+ yatEid,
+ yatLastUsedAddressRaw,
+ showIntroCakePayCard,
+ derivationInfoId,
+ hardwareWalletType,
+ parentAddress,
+ hashedWalletIdentifier,
+ isNonSeedWallet,
+ 0,
+ addressPageType,
+ false,
+ true,
+ null);
final wiId = await walletInfo.save();
for (final address in usedAddresses ?? <String>[]) {
await newWi.WalletInfoAddress.insert(wiId, newWi.WalletInfoAddressType.used, address);
@@ -289,8 +289,8 @@ class WalletInfo extends HiveObject {
for (final address in addressInfos![i] ?? <AddressInfo>[]) {
await newWi.WalletInfoAddressInfo.insert(
walletInfoId: wiId,
- mapKey: i,
- accountIndex: address.accountIndex??0,
+ mapKey: i,
+ accountIndex: address.accountIndex ?? 0,
address: address.address,
label: address.label,
);
@@ -304,8 +304,12 @@ class WalletInfo extends HiveObject {
final sw = Stopwatch()..start();
final list = box.values.toList();
for (final wi in list) {
- await wi.migrateToSqlite();
- await wi.delete();
+ try {
+ await wi.migrateToSqlite();
+ await wi.delete();
+ } catch (e) {
+ printV('Error migrating WalletInfo ${wi.id}: $e');
+ }
}
printV('Migrating WalletInfo to SQLite: end (${sw.elapsedMilliseconds}ms)');
}
diff --git a/integration_test/robots/transactions_page_robot.dart b/integration_test/robots/transactions_page_robot.dart
index e659626e..1365c54c 100644
--- a/integration_test/robots/transactions_page_robot.dart
+++ b/integration_test/robots/transactions_page_robot.dart
@@ -385,8 +385,8 @@ class TransactionsPageRobot {
Future<void> _verifyTradeListItemDisplay(TradeListItem item) async {
final keyId = 'trade_list_item_${item.trade.id}_key';
- final from = item.trade.from?.toString() ?? item.trade.userCurrencyFrom.toString();
- final to = item.trade.to?.toString() ?? item.trade.userCurrencyTo.toString();
+ final from = item.trade.from?.toString() ?? '';
+ final to = item.trade.to?.toString() ?? '';
//* ==============Confirm it has the right key for this item ========
commonTestCases.hasValueKey(keyId);
diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart
index 2db105c1..5daab7d4 100644
--- a/lib/core/backup_service.dart
+++ b/lib/core/backup_service.dart
@@ -19,6 +19,7 @@ import 'package:cake_wallet/entities/encrypt.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cw_core/wallet_info.dart';
+import 'package:cake_wallet/exchange/trade_legacy.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/wallet_types.g.dart';
import 'package:cake_backup/backup.dart' as cake_backup;
@@ -110,6 +111,7 @@ class $BackupService {
Future<void> verifyWallets() async {
await performHiveMigration(); // for backups made before sqlite migration
+ await performTradeHiveMigration(_secureStorage);
correctWallets = (await WalletInfo.getAll()).where((info) => availableWalletTypes.contains(info.type)).toList();
if (correctWallets.isEmpty) {
diff --git a/lib/core/trade_monitor.dart b/lib/core/trade_monitor.dart
index 07cd3eec..59327570 100644
--- a/lib/core/trade_monitor.dart
+++ b/lib/core/trade_monitor.dart
@@ -20,7 +20,6 @@ import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
import 'package:cw_core/utils/print_verbose.dart';
-import 'package:hive/hive.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -30,13 +29,11 @@ class TradeMonitor {
TradeMonitor({
required this.tradesStore,
- required this.trades,
required this.appStore,
required this.preferences,
});
final TradesStore tradesStore;
- final Box<Trade> trades;
final AppStore appStore;
final Map<String, Timer> _tradeTimers = {};
final SharedPreferences preferences;
@@ -54,7 +51,7 @@ class TradeMonitor {
case ExchangeProviderDescription.exolix:
return ExolixExchangeProvider();
case ExchangeProviderDescription.thorChain:
- return ThorChainExchangeProvider(tradesStore: trades);
+ return ThorChainExchangeProvider();
case ExchangeProviderDescription.swapTrade:
return SwapTradeExchangeProvider();
case ExchangeProviderDescription.letsExchange:
@@ -62,7 +59,7 @@ class TradeMonitor {
case ExchangeProviderDescription.stealthEx:
return StealthExExchangeProvider();
case ExchangeProviderDescription.chainflip:
- return ChainflipExchangeProvider(tradesStore: trades);
+ return ChainflipExchangeProvider();
case ExchangeProviderDescription.xoSwap:
return XOSwapExchangeProvider();
case ExchangeProviderDescription.swapsXyz:
@@ -187,12 +184,7 @@ class TradeMonitor {
try {
final updated = await provider.findTradeById(id: trade.id);
- trade
- ..stateRaw = updated.state.raw
- ..receiveAmount = updated.receiveAmount ?? trade.receiveAmount
- ..outputTransaction = updated.outputTransaction ?? trade.outputTransaction
- ..userCurrencyToRaw = updated.userCurrencyToRaw
- ..userCurrencyFromRaw = updated.userCurrencyFromRaw;
+ trade.mergeFindTradeByIdResult(updated);
printV('Trade ${trade.id} updated: ${trade.state}');
await trade.save();
diff --git a/lib/di.dart b/lib/di.dart
index a4b3c0fd..50a7cefc 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -329,7 +329,6 @@ var _isSetupFinished = false;
late Box<Node> _nodeSource;
late Box<Node> _powNodeSource;
late Box<Contact> _contactSource;
-late Box<Trade> _tradesSource;
late Box<Template> _templates;
late Box<ExchangeTemplate> _exchangeTemplates;
late Box<TransactionDescription> _transactionDescriptionBox;
@@ -341,7 +340,6 @@ Future<void> setup({
required Box<Node> nodeSource,
required Box<Node> powNodeSource,
required Box<Contact> contactSource,
- required Box<Trade> tradesSource,
required Box<Template> templates,
required Box<ExchangeTemplate> exchangeTemplates,
required Box<TransactionDescription> transactionDescriptionBox,
@@ -355,7 +353,6 @@ Future<void> setup({
_nodeSource = nodeSource;
_powNodeSource = powNodeSource;
_contactSource = contactSource;
- _tradesSource = tradesSource;
_templates = templates;
_exchangeTemplates = exchangeTemplates;
_transactionDescriptionBox = transactionDescriptionBox;
@@ -402,7 +399,7 @@ Future<void> setup({
nodeListStore: getIt.get<NodeListStore>(),
themeStore: getIt.get<ThemeStore>()));
getIt.registerSingleton<TradesStore>(
- TradesStore(tradesSource: _tradesSource, appStore: getIt.get<AppStore>()));
+ TradesStore(appStore: getIt.get<AppStore>()));
getIt.registerSingleton<OrdersStore>(
OrdersStore(ordersSource: _ordersSource, settingsStore: getIt.get<SettingsStore>()));
getIt.registerSingleton<BridgeTransfersStore>(BridgeTransfersStore());
@@ -569,7 +566,6 @@ Future<void> setup({
getIt.registerFactory(
() => ExchangeViewModel(
getIt.get<AppStore>(),
- _tradesSource,
getIt.get<ExchangeTemplateStore>(),
getIt.get<TradesStore>(),
getIt.get<SharedPreferences>(),
@@ -583,7 +579,6 @@ Future<void> setup({
getIt.registerSingleton(
TradeMonitor(
tradesStore: getIt.get<TradesStore>(),
- trades: _tradesSource,
appStore: getIt.get<AppStore>(),
preferences: getIt.get<SharedPreferences>(),
),
@@ -1258,7 +1253,6 @@ Future<void> setup({
getIt.registerFactory(
() => ExchangeTradeViewModel(
wallet: getIt.get<AppStore>().wallet!,
- trades: _tradesSource,
tradesStore: getIt.get<TradesStore>(),
sendViewModel: getIt.get<SendViewModel>(),
feesViewModel: getIt.get<FeesViewModel>(),
@@ -1471,11 +1465,8 @@ Future<void> setup({
getIt.registerFactoryParam<TransactionSuccessPage, String, void>(
(content, _) => TransactionSuccessPage(content: content));
- getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
- TradeDetailsViewModel(
- tradeForDetails: trade,
- trades: _tradesSource,
- appStore: getIt.get<AppStore>()));
+ getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>(
+ (trade, _) => TradeDetailsViewModel(tradeForDetails: trade, appStore: getIt.get<AppStore>()));
getIt.registerFactory(() => CakeFeaturesViewModel(getIt.get<CakePayService>()));
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index e30672ed..df3977d0 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -13,7 +13,6 @@ import 'package:cake_wallet/entities/haven_seed_store.dart';
import 'package:cake_wallet/entities/node_list.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/secret_store_key.dart';
-import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:collection/collection.dart';
@@ -64,11 +63,10 @@ Future<void> defaultSettingsMigration(
required SecureStorage secureStorage,
required Box<Node> nodes,
required Box<Node> powNodes,
- required Box<Trade> tradeSource,
required Box<Contact> contactSource,
required Box<HavenSeedStore> havenSeedStore}) async {
if (Platform.isIOS) {
- await ios_migrate_v1(tradeSource, contactSource);
+ await ios_migrate_v1(contactSource);
}
// check current nodes for nullability regardless of the version
diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart
index a85c579b..d5d187ad 100644
--- a/lib/entities/fs_migration.dart
+++ b/lib/entities/fs_migration.dart
@@ -29,7 +29,7 @@ Future<void> migrate_android_v1() async {
await android_migrate_wallets(appDocDir: appDocDir);
}
-Future<void> ios_migrate_v1(Box<Trade> tradeSource, Box<Contact> contactSource) async {
+Future<void> ios_migrate_v1(Box<Contact> contactSource) async {
final prefs = await SharedPreferences.getInstance();
if (prefs.getBool('ios_migration_v1_completed') ?? false) {
@@ -40,7 +40,7 @@ Future<void> ios_migrate_v1(Box<Trade> tradeSource, Box<Contact> contactSource)
await ios_migrate_pin();
await ios_migrate_wallet_passwords();
await ios_migrate_wallet_info();
- await ios_migrate_trades_list(tradeSource);
+ await ios_migrate_trades_list();
await ios_migrate_address_book(contactSource);
await prefs.setBool('ios_migration_v1_completed', true);
@@ -343,7 +343,7 @@ Future<void> ios_migrate_wallet_info() async {
}
}
-Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
+Future<void> ios_migrate_trades_list() async {
final prefs = await SharedPreferences.getInstance();
if (prefs.getBool('ios_migration_trade_list_completed') ?? false) {
@@ -366,7 +366,8 @@ Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
final key = masterPassword!.replaceAll('-', '');
final decoded = await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt);
final decodedJson = json.decode(decoded) as List<dynamic>;
- final trades = decodedJson.map((dynamic el) {
+
+ for (final dynamic el in decodedJson) {
final elAsMap = el as Map<String, dynamic>;
final providerAsString = elAsMap['provider'] as String;
final fromAsString = elAsMap['from'] as String;
@@ -393,17 +394,19 @@ Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
break;
}
- return Trade(
+ if (provider == null) continue;
+
+ await Trade(
id: tradeId,
- provider: provider!,
+ provider: provider,
from: from,
to: to,
createdAt: date,
amount: '',
receiveAmount: '',
- );
- });
- await tradeSource.addAll(trades);
+ ).save();
+ }
+
await prefs.setBool('ios_migration_trade_list_completed', true);
} catch (e) {
printV(e.toString());
diff --git a/lib/exchange/provider/chainflip_exchange_provider.dart b/lib/exchange/provider/chainflip_exchange_provider.dart
index 71109225..2d8acf8a 100644
--- a/lib/exchange/provider/chainflip_exchange_provider.dart
+++ b/lib/exchange/provider/chainflip_exchange_provider.dart
@@ -8,15 +8,13 @@ import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
-import 'package:hive/hive.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cake_wallet/utils/exchange_provider_logger.dart';
class ChainflipExchangeProvider extends ExchangeProvider {
- ChainflipExchangeProvider({required this.tradesStore});
+ ChainflipExchangeProvider();
static final List<CryptoCurrency> _supported = [
CryptoCurrency.btc,
@@ -41,8 +39,6 @@ class ChainflipExchangeProvider extends ExchangeProvider {
static const _affiliateBps = secrets.chainflipAffiliateFee;
static const _affiliateKey = secrets.chainflipApiKey;
- final Box<Trade> tradesStore;
-
@override
String get title => 'Chainflip';
@@ -229,19 +225,18 @@ class ChainflipExchangeProvider extends ExchangeProvider {
);
return Trade(
- id: id,
- from: request.fromCurrency,
- to: request.toCurrency,
- provider: description,
- inputAddress: swapResponse['address'].toString(),
- createdAt: DateTime.now(),
- amount: request.fromAmount,
- receiveAmount: request.toAmount,
- state: TradeState.waiting,
- payoutAddress: request.toAddress,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
- isSendAll: isSendAll);
+ id: id,
+ from: request.fromCurrency,
+ to: request.toCurrency,
+ provider: description,
+ inputAddress: swapResponse['address'].toString(),
+ createdAt: DateTime.now(),
+ amount: request.fromAmount,
+ receiveAmount: request.toAmount,
+ state: TradeState.waiting,
+ payoutAddress: request.toAddress,
+ isSendAll: isSendAll,
+ );
} catch (e, s) {
ExchangeProviderLogger.logError(
provider: description,
@@ -296,29 +291,19 @@ class ChainflipExchangeProvider extends ExchangeProvider {
final to = status['destinationAsset'].toString();
final newTrade = Trade(
- id: id,
- from: _toCurrency(status['sourceAsset'].toString()),
- to: _toCurrency(status['destinationAsset'].toString()),
- provider: description,
- amount: depositAmount,
- receiveAmount: amount,
- state: currentState,
- payoutAddress: status['destinationAddress'].toString(),
- outputTransaction: status['swapEgress']?['transactionReference']?.toString(),
- isRefund: isRefund,
- userCurrencyFromRaw: '${from.toUpperCase()}' + '_',
- userCurrencyToRaw: '${to.toUpperCase()}' + '_',
+ id: id,
+ from: _toCurrency(from),
+ to: _toCurrency(to),
+ provider: description,
+ amount: depositAmount,
+ receiveAmount: amount,
+ state: currentState,
+ payoutAddress: status['destinationAddress'].toString(),
+ outputTransaction:
+ status['swapEgress']?['transactionReference']?.toString(),
+ isRefund: isRefund,
);
- // Find trade and update receiveAmount with the real value received
- final storedTrade = _getStoredTrade(id);
-
- if (storedTrade != null) {
- storedTrade.$2.receiveAmount = newTrade.receiveAmount;
- storedTrade.$2.outputTransaction = newTrade.outputTransaction;
- tradesStore.put(storedTrade.$1, storedTrade.$2);
- }
-
return newTrade;
} catch (e) {
printV(e.toString());
@@ -368,17 +353,6 @@ class ChainflipExchangeProvider extends ExchangeProvider {
return currency;
}
- (dynamic, Trade)? _getStoredTrade(String id) {
- for (var i = tradesStore.length -1; i >= 0; i--) {
- Trade? t = tradesStore.getAt(i);
-
- if (t != null && t.id == id)
- return (i, t);
- }
-
- return null;
- }
-
String _amountToNative(double amount, CryptoCurrency currency) =>
(amount * pow(10, currency.decimals)).toInt().toString();
diff --git a/lib/exchange/provider/changenow_exchange_provider.dart b/lib/exchange/provider/changenow_exchange_provider.dart
index 69b906d3..d32a7d27 100644
--- a/lib/exchange/provider/changenow_exchange_provider.dart
+++ b/lib/exchange/provider/changenow_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_not_found_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/utils/distribution_info.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
@@ -248,8 +247,6 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
receiveAmount: toAmount ?? request.toAmount,
state: TradeState.created,
payoutAddress: payoutAddress,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
isSendAll: isSendAll,
);
}
@@ -315,9 +312,6 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
expiredAt: expiredAt,
outputTransaction: outputTransaction,
payoutAddress: payoutAddress,
- userCurrencyFromRaw:
- '${fromCurrency.toUpperCase()}' + '_' + '${fromTag?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_' + '${toTag?.toUpperCase() ?? ''}',
);
}
diff --git a/lib/exchange/provider/exchange_provider.dart b/lib/exchange/provider/exchange_provider.dart
index 513af4c4..55f422a9 100644
--- a/lib/exchange/provider/exchange_provider.dart
+++ b/lib/exchange/provider/exchange_provider.dart
@@ -1,4 +1,3 @@
-import 'package:cake_wallet/exchange/exchange_pair.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/exchange/limits.dart';
import 'package:cake_wallet/exchange/trade.dart';
@@ -31,13 +30,12 @@ abstract class ExchangeProvider {
Future<Trade> findTradeById({required String id});
- Future<double> fetchRate({
- required CryptoCurrency from,
- required CryptoCurrency to,
- required double amount,
- required bool isFixedRateMode,
- required bool isReceiveAmount
- });
+ Future<double> fetchRate(
+ {required CryptoCurrency from,
+ required CryptoCurrency to,
+ required double amount,
+ required bool isFixedRateMode,
+ required bool isReceiveAmount});
Future<bool> checkIsAvailable();
}
diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart
index caa1c334..fe019159 100644
--- a/lib/exchange/provider/exolix_exchange_provider.dart
+++ b/lib/exchange/provider/exolix_exchange_provider.dart
@@ -314,8 +314,6 @@ class ExolixExchangeProvider extends ExchangeProvider {
receiveAmount: receiveAmount ?? request.toAmount,
state: TradeState.created,
payoutAddress: payoutAddress,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
isSendAll: isSendAll,
);
}
@@ -363,18 +361,16 @@ class ExolixExchangeProvider extends ExchangeProvider {
final payoutAddress = responseJSON['withdrawalAddress'] as String;
return Trade(
- id: id,
- from: from,
- to: to,
- provider: description,
- inputAddress: inputAddress,
- amount: amount,
- state: TradeState.deserialize(raw: _prepareStatus(status)),
- extraId: extraId,
- outputTransaction: outputTransaction,
- payoutAddress: payoutAddress,
- userCurrencyFromRaw: '${coinFrom.toUpperCase()}' + '_' + '${fromTag?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${coinTo.toUpperCase()}' + '_' + '${toTag?.toUpperCase() ?? ''}',
+ id: id,
+ from: from,
+ to: to,
+ provider: description,
+ inputAddress: inputAddress,
+ amount: amount,
+ state: TradeState.deserialize(raw: _prepareStatus(status)),
+ extraId: extraId,
+ outputTransaction: outputTransaction,
+ payoutAddress: payoutAddress,
);
}
diff --git a/lib/exchange/provider/jupiter_exchange_provider.dart b/lib/exchange/provider/jupiter_exchange_provider.dart
index ff9b529f..6fc47e97 100644
--- a/lib/exchange/provider/jupiter_exchange_provider.dart
+++ b/lib/exchange/provider/jupiter_exchange_provider.dart
@@ -367,8 +367,6 @@ class JupiterExchangeProvider extends ExchangeProvider {
receiveAmount: receiveAmount,
payoutAddress: request.toAddress,
isSendAll: isSendAll,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? 'SOL'}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? 'SOL'}',
routerData: transaction,
routerValue: requestId,
fee: totalFeeInSol,
diff --git a/lib/exchange/provider/letsexchange_exchange_provider.dart b/lib/exchange/provider/letsexchange_exchange_provider.dart
index d2c9191d..8e5f4970 100644
--- a/lib/exchange/provider/letsexchange_exchange_provider.dart
+++ b/lib/exchange/provider/letsexchange_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
@@ -76,13 +75,12 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
}
@override
- Future<double> fetchRate({
- required CryptoCurrency from,
- required CryptoCurrency to,
- required double amount,
- required bool isFixedRateMode,
- required bool isReceiveAmount
- }) async {
+ Future<double> fetchRate(
+ {required CryptoCurrency from,
+ required CryptoCurrency to,
+ required double amount,
+ required bool isFixedRateMode,
+ required bool isReceiveAmount}) async {
final networkFrom = _getNetworkType(from);
final networkTo = _getNetworkType(to);
try {
@@ -191,14 +189,13 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
'Authorization': apiKey
};
- final uri = Uri.https(_baseUrl,
- isFixedRateMode ? _createTransactionRevertPath : _createTransactionPath);
+ final uri = Uri.https(
+ _baseUrl, isFixedRateMode ? _createTransactionRevertPath : _createTransactionPath);
final response = await ProxyWrapper().post(
clearnetUri: uri,
headers: headers,
body: json.encode(tradeParams),
);
-
if (response.statusCode != 200) {
ExchangeProviderLogger.logError(
@@ -304,8 +301,6 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
createdAt: createdAt,
expiredAt: expiredAt,
extraId: extraId,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
isSendAll: isSendAll,
);
} catch (e, s) {
@@ -342,7 +337,6 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
final url = Uri.https(_baseUrl, '$_getTransactionPath/$id');
final response = await ProxyWrapper().get(clearnetUri: url, headers: headers);
-
if (response.statusCode != 200) {
throw Exception('LetsExchange fetch trade failed: ${response.body}');
@@ -363,7 +357,6 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
final toTag = toCurrency == normalizedToNetwork ? null : normalizedToNetwork;
final to = CryptoCurrency.safeParseCurrencyFromString(toCurrency, tag: toTag);
-
final payoutAddress = responseJSON['withdrawal'] as String;
final depositAddress = responseJSON['deposit'] as String;
final refundAddress = responseJSON['return'] as String;
@@ -371,15 +364,8 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
final receiveAmount = responseJSON['withdrawal_amount'] as String;
final status = responseJSON['status'] as String;
- // We ignore the created_at from response and use DateTime.now() instead
- final createdAtString = responseJSON['created_at'] as String;
- final expiredAtTimestamp = responseJSON['expired_at'] as int;
-
final extraId = responseJSON['deposit_extra_id'] as String?;
- final createdAt = DateTime.parse(createdAtString).toLocal();
- final expiredAt = DateTime.fromMillisecondsSinceEpoch(expiredAtTimestamp * 1000).toLocal();
-
return Trade(
id: id,
from: from,
@@ -393,8 +379,6 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
state: TradeState.deserialize(raw: status),
isRefund: status == 'refund',
extraId: extraId,
- userCurrencyFromRaw: '${fromCurrency.toUpperCase()}' + '_' + '${fromTag?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_' + '${toTag?.toUpperCase() ?? ''}',
);
}
@@ -412,7 +396,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
headers: headers,
body: json.encode(params),
);
-
+
if (response.statusCode != 200) {
throw Exception('LetsExchange fetch info failed: ${response.body}');
}
diff --git a/lib/exchange/provider/near_Intents_exchange_provider.dart b/lib/exchange/provider/near_Intents_exchange_provider.dart
index 0f520624..544bd3f3 100644
--- a/lib/exchange/provider/near_Intents_exchange_provider.dart
+++ b/lib/exchange/provider/near_Intents_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/amount_converter.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
@@ -286,10 +285,6 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
receiveAmount: quoteObj['amountOutFormatted']?.toString(),
memo: depositMemo,
isSendAll: isSendAll,
- userCurrencyFromRaw:
- '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw:
- '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
ExchangeProviderLogger.logSuccess(
@@ -415,8 +410,6 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
txId: originTxHash,
extraId: depositMemo,
isRefund: statusRaw == 'REFUNDED',
- userCurrencyFromRaw: '${from?.$1.toUpperCase()}' + '_' + '${from?.$2?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${to?.$1.toUpperCase()}' + '_' + '${to?.$2?.toUpperCase() ?? ''}',
);
}
diff --git a/lib/exchange/provider/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart
index cd914213..2a49c0bc 100644
--- a/lib/exchange/provider/sideshift_exchange_provider.dart
+++ b/lib/exchange/provider/sideshift_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
import 'package:cake_wallet/exchange/trade_not_found_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
@@ -337,8 +336,6 @@ class SideShiftExchangeProvider extends ExchangeProvider {
createdAt: DateTime.now(),
isSendAll: isSendAll,
extraId: depositMemo,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
}
@@ -377,19 +374,25 @@ class SideShiftExchangeProvider extends ExchangeProvider {
final expiredAt = isVariable ? null : DateTime.tryParse(expiredAtRaw)?.toLocal();
final depositMemo = responseJSON['depositMemo'] as String?;
+ final fromParsed = CryptoCurrency.safeParseCurrencyFromString(
+ fromCurrency,
+ tag: fromNetwork,
+ );
+ final toParsed = CryptoCurrency.safeParseCurrencyFromString(
+ toCurrency,
+ tag: toNetwork,
+ );
return Trade(
- id: id,
- from: CryptoCurrency.safeParseCurrencyFromString(fromCurrency),
- to: CryptoCurrency.safeParseCurrencyFromString(toCurrency),
- provider: description,
- inputAddress: inputAddress,
- amount: expectedSendAmount ?? '',
- state: TradeState.deserialize(raw: status ?? 'created'),
- expiredAt: expiredAt,
- payoutAddress: settleAddress,
- extraId: depositMemo,
- userCurrencyFromRaw: '${fromCurrency.toUpperCase()}' + '_' + _normalizeNetworkType(fromNetwork ?? ''),
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_' + _normalizeNetworkType(toNetwork ?? ''),
+ id: id,
+ from: fromParsed,
+ to: toParsed,
+ provider: description,
+ inputAddress: inputAddress,
+ amount: expectedSendAmount ?? '',
+ state: TradeState.deserialize(raw: status ?? 'created'),
+ expiredAt: expiredAt,
+ payoutAddress: settleAddress,
+ extraId: depositMemo,
);
}
diff --git a/lib/exchange/provider/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart
index 211aeff7..85ee57ca 100644
--- a/lib/exchange/provider/simpleswap_exchange_provider.dart
+++ b/lib/exchange/provider/simpleswap_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
import 'package:cake_wallet/exchange/trade_not_found_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
@@ -290,8 +289,6 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
payoutAddress: payoutAddress,
createdAt: DateTime.now(),
isSendAll: isSendAll,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
}
@@ -326,18 +323,19 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
final status = responseJSON['status'] as String;
final payoutAddress = responseJSON['address_to'] as String;
+ final fromParsed =
+ CryptoCurrency.safeParseCurrencyFromString(fromCurrency);
+ final toParsed = CryptoCurrency.safeParseCurrencyFromString(toCurrency);
return Trade(
id: id,
- from: CryptoCurrency.safeParseCurrencyFromString(fromCurrency),
- to: CryptoCurrency.safeParseCurrencyFromString(toCurrency),
+ from: fromParsed,
+ to: toParsed,
extraId: extraId,
provider: description,
inputAddress: inputAddress,
amount: expectedSendAmount,
state: TradeState.deserialize(raw: status),
payoutAddress: payoutAddress,
- userCurrencyFromRaw: '${fromCurrency.toUpperCase()}' + '_',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_',
);
}
diff --git a/lib/exchange/provider/stealth_ex_exchange_provider.dart b/lib/exchange/provider/stealth_ex_exchange_provider.dart
index d8d8831b..22c4be96 100644
--- a/lib/exchange/provider/stealth_ex_exchange_provider.dart
+++ b/lib/exchange/provider/stealth_ex_exchange_provider.dart
@@ -9,7 +9,6 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/utils/exchange_provider_logger.dart';
@@ -299,8 +298,6 @@ class StealthExExchangeProvider extends ExchangeProvider {
createdAt: createdAt,
expiredAt: expiredAt,
extraId: extraId,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
isSendAll: isSendAll,
);
} catch (e, s) {
@@ -377,9 +374,6 @@ class StealthExExchangeProvider extends ExchangeProvider {
createdAt: createdAt,
isRefund: status == 'refunded',
extraId: extraId,
- userCurrencyFromRaw:
- '${fromCurrency.toUpperCase()}' + '_' + '${fromTag?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_' + '${toTag?.toUpperCase() ?? ''}',
);
}
diff --git a/lib/exchange/provider/swapsxyz_exchange_provider.dart b/lib/exchange/provider/swapsxyz_exchange_provider.dart
index 10e8eb2e..9d74394e 100644
--- a/lib/exchange/provider/swapsxyz_exchange_provider.dart
+++ b/lib/exchange/provider/swapsxyz_exchange_provider.dart
@@ -407,10 +407,6 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
requiresTokenApproval: requiresTokenApproval,
routerData: routerData,
routerValue: txValue,
- userCurrencyFromRaw:
- '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw:
- '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
return trade;
@@ -554,8 +550,6 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
state: state,
createdAt: createdAt,
refundAddress: refundAddress,
- userCurrencyFromRaw: '${fromSymbol.toUpperCase()}' + '_',
- userCurrencyToRaw: '${toSymbol.toUpperCase()}' + '_',
);
}
diff --git a/lib/exchange/provider/swaptrade_exchange_provider.dart b/lib/exchange/provider/swaptrade_exchange_provider.dart
index 99e6883b..91233446 100644
--- a/lib/exchange/provider/swaptrade_exchange_provider.dart
+++ b/lib/exchange/provider/swaptrade_exchange_provider.dart
@@ -297,8 +297,6 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
state: TradeState.created,
payoutAddress: request.toAddress,
isSendAll: isSendAll,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
} catch (e, s) {
ExchangeProviderLogger.logError(
@@ -374,8 +372,6 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
receiveAmount: expectedReceiveAmount,
memo: memo,
createdAt: DateTime.tryParse(createdAt ?? ''),
- userCurrencyFromRaw: '${fromCurrency.toUpperCase()}' + '_',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_',
);
} catch (e) {
printV("error getting trade: ${e.toString()}");
diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart
index c3f09d5b..aacf04b3 100644
--- a/lib/exchange/provider/thorchain_exchange.provider.dart
+++ b/lib/exchange/provider/thorchain_exchange.provider.dart
@@ -6,15 +6,13 @@ import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
-import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
-import 'package:hive/hive.dart';
import 'package:cake_wallet/utils/exchange_provider_logger.dart';
class ThorChainExchangeProvider extends ExchangeProvider {
- ThorChainExchangeProvider({required this.tradesStore});
+ ThorChainExchangeProvider();
static final isRefundAddressSupported = [CryptoCurrency.eth];
@@ -26,8 +24,6 @@ class ThorChainExchangeProvider extends ExchangeProvider {
static const _affiliateBps = '175';
static const _nameLookUpPath = 'v2/thorname/lookup/';
- final Box<Trade> tradesStore;
-
@override
String get title => 'THORChain';
@@ -195,8 +191,6 @@ class ThorChainExchangeProvider extends ExchangeProvider {
payoutAddress: request.toAddress,
memo: memo,
isSendAll: isSendAll,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
}
@@ -254,8 +248,6 @@ class ThorChainExchangeProvider extends ExchangeProvider {
state: currentState,
memo: memo,
isRefund: isRefund,
- userCurrencyFromRaw: '${tx['chain'] as String? ?? ''}' + '_',
- userCurrencyToRaw: '$toAsset' + '_',
);
}
diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart
index 060575d3..99e8b05a 100644
--- a/lib/exchange/provider/trocador_exchange_provider.dart
+++ b/lib/exchange/provider/trocador_exchange_provider.dart
@@ -392,8 +392,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
payoutAddress: payoutAddress,
isSendAll: isSendAll,
extraId: addressProviderMemo,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
);
}
@@ -456,9 +454,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
providerId: providerId,
providerName: providerName,
extraId: addressProviderMemo,
- userCurrencyFromRaw:
- '${fromCurrency.toUpperCase()}' + '_' + '${fromTag?.toUpperCase() ?? ''}',
- userCurrencyToRaw: '${toCurrency.toUpperCase()}' + '_' + '${toTag?.toUpperCase() ?? ''}',
);
});
}
diff --git a/lib/exchange/provider/xoswap_exchange_provider.dart b/lib/exchange/provider/xoswap_exchange_provider.dart
index 22d4ded7..35ede0bf 100644
--- a/lib/exchange/provider/xoswap_exchange_provider.dart
+++ b/lib/exchange/provider/xoswap_exchange_provider.dart
@@ -423,8 +423,6 @@ class XOSwapExchangeProvider extends ExchangeProvider {
receiveAmount: receiveAmount.toString(),
payoutAddress: payoutAddress,
extraId: extraId,
- userCurrencyFromRaw: '${request.fromCurrency.title}_${request.fromCurrency.tag ?? ''}',
- userCurrencyToRaw: '${request.toCurrency.title}_${request.toCurrency.tag ?? ''}',
isSendAll: isSendAll,
);
} catch (e, s) {
@@ -529,14 +527,6 @@ class XOSwapExchangeProvider extends ExchangeProvider {
final createdAt = DateTime.parse(createdAtString).toLocal();
final extraId = responseJSON['payInAddressTag'] as String?;
- final userCurrencyFromRaw = fromCurrency != null
- ? '${fromCurrency.title}' + '_' + '${fromCurrency.tag ?? ''}'
- : '${fromAssetBase}' + '_' + '${fromAssetTag ?? ''}';
-
- final userCurrencyToRaw = toCurrency != null
- ? '${toCurrency.title}' + '_' + '${toCurrency.tag ?? ''}'
- : '${toAssetBase}' + '_' + '${toAssetTag ?? ''}';
-
return Trade(
id: orderId,
from: fromCurrency,
@@ -550,8 +540,6 @@ class XOSwapExchangeProvider extends ExchangeProvider {
receiveAmount: receiveAmount,
payoutAddress: payoutAddress,
extraId: extraId,
- userCurrencyFromRaw: userCurrencyFromRaw,
- userCurrencyToRaw: userCurrencyToRaw,
);
} catch (e) {
printV(e.toString());
diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart
index 2dde57c8..b6052c2f 100644
--- a/lib/exchange/trade.dart
+++ b/lib/exchange/trade.dart
@@ -1,19 +1,22 @@
+import 'dart:async';
+
import 'package:cake_wallet/evm/evm.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/db/sqlite.dart';
import 'package:cw_core/format_amount.dart';
import 'package:cw_core/generate_name.dart';
-import 'package:cw_core/hive_type_ids.dart';
-import 'package:hive/hive.dart';
+import 'package:sqflite/sqflite.dart';
-class Trade extends HiveObject {
+class Trade {
Trade({
+ this.internalId = 0,
required this.id,
required this.amount,
ExchangeProviderDescription? provider,
- CryptoCurrency? from,
- CryptoCurrency? to,
+ this.from,
+ this.to,
TradeState? state,
this.receiveAmount,
this.createdAt,
@@ -34,8 +37,6 @@ class Trade extends HiveObject {
this.isRefund,
this.isSendAll,
this.router,
- this.userCurrencyFromRaw,
- this.userCurrencyToRaw,
// The following fields are used for SwapXyz trades only
this.needToRegisterInSwapXyz,
this.sourceTokenAddress,
@@ -48,364 +49,271 @@ class Trade extends HiveObject {
this.chainId,
}) {
if (provider != null) providerRaw = provider.raw;
-
- fromRaw = from?.raw ?? -1;
- toRaw = to?.raw ?? -1;
-
if (state != null) stateRaw = state.raw;
}
- static const typeId = TRADE_TYPE_ID;
+ static const tableName = 'Trade';
+ static const selfIdColumn = 'tradeId';
+
static const boxName = 'Trades';
static const boxKey = 'tradesBoxKey';
- @HiveField(0, defaultValue: '')
+ static final StreamController<void> onChanged = StreamController<void>.broadcast();
+
+ int internalId;
+
String id;
- @HiveField(1, defaultValue: 0)
- late int providerRaw;
+ int providerRaw = 0;
ExchangeProviderDescription get provider =>
ExchangeProviderDescription.deserialize(raw: providerRaw);
- @HiveField(2, defaultValue: -1)
- int fromRaw = -1;
-
- CryptoCurrency? get from => CryptoCurrency.safeDeserialize(raw: fromRaw);
-
- @HiveField(3, defaultValue: -1)
- int toRaw = -1;
+ CryptoCurrency? from;
+ CryptoCurrency? to;
- CryptoCurrency? get to => CryptoCurrency.safeDeserialize(raw: toRaw);
-
- @HiveField(4, defaultValue: '')
- late String stateRaw;
+ String stateRaw = '';
TradeState get state => TradeState.deserialize(raw: stateRaw);
- @HiveField(5)
DateTime? createdAt;
-
- @HiveField(6)
DateTime? expiredAt;
-
- @HiveField(7, defaultValue: '')
String amount;
-
- @HiveField(8)
+ String? receiveAmount;
String? inputAddress;
-
- @HiveField(9)
String? extraId;
-
- @HiveField(10)
String? outputTransaction;
-
- @HiveField(11)
String? refundAddress;
-
- @HiveField(12)
String? walletId;
-
- @HiveField(13)
String? payoutAddress;
-
- @HiveField(14)
String? password;
-
- @HiveField(15)
String? providerId;
-
- @HiveField(16)
String? providerName;
-
- @HiveField(17)
String? fromWalletAddress;
-
- @HiveField(18)
String? memo;
-
- @HiveField(19)
String? txId;
-
- @HiveField(20)
bool? isRefund;
-
- @HiveField(21)
bool? isSendAll;
-
- /// Must be set on createTrade;
-
- @HiveField(22)
String? router;
- @HiveField(23, defaultValue: '')
- String? receiveAmount;
-
- @HiveField(24, defaultValue: '')
- String? userCurrencyFromRaw;
-
- @HiveField(25, defaultValue: '')
- String? userCurrencyToRaw;
-
// The following fields are used for SwapXyz trades only
- @HiveField(26)
bool? needToRegisterInSwapXyz;
-
- @HiveField(27)
String? sourceTokenAddress;
-
- @HiveField(28)
int? sourceTokenDecimals;
-
- @HiveField(29)
String? routerData;
-
- @HiveField(30)
String? routerValue;
-
- @HiveField(31)
int? routerChainId;
-
- @HiveField(32)
String? sourceTokenAmountRaw;
-
- @HiveField(33, defaultValue: false)
bool? requiresTokenApproval;
- @HiveField(34)
int? chainId;
-
- @HiveField(35)
double? fee;
- CryptoCurrency? get userCurrencyFrom {
- if (userCurrencyFromRaw == null || userCurrencyFromRaw!.isEmpty) {
- return null;
- }
- final underscoreIndex = userCurrencyFromRaw!.indexOf('_');
- final title = userCurrencyFromRaw!.substring(0, underscoreIndex);
- String tag = userCurrencyFromRaw!.substring(underscoreIndex + 1);
-
- if (tag.contains('ARB')) tag = 'ARB';
+ String get chainName {
+ if (chainId == null) return '';
- return CryptoCurrency(
- title: title,
- tag: tag.isNotEmpty ? tag : null,
- name: '',
- raw: -1,
- decimals: 1,
- );
+ return evm!.getChainNameByChainId(chainId!).capitalized();
}
- CryptoCurrency? get userCurrencyTo {
- if (userCurrencyToRaw == null || userCurrencyToRaw!.isEmpty) {
- return null;
- }
- final underscoreIndex = userCurrencyToRaw!.indexOf('_');
- final title = userCurrencyToRaw!.substring(0, underscoreIndex);
- final tag = userCurrencyToRaw!.substring(underscoreIndex + 1);
+ // ── SQLite CRUD ──────────────────────────────────────
- return CryptoCurrency(
- title: title,
- tag: tag.isNotEmpty ? tag : null,
- name: '',
- raw: -1,
- decimals: 1,
+ Future<int> save() async {
+ final json = toSqliteMap();
+ if (json[selfIdColumn] == 0) {
+ json[selfIdColumn] = null;
+ }
+ internalId = await db!.insert(
+ tableName,
+ json,
+ conflictAlgorithm: ConflictAlgorithm.replace,
);
+ onChanged.add(null);
+ return internalId;
}
- String get chainName {
- if (chainId == null) return '';
+ static Future<List<Trade>> getAll({String? orderBy}) async {
+ final list = await db!.query(
+ tableName,
+ orderBy: orderBy ?? 'createdAt DESC',
+ );
+ return List.generate(
+ list.length,
+ (i) => Trade.fromSqliteRow(list[i]),
+ );
+ }
- return evm!.getChainNameByChainId(chainId!).capitalized();
+ static Future<Trade?> getByTradeId(String id) async {
+ final list = await db!.query(
+ tableName,
+ where: 'id = ?',
+ whereArgs: [id],
+ limit: 1,
+ );
+ if (list.isEmpty) return null;
+ return Trade.fromSqliteRow(list.first);
}
- static Trade fromMap(Map<String, Object?> map) {
- return Trade(
- id: map['id'] as String,
- provider: ExchangeProviderDescription.deserialize(raw: map['provider'] as int),
- from: CryptoCurrency.deserialize(raw: map['input'] as int),
- to: CryptoCurrency.deserialize(raw: map['output'] as int),
- createdAt:
- map['date'] != null ? DateTime.fromMillisecondsSinceEpoch(map['date'] as int) : null,
- amount: map['amount'] as String,
- receiveAmount: map['receive_amount'] as String?,
- walletId: map['wallet_id'] as String,
- fromWalletAddress: map['from_wallet_address'] as String?,
- memo: map['memo'] as String?,
- txId: map['tx_id'] as String?,
- isRefund: map['isRefund'] as bool?,
- isSendAll: map['isSendAll'] as bool?,
- router: map['router'] as String?,
- extraId: map['extra_id'] as String?,
- chainId: map['chain_id'] as int?,
+ static Future<int> deleteTrade(Trade trade) async {
+ final rows = await db!.delete(
+ tableName,
+ where: '$selfIdColumn = ?',
+ whereArgs: [trade.internalId],
);
+ onChanged.add(null);
+ return rows;
+ }
+
+ // ── SQLite serialization ─────────────────────────────
+ void mergeFindTradeByIdResult(Trade updated) {
+ if (updated.stateRaw.isNotEmpty) stateRaw = updated.stateRaw;
+ if (createdAt == null && updated.createdAt != null) {
+ createdAt = updated.createdAt;
+ }
+ if (updated.expiredAt != null) expiredAt = updated.expiredAt;
+ if (updated.isRefund != null) isRefund = updated.isRefund;
+
+ if (updated.receiveAmount != null) receiveAmount = updated.receiveAmount;
+ if (updated.inputAddress != null) inputAddress = updated.inputAddress;
+ if (updated.extraId != null) extraId = updated.extraId;
+ if (updated.outputTransaction != null) {
+ outputTransaction = updated.outputTransaction;
+ }
+ if (updated.refundAddress != null) refundAddress = updated.refundAddress;
+ if (updated.payoutAddress != null) payoutAddress = updated.payoutAddress;
+ if (updated.password != null) password = updated.password;
+ if (updated.providerId != null) providerId = updated.providerId;
+ if (updated.providerName != null) providerName = updated.providerName;
+ if (updated.memo != null) memo = updated.memo;
+ if (updated.txId != null) txId = updated.txId;
}
- Map<String, dynamic> toMap() {
+ Map<String, dynamic> toSqliteMap() {
return <String, dynamic>{
+ selfIdColumn: internalId,
'id': id,
- 'provider': provider.serialize(),
- 'input': fromRaw,
- 'output': toRaw,
- 'date': createdAt != null ? createdAt!.millisecondsSinceEpoch : null,
+ 'providerRaw': providerRaw,
+ 'fromTitle': from?.title,
+ 'fromName': from?.name,
+ 'fromTag': from?.tag,
+ 'fromFullName': from?.fullName,
+ 'fromDecimals': from?.decimals,
+ 'fromRaw': from?.raw,
+ 'fromIconPath': from?.iconPath,
+ 'fromFlatIconPath': from?.flatIconPath,
+ 'fromChainIconPath': from?.chainIconPath,
+ 'toTitle': to?.title,
+ 'toName': to?.name,
+ 'toTag': to?.tag,
+ 'toFullName': to?.fullName,
+ 'toDecimals': to?.decimals,
+ 'toRaw': to?.raw,
+ 'toIconPath': to?.iconPath,
+ 'toFlatIconPath': to?.flatIconPath,
+ 'toChainIconPath': to?.chainIconPath,
+ 'stateRaw': stateRaw,
+ 'createdAt': createdAt?.millisecondsSinceEpoch,
+ 'expiredAt': expiredAt?.millisecondsSinceEpoch,
'amount': amount,
- 'receive_amount': receiveAmount,
- 'wallet_id': walletId,
- 'from_wallet_address': fromWalletAddress,
+ 'receiveAmount': receiveAmount,
+ 'inputAddress': inputAddress,
+ 'extraId': extraId,
+ 'outputTransaction': outputTransaction,
+ 'refundAddress': refundAddress,
+ 'walletId': walletId,
+ 'payoutAddress': payoutAddress,
+ 'password': password,
+ 'providerId': providerId,
+ 'providerName': providerName,
+ 'fromWalletAddress': fromWalletAddress,
'memo': memo,
- 'tx_id': txId,
- 'isRefund': isRefund,
- 'isSendAll': isSendAll,
+ 'txId': txId,
+ 'isRefund': isRefund == true ? 1 : 0,
+ 'isSendAll': isSendAll == true ? 1 : 0,
'router': router,
- 'extra_id': extraId,
- 'chain_id': chainId,
+ 'needToRegisterInSwapXyz': needToRegisterInSwapXyz == true ? 1 : 0,
+ 'sourceTokenAddress': sourceTokenAddress,
+ 'sourceTokenDecimals': sourceTokenDecimals,
+ 'routerData': routerData,
+ 'routerValue': routerValue,
+ 'routerChainId': routerChainId,
+ 'sourceTokenAmountRaw': sourceTokenAmountRaw,
+ 'requiresTokenApproval': requiresTokenApproval == true ? 1 : 0,
+ 'chainId': chainId,
'fee': fee,
};
}
- String amountFormatted() => formatAmount(amount);
- String receiveAmountFormatted() => formatAmount(receiveAmount ?? '');
-}
+ factory Trade.fromSqliteRow(Map<String, dynamic> row) {
+ final trade = Trade(
+ id: row['id'] as String? ?? '',
+ amount: row['amount'] as String? ?? '',
+ receiveAmount: row['receiveAmount'] as String?,
+ createdAt: row['createdAt'] != null
+ ? DateTime.fromMillisecondsSinceEpoch(
+ row['createdAt'] as int,
+ )
+ : null,
+ expiredAt: row['expiredAt'] != null
+ ? DateTime.fromMillisecondsSinceEpoch(
+ row['expiredAt'] as int,
+ )
+ : null,
+ inputAddress: row['inputAddress'] as String?,
+ extraId: row['extraId'] as String?,
+ outputTransaction: row['outputTransaction'] as String?,
+ refundAddress: row['refundAddress'] as String?,
+ walletId: row['walletId'] as String?,
+ payoutAddress: row['payoutAddress'] as String?,
+ password: row['password'] as String?,
+ providerId: row['providerId'] as String?,
+ providerName: row['providerName'] as String?,
+ fromWalletAddress: row['fromWalletAddress'] as String?,
+ memo: row['memo'] as String?,
+ fee: row['fee'] as double?,
+ txId: row['txId'] as String?,
+ isRefund: (row['isRefund'] as int?) == 1,
+ isSendAll: (row['isSendAll'] as int?) == 1,
+ router: row['router'] as String?,
+ from: _currencyFromRow(row, 'from'),
+ to: _currencyFromRow(row, 'to'),
+ needToRegisterInSwapXyz: (row['needToRegisterInSwapXyz'] as int?) == 1,
+ sourceTokenAddress: row['sourceTokenAddress'] as String?,
+ sourceTokenDecimals: row['sourceTokenDecimals'] as int?,
+ routerData: row['routerData'] as String?,
+ routerValue: row['routerValue'] as String?,
+ routerChainId: row['routerChainId'] as int?,
+ sourceTokenAmountRaw: row['sourceTokenAmountRaw'] as String?,
+ requiresTokenApproval: (row['requiresTokenApproval'] as int?) == 1,
+ chainId: row['chainId'] as int?,
+ );
+ trade.internalId = row[selfIdColumn] as int? ?? 0;
+ trade.providerRaw = row['providerRaw'] as int? ?? 0;
+ trade.stateRaw = row['stateRaw'] as String? ?? '';
+ return trade;
+ }
-class TradeAdapter extends TypeAdapter<Trade> {
- @override
- final int typeId = Trade.typeId;
+ static CryptoCurrency? _currencyFromRow(Map<String, dynamic> row, String prefix) {
+ final title = row['${prefix}Title'] as String?;
+ if (title == null || title.isEmpty) return null;
- @override
- Trade read(BinaryReader reader) {
- final numOfFields = reader.readByte();
- final fields = <int, dynamic>{};
- for (int i = 0; i < numOfFields; i++) {
- try {
- fields[reader.readByte()] = reader.read();
- } catch (_) {}
- }
+ final tag = row['${prefix}Tag'] as String?;
- return Trade(
- id: fields[0] == null ? '' : fields[0] as String,
- amount: fields[7] == null ? '' : fields[7] as String,
- receiveAmount: fields[23] as String?,
- createdAt: fields[5] as DateTime?,
- expiredAt: fields[6] as DateTime?,
- inputAddress: fields[8] as String?,
- extraId: fields[9] as String?,
- outputTransaction: fields[10] as String?,
- refundAddress: fields[11] as String?,
- walletId: fields[12] as String?,
- payoutAddress: fields[13] as String?,
- password: fields[14] as String?,
- providerId: fields[15] as String?,
- providerName: fields[16] as String?,
- fromWalletAddress: fields[17] as String?,
- memo: fields[18] as String?,
- txId: fields[19] as String?,
- isRefund: fields[20] as bool?,
- isSendAll: fields[21] as bool?,
- router: fields[22] as String?,
- userCurrencyFromRaw: fields[24] as String?,
- userCurrencyToRaw: fields[25] as String?,
- needToRegisterInSwapXyz: fields[26] as bool?,
- sourceTokenAddress: fields[27] as String?,
- sourceTokenDecimals: fields[28] as int?,
- routerData: fields[29] as String?,
- routerValue: fields[30] as String?,
- routerChainId: fields[31] as int?,
- sourceTokenAmountRaw: fields[32] as String?,
- requiresTokenApproval: fields[33] as bool?,
- chainId: fields[34] as int?,
- fee: fields[35] as double?,
- )
- ..providerRaw = fields[1] == null ? 0 : fields[1] as int
- ..fromRaw = (fields[2] as int?) ?? -1
- ..toRaw = (fields[3] as int?) ?? -1
- ..stateRaw = fields[4] == null ? '' : fields[4] as String;
- }
+ final live = CryptoCurrency.safeParseCurrencyFromString(title, tag: tag);
+ if (live != null) return live;
- @override
- void write(BinaryWriter writer, Trade obj) {
- writer
- ..writeByte(26)
- ..writeByte(0)
- ..write(obj.id)
- ..writeByte(1)
- ..write(obj.providerRaw)
- ..writeByte(2)
- ..write(obj.fromRaw)
- ..writeByte(3)
- ..write(obj.toRaw)
- ..writeByte(4)
- ..write(obj.stateRaw)
- ..writeByte(5)
- ..write(obj.createdAt)
- ..writeByte(6)
- ..write(obj.expiredAt)
- ..writeByte(7)
- ..write(obj.amount)
- ..writeByte(8)
- ..write(obj.inputAddress)
- ..writeByte(9)
- ..write(obj.extraId)
- ..writeByte(10)
- ..write(obj.outputTransaction)
- ..writeByte(11)
- ..write(obj.refundAddress)
- ..writeByte(12)
- ..write(obj.walletId)
- ..writeByte(13)
- ..write(obj.payoutAddress)
- ..writeByte(14)
- ..write(obj.password)
- ..writeByte(15)
- ..write(obj.providerId)
- ..writeByte(16)
- ..write(obj.providerName)
- ..writeByte(17)
- ..write(obj.fromWalletAddress)
- ..writeByte(18)
- ..write(obj.memo)
- ..writeByte(19)
- ..write(obj.txId)
- ..writeByte(20)
- ..write(obj.isRefund)
- ..writeByte(21)
- ..write(obj.isSendAll)
- ..writeByte(22)
- ..write(obj.router)
- ..writeByte(23)
- ..write(obj.receiveAmount)
- ..writeByte(24)
- ..write(obj.userCurrencyFromRaw)
- ..writeByte(25)
- ..write(obj.userCurrencyToRaw)
- ..writeByte(26)
- ..write(obj.needToRegisterInSwapXyz)
- ..writeByte(27)
- ..write(obj.sourceTokenAddress)
- ..writeByte(28)
- ..write(obj.sourceTokenDecimals)
- ..writeByte(29)
- ..write(obj.routerData)
- ..writeByte(30)
- ..write(obj.routerValue)
- ..writeByte(31)
- ..write(obj.routerChainId)
- ..writeByte(32)
- ..write(obj.sourceTokenAmountRaw)
- ..writeByte(33)
- ..write(obj.requiresTokenApproval)
- ..writeByte(34)
- ..write(obj.chainId)
- ..writeByte(35)
- ..write(obj.fee);
+ return CryptoCurrency(
+ title: title,
+ name: row['${prefix}Name'] as String? ?? '',
+ tag: tag,
+ fullName: row['${prefix}FullName'] as String?,
+ decimals: row['${prefix}Decimals'] as int? ?? 1,
+ raw: row['${prefix}Raw'] as int? ?? -1,
+ iconPath: row['${prefix}IconPath'] as String?,
+ flatIconPath: row['${prefix}FlatIconPath'] as String?,
+ chainIconPath: row['${prefix}ChainIconPath'] as String?,
+ );
}
- @override
- int get hashCode => typeId.hashCode;
-
- @override
- bool operator ==(Object other) =>
- identical(this, other) ||
- other is TradeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
+ String amountFormatted() => formatAmount(amount);
+ String receiveAmountFormatted() => formatAmount(receiveAmount ?? '');
}
diff --git a/lib/exchange/trade_currency_snapshot.dart b/lib/exchange/trade_currency_snapshot.dart
new file mode 100644
index 00000000..a9dea6a9
--- /dev/null
+++ b/lib/exchange/trade_currency_snapshot.dart
@@ -0,0 +1,45 @@
+import 'package:cw_core/crypto_currency.dart';
+
+class TradeCurrencySnapshot {
+ TradeCurrencySnapshot._();
+
+ static CryptoCurrency? fromLegacyHive({
+ required int raw,
+ String? displayTitleTag,
+ }) {
+ if (raw >= 0) {
+ final curr = CryptoCurrency.safeDeserialize(raw: raw);
+ if (curr != null) return curr;
+ }
+
+ return _parseLegacyTitleTag(displayTitleTag);
+ }
+
+ static CryptoCurrency? _parseLegacyTitleTag(String? titleTag) {
+ if (titleTag == null || titleTag.isEmpty) return null;
+
+ final idx = titleTag.indexOf('_');
+ if (idx < 0) {
+ return CryptoCurrency(
+ title: titleTag,
+ name: '',
+ raw: -1,
+ decimals: 1,
+ );
+ }
+
+ final title = titleTag.substring(0, idx);
+
+ var tag = titleTag.substring(idx + 1);
+
+ if (tag.contains('ARB')) tag = 'ARB';
+
+ return CryptoCurrency(
+ title: title,
+ tag: tag.isNotEmpty ? tag : null,
+ name: '',
+ raw: -1,
+ decimals: 1,
+ );
+ }
+}
diff --git a/lib/exchange/trade_legacy.dart b/lib/exchange/trade_legacy.dart
new file mode 100644
index 00000000..ea562024
--- /dev/null
+++ b/lib/exchange/trade_legacy.dart
@@ -0,0 +1,168 @@
+import 'package:cake_wallet/core/secure_storage.dart';
+import 'package:cake_wallet/entities/get_encryption_key.dart';
+import 'package:cake_wallet/exchange/exchange_provider_description.dart';
+import 'package:cake_wallet/exchange/trade.dart';
+import 'package:cake_wallet/exchange/trade_currency_snapshot.dart';
+import 'package:cake_wallet/exchange/trade_state.dart';
+import 'package:cw_core/cake_hive.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/hive_type_ids.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+import 'package:hive/hive.dart';
+
+part 'trade_legacy.part.dart';
+
+Future<void> performTradeHiveMigration(SecureStorage secureStorage) async {
+ try {
+ if (!CakeHive.isAdapterRegistered(TradeLegacy.typeId)) {
+ CakeHive.registerAdapter(TradeLegacyAdapter());
+ }
+ final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
+ final box = await CakeHive.openBox<TradeLegacy>(Trade.boxName, encryptionKey: tradesBoxKey);
+ await TradeLegacy.migrateAllToSqlite(box);
+ } catch (e) {
+ printV('Trade Hive migration error: $e');
+ }
+}
+
+class TradeLegacy extends HiveObject {
+ TradeLegacy({
+ required this.id,
+ required this.amount,
+ ExchangeProviderDescription? provider,
+ CryptoCurrency? from,
+ CryptoCurrency? to,
+ TradeState? state,
+ this.receiveAmount,
+ this.createdAt,
+ this.expiredAt,
+ this.inputAddress,
+ this.extraId,
+ this.outputTransaction,
+ this.refundAddress,
+ this.walletId,
+ this.payoutAddress,
+ this.password,
+ this.providerId,
+ this.providerName,
+ this.fromWalletAddress,
+ this.memo,
+ this.fee,
+ this.txId,
+ this.isRefund,
+ this.isSendAll,
+ this.router,
+ this.userCurrencyFromRaw,
+ this.userCurrencyToRaw,
+ this.needToRegisterInSwapXyz,
+ this.sourceTokenAddress,
+ this.sourceTokenDecimals,
+ this.routerData,
+ this.routerValue,
+ this.routerChainId,
+ this.sourceTokenAmountRaw,
+ this.requiresTokenApproval,
+ this.chainId,
+ }) {
+ if (provider != null) providerRaw = provider.raw;
+ fromRaw = from?.raw ?? -1;
+ toRaw = to?.raw ?? -1;
+ if (state != null) stateRaw = state.raw;
+ }
+
+ static const typeId = TRADE_TYPE_ID;
+
+ String id;
+ late int providerRaw;
+ int fromRaw = -1;
+ int toRaw = -1;
+ late String stateRaw;
+ DateTime? createdAt;
+ DateTime? expiredAt;
+ String amount;
+ String? receiveAmount;
+ String? inputAddress;
+ String? extraId;
+ String? outputTransaction;
+ String? refundAddress;
+ String? walletId;
+ String? payoutAddress;
+ String? password;
+ String? providerId;
+ String? providerName;
+ String? fromWalletAddress;
+ String? memo;
+ String? txId;
+ bool? isRefund;
+ bool? isSendAll;
+ String? router;
+ String? userCurrencyFromRaw;
+ String? userCurrencyToRaw;
+ bool? needToRegisterInSwapXyz;
+ String? sourceTokenAddress;
+ int? sourceTokenDecimals;
+ String? routerData;
+ String? routerValue;
+ int? routerChainId;
+ String? sourceTokenAmountRaw;
+ bool? requiresTokenApproval;
+ int? chainId;
+ double? fee;
+
+ Future<void> migrateToSqlite() async {
+ final trade = Trade(
+ id: id,
+ amount: amount,
+ receiveAmount: receiveAmount,
+ createdAt: createdAt,
+ expiredAt: expiredAt,
+ inputAddress: inputAddress,
+ extraId: extraId,
+ outputTransaction: outputTransaction,
+ refundAddress: refundAddress,
+ walletId: walletId,
+ payoutAddress: payoutAddress,
+ password: password,
+ providerId: providerId,
+ providerName: providerName,
+ fromWalletAddress: fromWalletAddress,
+ memo: memo,
+ fee: fee,
+ txId: txId,
+ isRefund: isRefund,
+ isSendAll: isSendAll,
+ router: router,
+ from:
+ TradeCurrencySnapshot.fromLegacyHive(raw: fromRaw, displayTitleTag: userCurrencyFromRaw),
+ to: TradeCurrencySnapshot.fromLegacyHive(raw: toRaw, displayTitleTag: userCurrencyToRaw),
+ needToRegisterInSwapXyz: needToRegisterInSwapXyz,
+ sourceTokenAddress: sourceTokenAddress,
+ sourceTokenDecimals: sourceTokenDecimals,
+ routerData: routerData,
+ routerValue: routerValue,
+ routerChainId: routerChainId,
+ sourceTokenAmountRaw: sourceTokenAmountRaw,
+ requiresTokenApproval: requiresTokenApproval,
+ chainId: chainId,
+ );
+ trade.providerRaw = providerRaw;
+ trade.stateRaw = stateRaw;
+ await trade.save();
+ }
+
+ static Future<void> migrateAllToSqlite(
+ Box<TradeLegacy> box,
+ ) async {
+ printV('Migrating Trades to SQLite: start');
+ final list = box.values.toList();
+ for (final trade in list) {
+ try {
+ await trade.migrateToSqlite();
+ await trade.delete();
+ } catch (e) {
+ printV('Error migrating trade ${trade.id}: $e');
+ }
+ }
+ printV('Migrating Trades to SQLite: end');
+ }
+}
diff --git a/lib/exchange/trade_legacy.part.dart b/lib/exchange/trade_legacy.part.dart
new file mode 100644
index 00000000..8bb952b3
--- /dev/null
+++ b/lib/exchange/trade_legacy.part.dart
@@ -0,0 +1,146 @@
+part of 'trade_legacy.dart';
+
+class TradeLegacyAdapter extends TypeAdapter<TradeLegacy> {
+ @override
+ final int typeId = TradeLegacy.typeId;
+
+ @override
+ TradeLegacy read(BinaryReader reader) {
+ final numOfFields = reader.readByte();
+ final fields = <int, dynamic>{};
+ for (int i = 0; i < numOfFields; i++) {
+ try {
+ fields[reader.readByte()] = reader.read();
+ } catch (_) {}
+ }
+
+ return TradeLegacy(
+ id: fields[0] == null ? '' : fields[0] as String,
+ amount: fields[7] == null ? '' : fields[7] as String,
+ receiveAmount: fields[23] as String?,
+ createdAt: fields[5] as DateTime?,
+ expiredAt: fields[6] as DateTime?,
+ inputAddress: fields[8] as String?,
+ extraId: fields[9] as String?,
+ outputTransaction: fields[10] as String?,
+ refundAddress: fields[11] as String?,
+ walletId: fields[12] as String?,
+ payoutAddress: fields[13] as String?,
+ password: fields[14] as String?,
+ providerId: fields[15] as String?,
+ providerName: fields[16] as String?,
+ fromWalletAddress: fields[17] as String?,
+ memo: fields[18] as String?,
+ txId: fields[19] as String?,
+ isRefund: fields[20] as bool?,
+ isSendAll: fields[21] as bool?,
+ router: fields[22] as String?,
+ userCurrencyFromRaw: fields[24] as String?,
+ userCurrencyToRaw: fields[25] as String?,
+ needToRegisterInSwapXyz: fields[26] as bool?,
+ sourceTokenAddress: fields[27] as String?,
+ sourceTokenDecimals: fields[28] as int?,
+ routerData: fields[29] as String?,
+ routerValue: fields[30] as String?,
+ routerChainId: fields[31] as int?,
+ sourceTokenAmountRaw: fields[32] as String?,
+ requiresTokenApproval: fields[33] as bool?,
+ chainId: fields[34] as int?,
+ fee: fields[35] as double?,
+ )
+ ..providerRaw =
+ fields[1] == null ? 0 : fields[1] as int
+ ..fromRaw = (fields[2] as int?) ?? -1
+ ..toRaw = (fields[3] as int?) ?? -1
+ ..stateRaw =
+ fields[4] == null ? '' : fields[4] as String;
+ }
+
+ @override
+ void write(BinaryWriter writer, TradeLegacy obj) {
+ writer
+ ..writeByte(36)
+ ..writeByte(0)
+ ..write(obj.id)
+ ..writeByte(1)
+ ..write(obj.providerRaw)
+ ..writeByte(2)
+ ..write(obj.fromRaw)
+ ..writeByte(3)
+ ..write(obj.toRaw)
+ ..writeByte(4)
+ ..write(obj.stateRaw)
+ ..writeByte(5)
+ ..write(obj.createdAt)
+ ..writeByte(6)
+ ..write(obj.expiredAt)
+ ..writeByte(7)
+ ..write(obj.amount)
+ ..writeByte(8)
+ ..write(obj.inputAddress)
+ ..writeByte(9)
+ ..write(obj.extraId)
+ ..writeByte(10)
+ ..write(obj.outputTransaction)
+ ..writeByte(11)
+ ..write(obj.refundAddress)
+ ..writeByte(12)
+ ..write(obj.walletId)
+ ..writeByte(13)
+ ..write(obj.payoutAddress)
+ ..writeByte(14)
+ ..write(obj.password)
+ ..writeByte(15)
+ ..write(obj.providerId)
+ ..writeByte(16)
+ ..write(obj.providerName)
+ ..writeByte(17)
+ ..write(obj.fromWalletAddress)
+ ..writeByte(18)
+ ..write(obj.memo)
+ ..writeByte(19)
+ ..write(obj.txId)
+ ..writeByte(20)
+ ..write(obj.isRefund)
+ ..writeByte(21)
+ ..write(obj.isSendAll)
+ ..writeByte(22)
+ ..write(obj.router)
+ ..writeByte(23)
+ ..write(obj.receiveAmount)
+ ..writeByte(24)
+ ..write(obj.userCurrencyFromRaw)
+ ..writeByte(25)
+ ..write(obj.userCurrencyToRaw)
+ ..writeByte(26)
+ ..write(obj.needToRegisterInSwapXyz)
+ ..writeByte(27)
+ ..write(obj.sourceTokenAddress)
+ ..writeByte(28)
+ ..write(obj.sourceTokenDecimals)
+ ..writeByte(29)
+ ..write(obj.routerData)
+ ..writeByte(30)
+ ..write(obj.routerValue)
+ ..writeByte(31)
+ ..write(obj.routerChainId)
+ ..writeByte(32)
+ ..write(obj.sourceTokenAmountRaw)
+ ..writeByte(33)
+ ..write(obj.requiresTokenApproval)
+ ..writeByte(34)
+ ..write(obj.chainId)
+ ..writeByte(35)
+ ..write(obj.fee);
+ }
+
+ @override
+ int get hashCode => typeId.hashCode;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is TradeLegacyAdapter &&
+ runtimeType == other.runtimeType &&
+ typeId == other.typeId;
+}
diff --git a/lib/main.dart b/lib/main.dart
index a50f70e4..61dea0d6 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -19,7 +19,7 @@ import 'package:cake_wallet/entities/language_service.dart';
import 'package:cake_wallet/entities/template.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/exchange/exchange_template.dart';
-import 'package:cake_wallet/exchange/trade.dart';
+import 'package:cake_wallet/exchange/trade_legacy.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/locales/locale.dart';
import 'package:cake_wallet/order/order.dart';
@@ -37,7 +37,6 @@ import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/link_view_model.dart';
-import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/zcash/zcash.dart';
import 'package:cw_core/address_info.dart';
import 'package:cw_core/cake_hive.dart';
@@ -65,7 +64,6 @@ import 'package:flutter/services.dart';
import 'package:flutter_daemon/flutter_daemon.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:hive/hive.dart';
-import 'package:cw_core/root_dir.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -230,10 +228,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
CakeHive.registerAdapter(TransactionDescriptionAdapter());
}
- if (!CakeHive.isAdapterRegistered(Trade.typeId)) {
- CakeHive.registerAdapter(TradeAdapter());
- }
-
if (!CakeHive.isAdapterRegistered(AddressInfo.typeId)) {
CakeHive.registerAdapter(AddressInfoAdapter());
}
@@ -290,7 +284,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
final secureStorage = secureStorageShared;
final transactionDescriptionsBoxKey =
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
- final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
final contacts = await CakeHive.openBox<Contact>(Contact.boxName);
final nodes = await CakeHive.openBox<Node>(Node.boxName);
@@ -299,7 +292,8 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
final transactionDescriptions = await CakeHive.openBox<TransactionDescription>(
TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
- final trades = await CakeHive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
+ await performTradeHiveMigration(secureStorage);
+
final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
final templates = await CakeHive.openBox<Template>(Template.boxName);
final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
@@ -318,7 +312,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
nodes: nodes,
powNodes: powNodes,
contactSource: contacts,
- tradesSource: trades,
ordersSource: orders,
unspentCoinsInfoSource: unspentCoinsInfoSource,
// fiatConvertationService: fiatConvertationService,
@@ -339,7 +332,6 @@ Future<void> initialSetup({
required Box<Node> nodes,
required Box<Node> powNodes,
required Box<Contact> contactSource,
- required Box<Trade> tradesSource,
required Box<Order> ordersSource,
// required FiatConvertationService fiatConvertationService,
required Box<Template> templates,
@@ -354,19 +346,18 @@ Future<void> initialSetup({
}) async {
LanguageService.loadLocaleList();
await defaultSettingsMigration(
- secureStorage: secureStorage,
- version: initialMigrationVersion,
- sharedPreferences: sharedPreferences,
- contactSource: contactSource,
- tradeSource: tradesSource,
- nodes: nodes,
- powNodes: powNodes,
- havenSeedStore: havenSeedStore);
+ secureStorage: secureStorage,
+ version: initialMigrationVersion,
+ sharedPreferences: sharedPreferences,
+ contactSource: contactSource,
+ nodes: nodes,
+ powNodes: powNodes,
+ havenSeedStore: havenSeedStore,
+ );
await setup(
nodeSource: nodes,
powNodeSource: powNodes,
contactSource: contactSource,
- tradesSource: tradesSource,
ordersSource: ordersSource,
templates: templates,
exchangeTemplates: exchangeTemplates,
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
index 497373d3..32d99020 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
@@ -35,13 +35,15 @@ class HistorySection extends StatelessWidget {
? SliverPadding(
padding: EdgeInsets.only(top: 24),
sliver: SliverToBoxAdapter(
- child: (dashboardViewModel.status is SyncingSyncStatus) ? SizedBox.shrink() : Center(
- child: Text(S.of(context).transactions_will_appear_here,
- style: TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.w400,
- color: Theme.of(context).colorScheme.onSurfaceVariant)),
- ),
+ child: (dashboardViewModel.status is SyncingSyncStatus)
+ ? SizedBox.shrink()
+ : Center(
+ child: Text(S.of(context).transactions_will_appear_here,
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: Theme.of(context).colorScheme.onSurfaceVariant)),
+ ),
),
)
: SliverList(
@@ -51,136 +53,147 @@ class HistorySection extends StatelessWidget {
final prevItem = index == 0 ? null : dashboardViewModel.items[index - 1];
final topPadding = index == 0 ? 0.0 : 18.0;
final item = dashboardViewModel.items[index];
- final nextItem = index == dashboardViewModel.items.length - 1
- ? null
- : dashboardViewModel.items[index + 1];
+ final nextItem = index == dashboardViewModel.items.length - 1
+ ? null
+ : dashboardViewModel.items[index + 1];
- final roundedBottom = (nextItem == null || nextItem is DateSectionItem);
- final roundedTop = (prevItem == null || prevItem is DateSectionItem);
+ final roundedBottom = (nextItem == null || nextItem is DateSectionItem);
+ final roundedTop = (prevItem == null || prevItem is DateSectionItem);
- if (item is TransactionListItem) {
- final transaction = item.transaction;
- final transactionType = dashboardViewModel.getTransactionType(transaction);
+ if (item is TransactionListItem) {
+ final transaction = item.transaction;
+ final transactionType = dashboardViewModel.getTransactionType(transaction);
- if (item.hasTokens && item.assetOfTransaction == null) {
- return Container();
- }
+ if (item.hasTokens && item.assetOfTransaction == null) {
+ return Container();
+ }
- CryptoCurrency? asset;
- if (transaction.additionalInfo["isLightning"] == true)
- asset = CryptoCurrency.btcln;
- else
- asset = item.assetOfTransaction;
+ CryptoCurrency? asset;
+ if (transaction.additionalInfo["isLightning"] == true)
+ asset = CryptoCurrency.btcln;
+ else
+ asset = item.assetOfTransaction;
- return GestureDetector(
- onTap: () {
- final page = getIt.get<TransactionDetailsModal>(param1: transaction);
- showModalBottomSheet(isScrollControlled:true,context: context, builder: (context) => page);
- },
- child: HistoryTile(
- title: item.formattedTitle + transactionType,
- date: DateFormat('HH:mm').format(transaction.date),
- amount: item.formattedCryptoAmount,
- amountFiat: item.formattedFiatAmount,
- hasTokens: item.hasTokens,
- chainIconPath: _getChainIconPath(),
- roundedBottom: roundedBottom,
- roundedTop: roundedTop,
- bottomSeparator: !roundedBottom,
- direction: item.transaction.direction,
- pending: item.transaction.isPending,
- asset: asset,
- ),
- );
- } else if (item is TradeListItem) {
- final trade = item.trade;
+ return GestureDetector(
+ onTap: () {
+ final page = getIt.get<TransactionDetailsModal>(param1: transaction);
+ showModalBottomSheet(
+ isScrollControlled: true,
+ context: context,
+ builder: (context) => page);
+ },
+ child: HistoryTile(
+ title: item.formattedTitle + transactionType,
+ date: DateFormat('HH:mm').format(transaction.date),
+ amount: item.formattedCryptoAmount,
+ amountFiat: item.formattedFiatAmount,
+ hasTokens: item.hasTokens,
+ chainIconPath: _getChainIconPath(),
+ roundedBottom: roundedBottom,
+ roundedTop: roundedTop,
+ bottomSeparator: !roundedBottom,
+ direction: item.transaction.direction,
+ pending: item.transaction.isPending,
+ asset: asset,
+ ),
+ );
+ } else if (item is TradeListItem) {
+ final trade = item.trade;
+ final tradeFrom = trade.from;
+ final tradeTo = trade.to;
+ if (tradeFrom == null || tradeTo == null) {
+ return const SizedBox.shrink();
+ }
- final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom;
+ return GestureDetector(
+ onTap: () => Navigator.of(context)
+ .pushNamed(Routes.tradeDetails, arguments: trade),
+ child: HistoryTradeTile(
+ from: tradeFrom,
+ to: tradeTo,
+ provider: trade.provider,
+ date:
+ DateFormat('HH:mm').format(item.trade.createdAt ?? DateTime.now()),
+ amount: trade.amountFormatted(),
+ receiveAmount: trade.receiveAmountFormatted(),
+ roundedBottom: roundedBottom,
+ roundedTop: roundedTop,
+ bottomSeparator: !roundedBottom,
+ swapState: trade.state,
+ ),
+ );
+ } else if (item is DateSectionItem) {
+ return Padding(
+ padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
+ child: Text(DateFormatter.convertDateTimeToReadableString(item.date),
+ style: TextStyle(
+ color: Theme.of(context).colorScheme.onSurfaceVariant)));
+ } else if (item is OrderListItem) {
+ return GestureDetector(
+ onTap: () => Navigator.of(context)
+ .pushNamed(Routes.orderDetails, arguments: item.order),
+ child: HistoryOrderTile(
+ date: DateFormat('HH:mm').format(item.order.createdAt),
+ amount: item.orderFormattedAmount,
+ amountFiat: "USD 0.00",
+ roundedBottom: roundedBottom,
+ roundedTop: roundedTop,
+ bottomSeparator: !roundedBottom,
+ ),
+ );
+ } else if (item is PayjoinTransactionListItem) {
+ final session = item.session;
- final tradeTo = trade.toRaw >= 0 ? trade.to : trade.userCurrencyTo;
+ return GestureDetector(
+ onTap: () => Navigator.of(context).pushNamed(
+ Routes.payjoinDetails,
+ arguments: [item.sessionId, item.transaction],
+ ),
+ child: PayjoinHistoryTile(
+ createdAt: DateFormat('HH:mm').format(session.inProgressSince!),
+ amount: dashboardViewModel.appStore.amountParsingProxy
+ .getDisplayCryptoString(
+ session.amount.toInt(), CryptoCurrency.btc),
+ currency: item.transaction?.from ?? "BTC",
+ state: item.status,
+ isSending: session.isSenderSession,
+ roundedTop: roundedTop,
+ roundedBottom: roundedBottom,
+ bottomSeparator: !roundedBottom),
+ );
+ } else if (item is AnonpayTransactionListItem) {
+ final transactionInfo = item.transaction;
- return GestureDetector(
- onTap: () => Navigator.of(context)
- .pushNamed(Routes.tradeDetails, arguments: trade),
- child: HistoryTradeTile(
- from: tradeFrom!,
- to: tradeTo!,
- provider: trade.provider,
- date: DateFormat('HH:mm').format(item.trade.createdAt!),
- amount: trade.amountFormatted(),
- receiveAmount: trade.receiveAmountFormatted(),
- roundedBottom: roundedBottom,
- roundedTop: roundedTop,
- bottomSeparator: !roundedBottom,
- swapState: trade.state,
- ),
- );
- } else if (item is DateSectionItem) {
- return Padding(
- padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
- child: Text(DateFormatter.convertDateTimeToReadableString(item.date),
- style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant)));
- }else if(item is OrderListItem){
- return GestureDetector(
- onTap: () => Navigator.of(context)
- .pushNamed(Routes.orderDetails, arguments: item.order),
- child: HistoryOrderTile(
- date: DateFormat('HH:mm').format(item.order.createdAt),
- amount: item.orderFormattedAmount,
- amountFiat: "USD 0.00",
- roundedBottom: roundedBottom,
- roundedTop: roundedTop,
- bottomSeparator: !roundedBottom,
- ),
- );
- } else if (item is PayjoinTransactionListItem) {
- final session = item.session;
-
- return GestureDetector(
- onTap: () => Navigator.of(context).pushNamed(
- Routes.payjoinDetails,
- arguments: [item.sessionId, item.transaction],
+ return GestureDetector(
+ onTap: () => Navigator.of(context)
+ .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
+ child: AnonpayHistoryTile(
+ provider: transactionInfo.provider,
+ createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
+ amount: transactionInfo.fiatAmount?.toString() ??
+ (transactionInfo.amountTo?.toString() ?? ''),
+ currency: transactionInfo.fiatAmount != null
+ ? transactionInfo.fiatEquiv ?? ''
+ : CryptoCurrency.fromFullName(transactionInfo.coinTo)
+ .name
+ .toUpperCase(),
+ roundedTop: roundedTop,
+ roundedBottom: roundedBottom,
+ bottomSeparator: !roundedBottom));
+ } else
+ return Text(item.runtimeType.toString());
+ }),
+ ),
),
- child: PayjoinHistoryTile(
- createdAt: DateFormat('HH:mm').format(session.inProgressSince!),
- amount: dashboardViewModel.appStore.amountParsingProxy
- .getDisplayCryptoString(session.amount.toInt(), CryptoCurrency.btc),
- currency: item.transaction?.from ?? "BTC",
- state: item.status,
- isSending: session.isSenderSession,
- roundedTop: roundedTop,
- roundedBottom: roundedBottom,
- bottomSeparator: !roundedBottom),
- );
- } else if (item is AnonpayTransactionListItem) {
- final transactionInfo = item.transaction;
-
- return GestureDetector(
- onTap: () => Navigator.of(context)
- .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
- child: AnonpayHistoryTile(
- provider: transactionInfo.provider,
- createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
- amount: transactionInfo.fiatAmount?.toString() ??
- (transactionInfo.amountTo?.toString() ?? ''),
- currency: transactionInfo.fiatAmount != null
- ? transactionInfo.fiatEquiv ?? ''
- : CryptoCurrency.fromFullName(transactionInfo.coinTo).name.toUpperCase(),
- roundedTop: roundedTop,
- roundedBottom: roundedBottom,
- bottomSeparator: !roundedBottom));
- } else
- return Text(item.runtimeType.toString());
- }),
- ),
- ),
- ));
+ ));
}
String _getChainIconPath() {
try {
- return CryptoCurrency.fromString(dashboardViewModel.wallet.currency.tag ??dashboardViewModel.wallet.currency.title).chainIconPath!;
- } catch(e) {
+ return CryptoCurrency.fromString(
+ dashboardViewModel.wallet.currency.tag ?? dashboardViewModel.wallet.currency.title)
+ .chainIconPath!;
+ } catch (e) {
return dashboardViewModel.wallet.currency.chainIconPath ?? "";
}
}
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart b/lib/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart
index 8a13bbb2..3e859803 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart
@@ -39,28 +39,30 @@ class HistoryTradeTile extends StatelessWidget {
width: 50,
child: Stack(
children: [
- CakeImageWidget(imageUrl: _getIconPath(from),
- width: currencyIconSize, height: currencyIconSize),
+ CakeImageWidget(
+ imageUrl: _getIconPath(from), width: currencyIconSize, height: currencyIconSize),
Positioned(
- top: currencyIconSize / 2,
- left: currencyIconSize / 2,
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(
- width: 2,
- color: Theme.of(context).colorScheme.surfaceContainer),
- shape: BoxShape.circle),
- child: CakeImageWidget(imageUrl: _getIconPath(to),
- width: currencyIconSize, height: currencyIconSize))),
+ top: currencyIconSize / 2,
+ left: currencyIconSize / 2,
+ child: Container(
+ decoration: BoxDecoration(
+ border:
+ Border.all(width: 2, color: Theme.of(context).colorScheme.surfaceContainer),
+ shape: BoxShape.circle),
+ child: CakeImageWidget(
+ imageUrl: _getIconPath(to),
+ width: currencyIconSize,
+ height: currencyIconSize,
+ ),
+ ),
+ ),
],
),
);
}
-
@override
Widget build(BuildContext context) {
-
final fromChainIcon = _getChainIcon(from);
final toChainIcon = _getChainIcon(to);
@@ -118,36 +120,32 @@ class HistoryTradeTile extends StatelessWidget {
}
String _getIconPath(CryptoCurrency currency) {
- try { // temporarily until we migrate from hive to sqlite and store the full currency object
- if (currency.iconPath != null) {
- return currency.iconPath!;
+ try {
+ if (currency.title.isNotEmpty) {
+ final live = CryptoCurrency.safeParseCurrencyFromString(currency.title, tag: currency.tag);
+ if (live?.iconPath != null) return live!.iconPath!;
}
- if (currency.name.isNotEmpty) {
- final currencyFromName = CryptoCurrency.fromString(currency.name);
- if (currencyFromName.iconPath != null) {
- return currencyFromName.iconPath!;
- }
- }
+ if (currency.iconPath != null) return currency.iconPath!;
- if (currency.title.isNotEmpty) {
- final currencyFromTitle = CryptoCurrency.fromString(currency.title);
- if (currencyFromTitle.iconPath != null) {
- return currencyFromTitle.iconPath!;
- }
+ if (currency.name.isNotEmpty) {
+ final byName = CryptoCurrency.safeParseCurrencyFromString(currency.name);
+ if (byName?.iconPath != null) return byName!.iconPath!;
}
} catch (_) {}
- //TODO approporiate fallback
return "";
}
String _getChainIcon(CryptoCurrency currency) {
try {
- if (currency.chainIconPath != null) {
- return currency.chainIconPath!;
+ if (currency.title.isNotEmpty) {
+ final parsedCurrency = CryptoCurrency.safeParseCurrencyFromString(currency.title, tag: currency.tag);
+ if (parsedCurrency?.chainIconPath != null) return parsedCurrency!.chainIconPath!;
}
+ if (currency.chainIconPath != null) return currency.chainIconPath!;
+
if ((currency.tag ?? "").isNotEmpty) {
final currencyFromTag = CryptoCurrency.fromString(currency.tag!);
if (currencyFromTag.chainIconPath != null) {
diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart
index 5a0b7c44..39b0dcc8 100644
--- a/lib/src/screens/dashboard/pages/transactions_page.dart
+++ b/lib/src/screens/dashboard/pages/transactions_page.dart
@@ -166,9 +166,9 @@ class TransactionsPage extends StatelessWidget {
final trade = item.trade;
final tradeFrom =
- trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom;
+ trade.from;
- final tradeTo = trade.toRaw >= 0 ? trade.to : trade.userCurrencyTo;
+ final tradeTo = trade.to;
return tradeFrom != null && tradeTo != null
? Observer(
diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart
index c89a2eb9..8ffd7685 100644
--- a/lib/src/screens/exchange_trade/exchange_trade_page.dart
+++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart
@@ -31,7 +31,7 @@ void showInformation(ExchangeTradeViewModel exchangeTradeViewModel, BuildContext
final trade = exchangeTradeViewModel.trade;
final walletName = exchangeTradeViewModel.wallet.name;
- final from = trade.from?.toString() ?? trade.userCurrencyFrom.toString();
+ final from = trade.from?.toString() ?? '';
final information = exchangeTradeViewModel.isSendable
? S.current.exchange_trade_result_confirm(trade.amount, from, walletName) +
diff --git a/lib/src/widgets/bottom_sheet/swap_details_bottom_sheet.dart b/lib/src/widgets/bottom_sheet/swap_details_bottom_sheet.dart
index 9545f775..12544c8b 100644
--- a/lib/src/widgets/bottom_sheet/swap_details_bottom_sheet.dart
+++ b/lib/src/widgets/bottom_sheet/swap_details_bottom_sheet.dart
@@ -319,14 +319,14 @@ class _SwapDetailsContent extends StatelessWidget {
_SwapDetailsTile(
label: 'You Send',
value:
- '${trade.amount} ${trade.from?.title ?? trade.userCurrencyFrom?.title ?? ''}',
+ '${trade.amount} ${trade.from?.title ?? ''}',
valueFiatFormatted: exchangeTradeViewModel.sendAmountFiatFormatted,
),
const SizedBox(height: 8),
_SwapDetailsTile(
label: 'You Get',
value:
- '${trade.receiveAmount ?? '0'} ${trade.to?.title ?? trade.userCurrencyTo?.title ?? ''}',
+ '${trade.receiveAmount ?? '0'} ${trade.to?.title ?? ''}',
valueFiatFormatted: exchangeTradeViewModel
.getReceiveAmountFiatFormatted(trade.receiveAmount ?? '0.0'),
),
diff --git a/lib/store/dashboard/trades_store.dart b/lib/store/dashboard/trades_store.dart
index b32ae1f8..3db546f7 100644
--- a/lib/store/dashboard/trades_store.dart
+++ b/lib/store/dashboard/trades_store.dart
@@ -1,9 +1,7 @@
-import 'dart:async';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
import 'package:flutter/foundation.dart';
-import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
part 'trades_store.g.dart';
@@ -11,14 +9,11 @@ part 'trades_store.g.dart';
class TradesStore = TradesStoreBase with _$TradesStore;
abstract class TradesStoreBase with Store {
- TradesStoreBase({required this.tradesSource, required this.appStore})
- : trades = <TradeListItem>[] {
- _onTradesChanged = tradesSource.watch().listen((_) async => await updateTradeList());
+ TradesStoreBase({required this.appStore}) : trades = <TradeListItem>[] {
+ Trade.onChanged.stream.listen((_) => updateTradeList());
updateTradeList();
}
- Box<Trade> tradesSource;
- StreamSubscription<BoxEvent>? _onTradesChanged;
AppStore appStore;
@observable
@@ -31,11 +26,18 @@ abstract class TradesStoreBase with Store {
void setTrade(Trade trade) => this.trade = trade;
@action
- Future<void> updateTradeList() async => trades = tradesSource.values
- .map((trade) => TradeListItem(
- trade: trade,
- appStore: appStore,
- key: ValueKey('trade_list_item_${trade.id}_key'),
- ))
- .toList();
+ Future<void> updateTradeList() async {
+ try {
+ final allTrades = await Trade.getAll();
+ runInAction(() {
+ trades = allTrades
+ .map((trade) => TradeListItem(
+ trade: trade,
+ appStore: appStore,
+ key: ValueKey('trade_list_item_${trade.id}_key'),
+ ))
+ .toList();
+ });
+ } catch (_) {}
+ }
}
diff --git a/lib/view_model/dashboard/trade_list_item.dart b/lib/view_model/dashboard/trade_list_item.dart
index e725afca..1fdd677d 100644
--- a/lib/view_model/dashboard/trade_list_item.dart
+++ b/lib/view_model/dashboard/trade_list_item.dart
@@ -15,15 +15,24 @@ class TradeListItem extends ActionListItem {
BalanceDisplayMode get displayMode => appStore.settingsStore.balanceDisplayMode;
- String get tradeFormattedAmount => displayMode == BalanceDisplayMode.hiddenBalance
- ? "---"
- : appStore.amountParsingProxy.getDisplayCryptoAmount(trade.amountFormatted(), trade.from!);
+ String get tradeFormattedAmount {
+ if (displayMode == BalanceDisplayMode.hiddenBalance) {
+ return '---';
+ }
+ final from = trade.from;
+ if (from == null) return trade.amountFormatted();
+ return appStore.amountParsingProxy.getDisplayCryptoAmount(trade.amountFormatted(), from);
+ }
- String get tradeFormattedReceiveAmount => displayMode == BalanceDisplayMode.hiddenBalance
- ? "---"
- : appStore.amountParsingProxy
- .getDisplayCryptoAmount(trade.receiveAmountFormatted(), trade.to!);
+ String get tradeFormattedReceiveAmount {
+ if (displayMode == BalanceDisplayMode.hiddenBalance) {
+ return '---';
+ }
+ final to = trade.to;
+ if (to == null) return trade.receiveAmountFormatted();
+ return appStore.amountParsingProxy.getDisplayCryptoAmount(trade.receiveAmountFormatted(), to);
+ }
@override
- DateTime get date => trade.createdAt!;
+ DateTime get date => trade.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
}
diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart
index 60f6e233..7807fb1e 100644
--- a/lib/view_model/exchange/exchange_trade_view_model.dart
+++ b/lib/view_model/exchange/exchange_trade_view_model.dart
@@ -34,7 +34,6 @@ import 'package:cw_core/payment_uris.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
-import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
part 'exchange_trade_view_model.g.dart';
@@ -44,7 +43,6 @@ class ExchangeTradeViewModel = ExchangeTradeViewModelBase with _$ExchangeTradeVi
abstract class ExchangeTradeViewModelBase with Store {
ExchangeTradeViewModelBase({
required this.wallet,
- required this.trades,
required this.tradesStore,
required this.sendViewModel,
required this.feesViewModel,
@@ -78,10 +76,10 @@ abstract class ExchangeTradeViewModelBase with Store {
_provider = StealthExExchangeProvider();
break;
case ExchangeProviderDescription.thorChain:
- _provider = ThorChainExchangeProvider(tradesStore: trades);
+ _provider = ThorChainExchangeProvider();
break;
case ExchangeProviderDescription.chainflip:
- _provider = ChainflipExchangeProvider(tradesStore: trades);
+ _provider = ChainflipExchangeProvider();
break;
case ExchangeProviderDescription.xoSwap:
_provider = XOSwapExchangeProvider();
@@ -106,7 +104,6 @@ abstract class ExchangeTradeViewModelBase with Store {
}
final WalletBase wallet;
- final Box<Trade> trades;
final TradesStore tradesStore;
final SendViewModel sendViewModel;
final FeesViewModel feesViewModel;
@@ -217,7 +214,7 @@ abstract class ExchangeTradeViewModelBase with Store {
Future<void> confirmSending() async {
if (!isSendable) return;
- final selected = trade.from ?? trade.userCurrencyFrom;
+ final selected = trade.from;
if (selected == null) {
printV('No selectable currency for trade ${trade.id}');
return;
@@ -231,35 +228,23 @@ abstract class ExchangeTradeViewModelBase with Store {
if (_provider is SwapsXyzExchangeProvider) {
final hash = pendingTransaction?.evmTxHashFromRawHex ?? pendingTransaction?.id ?? '';
trade.txId = hash;
-
- if (trade.isInBox) {
- await trade.save();
- } else {
- await trades.add(trade);
- }
+ await trade.save();
}
if (_provider is ThorChainExchangeProvider) {
trade.id = pendingTransaction?.id ?? '';
- trades.add(trade);
+ await trade.save();
}
}
@action
Future<void> _updateTrade() async {
try {
- final agreedAmount = tradesStore.trade!.amount;
- final isSendAll = tradesStore.trade!.isSendAll;
final updatedTrade = await _provider!.findTradeById(id: trade.id);
- if (updatedTrade.createdAt == null && trade.createdAt != null)
- updatedTrade.createdAt = trade.createdAt;
-
- if (updatedTrade.amount.isEmpty) updatedTrade.amount = trade.amount;
-
- trade = updatedTrade;
- trade.amount = agreedAmount;
- trade.isSendAll = isSendAll;
+ trade.mergeFindTradeByIdResult(updatedTrade);
+ await trade.save();
+ tradesStore.setTrade(trade);
_updateItems();
} catch (e) {
@@ -268,10 +253,8 @@ abstract class ExchangeTradeViewModelBase with Store {
}
void _updateItems() {
- final trade = tradesStore.trade!;
-
- final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom;
- final tradeTo = trade.toRaw >= 0 ? trade.to : trade.userCurrencyTo;
+ final tradeFrom = trade.from;
+ final tradeTo = trade.to;
final tagFrom = tradeFrom?.tag != null ? "${tradeFrom!.tag} " : "";
final tagTo = tradeTo?.tag != null ? "${tradeTo!.tag} " : "";
@@ -289,12 +272,12 @@ abstract class ExchangeTradeViewModelBase with Store {
),
);
- if (tradeFrom != null || tradeTo != null) {
+ if (tradeFrom != null && tradeTo != null) {
items.addAll([
ExchangeTradeItem(
title: S.current.amount,
data:
- "${_amountParsingProxy.getDisplayCryptoAmount(trade.amount, tradeFrom!)} ${_amountParsingProxy.getCryptoSymbol(tradeFrom)}",
+ "${_amountParsingProxy.getDisplayCryptoAmount(trade.amount, tradeFrom)} ${_amountParsingProxy.getCryptoSymbol(tradeFrom)}",
isCopied: false,
isReceiveDetail: false,
isExternalSendDetail: true,
@@ -302,14 +285,14 @@ abstract class ExchangeTradeViewModelBase with Store {
ExchangeTradeItem(
title: "${S.current.you_will_receive_estimated_amount}:",
data:
- "${_amountParsingProxy.getDisplayCryptoAmount(tradesStore.trade?.receiveAmount ?? "0", tradeTo!)} ${_amountParsingProxy.getCryptoSymbol(tradeTo)}",
+ "${_amountParsingProxy.getDisplayCryptoAmount(trade.receiveAmount ?? "0", tradeTo)} ${_amountParsingProxy.getCryptoSymbol(tradeTo)}",
isCopied: true,
isReceiveDetail: true,
isExternalSendDetail: false,
),
ExchangeTradeItem(
- title: "${S.current.send_to_this_address("${tradeFrom}", tagFrom)}:",
- data: trade.inputAddress ?? "",
+ title: "${S.current.send_to_this_address("$tradeFrom", tagFrom)}:",
+ data: trade.inputAddress ?? '',
isCopied: false,
isReceiveDetail: false,
isExternalSendDetail: true,
@@ -367,7 +350,10 @@ abstract class ExchangeTradeViewModelBase with Store {
static bool _checkIfCanSend(TradesStore tradesStore, WalletBase wallet) {
final trade = tradesStore.trade!;
- final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom;
+ final tradeFrom = trade.from;
+
+ bool _sameCurrency(CryptoCurrency? a, CryptoCurrency? b) =>
+ a != null && b != null && a.titleAndTagEqual(b);
bool _isEthToken() =>
wallet.currency == CryptoCurrency.eth && tradeFrom?.tag == CryptoCurrency.eth.title;
@@ -393,8 +379,9 @@ abstract class ExchangeTradeViewModelBase with Store {
bool _isBscToken() =>
wallet.currency == CryptoCurrency.bnb && tradeFrom?.tag == CryptoCurrency.bnb.tag;
- return tradeFrom == wallet.currency ||
- tradeFrom == CryptoCurrency.btcln && wallet.currency == CryptoCurrency.btc ||
+ return _sameCurrency(tradeFrom, wallet.currency) ||
+ (_sameCurrency(tradeFrom, CryptoCurrency.btcln) &&
+ wallet.currency == CryptoCurrency.btc) ||
tradesStore.trade!.provider == ExchangeProviderDescription.xmrto ||
_isEthToken() ||
_isPolygonToken() ||
@@ -472,7 +459,7 @@ abstract class ExchangeTradeViewModelBase with Store {
PaymentURI? get paymentUri {
final inputAddress = trade.inputAddress;
final amount = trade.amount;
- final fromCurrency = trade.from ?? trade.userCurrencyFrom;
+ final fromCurrency = trade.from;
if (inputAddress == null || inputAddress.isEmpty || fromCurrency == null) {
return null;
diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart
index 6ae08551..9811a999 100644
--- a/lib/view_model/exchange/exchange_view_model.dart
+++ b/lib/view_model/exchange/exchange_view_model.dart
@@ -67,7 +67,6 @@ import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
-import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -95,7 +94,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
ExchangeViewModelBase(
this._appStore,
- this.trades,
this._exchangeTemplateStore,
this.tradesStore,
this.sharedPreferences,
@@ -307,7 +305,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
[WalletType.monero, WalletType.wownero, WalletType.zcash].contains(wallet.type);
bool _useTorOnly;
- final Box<Trade> trades;
final ExchangeTemplateStore _exchangeTemplateStore;
final TradesStore tradesStore;
final SharedPreferences sharedPreferences;
@@ -315,7 +312,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
List<ExchangeProvider> get _allProviders => [
ChangeNowExchangeProvider(settingsStore: _settingsStore),
// SideShiftExchangeProvider(),
- ChainflipExchangeProvider(tradesStore: trades),
+ ChainflipExchangeProvider(),
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
SwapTradeExchangeProvider(),
LetsExchangeExchangeProvider(),
@@ -1213,7 +1210,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
}
tradesStore.setTrade(trade);
- if (trade.provider != ExchangeProviderDescription.thorChain) await trades.add(trade);
+ if (trade.provider != ExchangeProviderDescription.thorChain) await trade.save();
tradeState = TradeIsCreatedSuccessfully(trade: trade);
/// return after the first successful trade
@@ -1626,7 +1623,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
if (trade.provider == ExchangeProviderDescription.swapsXyz) {
- final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom;
+ final tradeFrom = trade.from;
if (tradeFrom == null) {
return CreateTradeResult(
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 1c39e57e..7ff989dd 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -1091,9 +1091,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
_currentTrade!.stateRaw = isSuccess ? TradeState.completed.raw : TradeState.failed.raw;
- if (_currentTrade!.isInBox) {
- await _currentTrade!.save();
- }
+ await _currentTrade!.save();
}
@action
diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart
index dcc304b9..54f7615e 100644
--- a/lib/view_model/trade_details_view_model.dart
+++ b/lib/view_model/trade_details_view_model.dart
@@ -26,11 +26,8 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/utils/date_formatter.dart';
import 'package:cake_wallet/utils/show_bar.dart';
-import 'package:collection/collection.dart';
-import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:flutter/services.dart';
-import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -41,11 +38,9 @@ class TradeDetailsViewModel = TradeDetailsViewModelBase with _$TradeDetailsViewM
abstract class TradeDetailsViewModelBase with Store {
TradeDetailsViewModelBase({
required Trade tradeForDetails,
- required this.trades,
required this.appStore,
}) : items = ObservableList<StandartListItem>(),
- trade = trades.values.firstWhereOrNull((element) => element.id == tradeForDetails.id) ??
- tradeForDetails {
+ trade = tradeForDetails {
switch (trade.provider) {
case ExchangeProviderDescription.changeNow:
_provider = ChangeNowExchangeProvider(settingsStore: appStore.settingsStore);
@@ -63,7 +58,7 @@ abstract class TradeDetailsViewModelBase with Store {
_provider = ExolixExchangeProvider();
break;
case ExchangeProviderDescription.thorChain:
- _provider = ThorChainExchangeProvider(tradesStore: trades);
+ _provider = ThorChainExchangeProvider();
break;
case ExchangeProviderDescription.swapTrade:
_provider = SwapTradeExchangeProvider();
@@ -74,7 +69,7 @@ abstract class TradeDetailsViewModelBase with Store {
_provider = StealthExExchangeProvider();
break;
case ExchangeProviderDescription.chainflip:
- _provider = ChainflipExchangeProvider(tradesStore: trades);
+ _provider = ChainflipExchangeProvider();
break;
case ExchangeProviderDescription.xoSwap:
_provider = XOSwapExchangeProvider();
@@ -132,8 +127,6 @@ abstract class TradeDetailsViewModelBase with Store {
return null;
}
- final Box<Trade> trades;
-
@observable
Trade trade;
@@ -151,22 +144,8 @@ abstract class TradeDetailsViewModelBase with Store {
try {
final updatedTrade = await _provider!.findTradeById(id: trade.id);
- if (updatedTrade.createdAt == null && trade.createdAt != null) {
- updatedTrade.createdAt = trade.createdAt;
- }
-
- if (updatedTrade.toRaw == -1 && trade.toRaw != -1) {
- updatedTrade.toRaw = trade.toRaw;
- }
-
- Trade? foundElement = trades.values.firstWhereOrNull((element) => element.id == trade.id);
- if (foundElement != null) {
- final editedTrade = trades.get(foundElement.key);
- editedTrade?.stateRaw = updatedTrade.stateRaw;
- editedTrade?.save();
- }
-
- trade = updatedTrade;
+ trade.mergeFindTradeByIdResult(updatedTrade);
+ await trade.save();
_updateItems();
} catch (e) {
@@ -186,8 +165,8 @@ abstract class TradeDetailsViewModelBase with Store {
items.add(
DetailsListStatusItem(title: S.current.trade_details_state, value: trade.state.toString()));
- final tradeFrom = _safeFrom(trade);
- final tradeTo = _safeTo(trade);
+ final tradeFrom = trade.from;
+ final tradeTo = trade.to;
if (tradeFrom != null && tradeTo != null) {
items.add(TradeDetailsListCardItem.tradeDetails(
@@ -241,21 +220,5 @@ abstract class TradeDetailsViewModelBase with Store {
} catch (e) {}
}
- CryptoCurrency? _safeFrom(Trade trade) {
- try {
- final raw = trade.fromRaw;
- return raw >= 0 ? trade.from : trade.userCurrencyFrom;
- } catch (_) {
- return trade.userCurrencyFrom;
- }
- }
- CryptoCurrency? _safeTo(Trade trade) {
- try {
- final raw = trade.toRaw;
- return raw >= 0 ? trade.to : trade.userCurrencyTo;
- } catch (_) {
- return trade.userCurrencyTo;
- }
- }
}
Why this scored 27/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.