diff --git a/lib/bloc/app_bloc_root.dart b/lib/bloc/app_bloc_root.dart index cc5c732256..59e8c18e07 100644 --- a/lib/bloc/app_bloc_root.dart +++ b/lib/bloc/app_bloc_root.dart @@ -28,6 +28,7 @@ import 'package:web_dex/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart'; import 'package:web_dex/bloc/cex_market_data/profit_loss/profit_loss_repository.dart'; import 'package:web_dex/bloc/coins_bloc/coins_bloc.dart'; import 'package:web_dex/bloc/coins_bloc/coins_repo.dart'; +import 'package:web_dex/bloc/coins_manager/coins_manager_bloc.dart'; import 'package:web_dex/bloc/dex_repository.dart'; import 'package:web_dex/bloc/market_maker_bot/market_maker_bot/market_maker_bot_bloc.dart'; import 'package:web_dex/bloc/market_maker_bot/market_maker_bot/market_maker_bot_repository.dart'; @@ -125,7 +126,7 @@ class AppBlocRoot extends StatelessWidget { demoDataGenerator: DemoDataCache.withDefaults(), ) : */ - TransactionHistoryRepo(sdk: komodoDefiSdk); + SdkTransactionHistoryRepository(sdk: komodoDefiSdk); final profitLossRepo = ProfitLossRepository.withDefaults( transactionHistoryRepo: transactionsRepo, @@ -135,7 +136,6 @@ class AppBlocRoot extends StatelessWidget { demoMode: performanceMode, coinsRepository: coinsRepository, mm2Api: mm2Api, - sdk: komodoDefiSdk, ); final portfolioGrowthRepo = PortfolioGrowthRepository.withDefaults( @@ -144,7 +144,6 @@ class AppBlocRoot extends StatelessWidget { demoMode: performanceMode, coinsRepository: coinsRepository, mm2Api: mm2Api, - sdk: komodoDefiSdk, ); _clearCachesIfPerformanceModeChanged( @@ -303,6 +302,12 @@ class AppBlocRoot extends StatelessWidget { coinsRepository: coinsRepository, ), ), + BlocProvider( + create: (context) => CoinsManagerBloc( + coinsRepo: coinsRepository, + sdk: komodoDefiSdk, + ), + ), ], child: _MyAppView(), ), diff --git a/lib/bloc/assets_overview/bloc/asset_overview_bloc.dart b/lib/bloc/assets_overview/bloc/asset_overview_bloc.dart index 8b96403366..b47cc1c1e3 100644 --- a/lib/bloc/assets_overview/bloc/asset_overview_bloc.dart +++ b/lib/bloc/assets_overview/bloc/asset_overview_bloc.dart @@ -39,7 +39,7 @@ class AssetOverviewBloc extends Bloc { try { final profitLosses = await profitLossRepository.getProfitLoss( - event.coin.abbr, + event.coin.id, 'USDT', event.walletId, ); @@ -96,7 +96,7 @@ class AssetOverviewBloc extends Bloc { // affect the total investment calculation. try { return await profitLossRepository.getProfitLoss( - coin.abbr, + coin.id, 'USDT', event.walletId, ); diff --git a/lib/bloc/assets_overview/investment_repository.dart b/lib/bloc/assets_overview/investment_repository.dart index 825c4fa1f0..94ddd014a7 100644 --- a/lib/bloc/assets_overview/investment_repository.dart +++ b/lib/bloc/assets_overview/investment_repository.dart @@ -1,7 +1,6 @@ import 'package:web_dex/bloc/cex_market_data/profit_loss/models/fiat_value.dart'; import 'package:web_dex/bloc/cex_market_data/profit_loss/profit_loss_repository.dart'; import 'package:web_dex/model/coin.dart'; - import 'package:web_dex/shared/utils/utils.dart' as logger; class InvestmentRepository { @@ -29,7 +28,7 @@ class InvestmentRepository { // affect the total investment calculation. try { final profitLoss = await _profitLossRepository.getProfitLoss( - coin.abbr, + coin.id, 'USDT', walletId, ); diff --git a/lib/bloc/cex_market_data/mockup/generate_demo_data.dart b/lib/bloc/cex_market_data/mockup/generate_demo_data.dart index e715a96d60..84138e7f9e 100644 --- a/lib/bloc/cex_market_data/mockup/generate_demo_data.dart +++ b/lib/bloc/cex_market_data/mockup/generate_demo_data.dart @@ -1,10 +1,10 @@ import 'dart:math'; +import 'package:decimal/decimal.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:uuid/uuid.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/performance_mode.dart'; -import 'package:web_dex/mm2/mm2_api/rpc/my_tx_history/transaction.dart'; -import 'package:web_dex/model/withdraw_details/fee_details.dart'; // similar to generator implementation to allow for const constructor final _ohlcvCache = >{}; @@ -110,7 +110,7 @@ class DemoDataGenerator { transactions.add(transaction); } - totalBalance += double.parse(transaction.myBalanceChange); + totalBalance += transaction.balanceChanges.netChange.toDouble(); if (totalBalance <= 0) { totalBalance = targetFinalBalance; break; @@ -131,22 +131,34 @@ class DemoDataGenerator { double totalBalance, List transactions, ) { - double adjustmentFactor = targetFinalBalance / totalBalance; + final Decimal adjustmentFactor = + Decimal.parse((targetFinalBalance / totalBalance).toString()); final adjustedTransactions = []; for (var transaction in transactions) { + final netChange = transaction.balanceChanges.netChange; + final received = transaction.balanceChanges.receivedByMe; + final spent = transaction.balanceChanges.spentByMe; + final totalAmount = transaction.balanceChanges.totalAmount; + adjustedTransactions.add( - transaction.copyWith( - myBalanceChange: - (double.parse(transaction.myBalanceChange) * adjustmentFactor) - .toString(), - receivedByMe: - (double.parse(transaction.receivedByMe) * adjustmentFactor) - .toString(), - spentByMe: (double.parse(transaction.spentByMe) * adjustmentFactor) - .toString(), - totalAmount: - (double.parse(transaction.totalAmount) * adjustmentFactor) - .toString(), + Transaction( + id: transaction.id, + timestamp: transaction.timestamp, + assetId: transaction.assetId, + blockHeight: transaction.blockHeight, + from: transaction.from, + internalId: transaction.internalId, + confirmations: transaction.confirmations, + to: transaction.to, + txHash: transaction.txHash, + fee: transaction.fee, + memo: transaction.memo, + balanceChanges: BalanceChanges( + netChange: netChange * adjustmentFactor, + receivedByMe: received * adjustmentFactor, + spentByMe: spent * adjustmentFactor, + totalAmount: totalAmount * adjustmentFactor, + ), ), ); } @@ -193,25 +205,30 @@ Transaction fromTradeAmount( final random = Random(42); return Transaction( + id: uuid.v4(), blockHeight: random.nextInt(100000) + 100000, - coin: coinId, - confirmations: random.nextInt(3) + 1, - feeDetails: FeeDetails( - type: "fixed", - coin: "USDT", - amount: "1.0", - totalFee: "1.0", + assetId: AssetId( + chainId: AssetChainId(chainId: 0), + derivationPath: '', + id: coinId, + name: coinId, + subClass: CoinSubClass.smartChain, + symbol: AssetSymbol(assetConfigId: coinId), ), - from: ["address1"], + confirmations: random.nextInt(3) + 1, + from: const ["address1"], internalId: uuid.v4(), - myBalanceChange: isBuy ? tradeAmount.toString() : (-tradeAmount).toString(), - receivedByMe: !isBuy ? tradeAmount.toString() : '0', - spentByMe: isBuy ? tradeAmount.toString() : '0', - timestamp: closeTimestamp ~/ 1000, - to: ["address2"], - totalAmount: tradeAmount.toString(), + balanceChanges: BalanceChanges( + netChange: Decimal.parse( + isBuy ? tradeAmount.toString() : (-tradeAmount).toString(), + ), + receivedByMe: Decimal.parse(!isBuy ? tradeAmount.toString() : '0'), + spentByMe: Decimal.parse(isBuy ? tradeAmount.toString() : '0'), + totalAmount: Decimal.parse(tradeAmount.toString()), + ), + timestamp: DateTime.fromMillisecondsSinceEpoch(closeTimestamp), + to: const ["address2"], txHash: uuid.v4(), - txHex: "hexstring", memo: "memo", ); } diff --git a/lib/bloc/cex_market_data/mockup/generator.dart b/lib/bloc/cex_market_data/mockup/generator.dart index a1e8c50884..fdd9cfe1a5 100644 --- a/lib/bloc/cex_market_data/mockup/generator.dart +++ b/lib/bloc/cex_market_data/mockup/generator.dart @@ -3,9 +3,9 @@ import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/generate_demo_data.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/performance_mode.dart'; -import 'package:web_dex/mm2/mm2_api/rpc/my_tx_history/transaction.dart'; final _supportedCoinsCache = >{}; final _transactionsCache = >>{}; diff --git a/lib/bloc/cex_market_data/mockup/mock_portfolio_growth_repository.dart b/lib/bloc/cex_market_data/mockup/mock_portfolio_growth_repository.dart index 68567d22e3..0a506d2b78 100644 --- a/lib/bloc/cex_market_data/mockup/mock_portfolio_growth_repository.dart +++ b/lib/bloc/cex_market_data/mockup/mock_portfolio_growth_repository.dart @@ -1,6 +1,5 @@ import 'package:http/http.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; -import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; import 'package:komodo_persistence_layer/komodo_persistence_layer.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/generator.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart'; @@ -26,7 +25,6 @@ class MockPortfolioGrowthRepository extends PortfolioGrowthRepository { required this.performanceMode, required CoinsRepo coinsRepository, required Mm2Api mm2Api, - required KomodoDefiSdk sdk, }) : super( cexRepository: BinanceRepository( binanceProvider: const BinanceProvider(), @@ -36,7 +34,6 @@ class MockPortfolioGrowthRepository extends PortfolioGrowthRepository { client: Client(), performanceMode: performanceMode, demoDataGenerator: DemoDataCache.withDefaults(), - sdk: sdk, ), cacheProvider: HiveLazyBoxProvider( name: GraphType.balanceGrowth.tableName, diff --git a/lib/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart b/lib/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart index 77a7f2643f..0763a0678f 100644 --- a/lib/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart +++ b/lib/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart @@ -1,12 +1,11 @@ import 'package:http/http.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/generator.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/performance_mode.dart'; import 'package:web_dex/bloc/transaction_history/transaction_history_repo.dart'; import 'package:web_dex/mm2/mm2_api/mm2_api.dart'; -import 'package:web_dex/mm2/mm2_api/rpc/my_tx_history/transaction.dart'; -import 'package:web_dex/model/coin.dart'; -class MockTransactionHistoryRepo extends TransactionHistoryRepo { +class MockTransactionHistoryRepo implements TransactionHistoryRepo { final PerformanceMode performanceMode; final DemoDataCache demoDataGenerator; @@ -15,14 +14,17 @@ class MockTransactionHistoryRepo extends TransactionHistoryRepo { required Client client, required this.performanceMode, required this.demoDataGenerator, - required super.sdk, }); - - // TODO: SDK Port needed, not sure about this part - Future> fetchTransactions(Coin coin) async { + @override + Future> fetch(AssetId assetId) { return demoDataGenerator.loadTransactionsDemoData( performanceMode, - coin.abbr, + assetId.id, ); } + + @override + Future> fetchCompletedTransactions(AssetId assetId) { + return fetch(assetId); + } } diff --git a/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart b/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart index 515337177e..6b05f2a775 100644 --- a/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart +++ b/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart @@ -141,7 +141,7 @@ class PortfolioGrowthBloc final List coins = List.from(event.coins); for (final coin in event.coins) { final isCoinSupported = await portfolioGrowthRepository - .isCoinChartSupported(coin.abbr, event.fiatCoinId); + .isCoinChartSupported(coin.id, event.fiatCoinId); if (!isCoinSupported) { coins.remove(coin); } diff --git a/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_repository.dart b/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_repository.dart index 933443b10d..fd6d4c8c38 100644 --- a/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_repository.dart +++ b/lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_repository.dart @@ -3,7 +3,7 @@ import 'dart:math'; import 'package:hive/hive.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart' as cex; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; -import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:komodo_persistence_layer/komodo_persistence_layer.dart'; import 'package:web_dex/bloc/cex_market_data/charts.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/mock_portfolio_growth_repository.dart'; @@ -13,7 +13,6 @@ import 'package:web_dex/bloc/cex_market_data/models/models.dart'; import 'package:web_dex/bloc/coins_bloc/coins_repo.dart'; import 'package:web_dex/bloc/transaction_history/transaction_history_repo.dart'; import 'package:web_dex/mm2/mm2_api/mm2_api.dart'; -import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/model/coin.dart'; /// A repository for fetching the growth chart for the portfolio and coins. @@ -37,7 +36,6 @@ class PortfolioGrowthRepository { required cex.CexRepository cexRepository, required CoinsRepo coinsRepository, required Mm2Api mm2Api, - required KomodoDefiSdk sdk, PerformanceMode? demoMode, }) { if (demoMode != null) { @@ -45,7 +43,6 @@ class PortfolioGrowthRepository { performanceMode: demoMode, coinsRepository: coinsRepository, mm2Api: mm2Api, - sdk: sdk, ); } @@ -96,7 +93,7 @@ class PortfolioGrowthRepository { /// /// Returns the growth [ChartData] for the coin ([List] of [Point]). Future getCoinGrowthChart( - String coinId, { + AssetId coinId, { // avoid the possibility of accidentally swapping the order of these // required parameters by using named parameters required String fiatCoinId, @@ -108,7 +105,7 @@ class PortfolioGrowthRepository { }) async { if (useCache) { final String compoundKey = GraphCache.getPrimaryKey( - coinId, + coinId.id, fiatCoinId, GraphType.balanceGrowth, walletId, @@ -124,9 +121,9 @@ class PortfolioGrowthRepository { // TODO: Refactor referenced coinsBloc method to a repository. // NB: Even though the class is called [CoinsBloc], it is not a Bloc. - final Coin coin = _coinsRepository.getCoin(coinId)!; + final Coin coin = _coinsRepository.getCoinFromId(coinId)!; final List transactions = await _transactionHistoryRepository - .fetchCompletedTransactions(coin) + .fetchCompletedTransactions(coin.id) .then((value) => value.toList()) .catchError((Object e) { if (ignoreTransactionFetchErrors) { @@ -142,7 +139,7 @@ class PortfolioGrowthRepository { // called later with useCache set to false to fetch the transactions again await _graphCache.insert( GraphCache( - coinId: coinId, + coinId: coinId.id, fiatCoinId: fiatCoinId, lastUpdated: DateTime.now(), graph: List.empty(), @@ -235,7 +232,7 @@ class PortfolioGrowthRepository { final chartDataFutures = coins.map((coin) async { try { return await getCoinGrowthChart( - coin.abbr, + coin.id, fiatCoinId: fiatCoinId, useCache: useCache, walletId: walletId, @@ -313,11 +310,11 @@ class PortfolioGrowthRepository { /// Returns `true` if the coin is supported by the CEX API for charting. /// Returns `false` if the coin is not supported by the CEX API for charting. Future isCoinChartSupported( - String coinId, + AssetId coinId, String fiatCoinId, { bool allowFiatAsBase = true, }) async { - final Coin coin = _coinsRepository.getCoin(coinId)!; + final Coin coin = _coinsRepository.getCoinFromId(coinId)!; final supportedCoins = await _cexRepository.getCoinList(); final coinTicker = coin.abbr.split('-').firstOrNull?.toUpperCase() ?? ''; diff --git a/lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart b/lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart index 84dc4bc4fa..ce46224f73 100644 --- a/lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart +++ b/lib/bloc/cex_market_data/price_chart/price_chart_bloc.dart @@ -37,7 +37,7 @@ class PriceChartBloc extends Bloc { // (e.g. Binance), some of which are not in our known/available // assets/coins list. This filter ensures that we only attempt to // fetch and display data for supported coins - .where((coin) => sdk.assets.assetsFromTicker(coin.id).length >= 1) + .where((coin) => sdk.assets.assetsFromTicker(coin.id).isNotEmpty) .map((coin) async { double? dayChangePercent = coinPrices[coin.symbol]?.change24h; diff --git a/lib/bloc/cex_market_data/profit_loss/demo_profit_loss_repository.dart b/lib/bloc/cex_market_data/profit_loss/demo_profit_loss_repository.dart index 4669f51feb..ba6af9ccb3 100644 --- a/lib/bloc/cex_market_data/profit_loss/demo_profit_loss_repository.dart +++ b/lib/bloc/cex_market_data/profit_loss/demo_profit_loss_repository.dart @@ -1,6 +1,5 @@ import 'package:http/http.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; -import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; import 'package:komodo_persistence_layer/komodo_persistence_layer.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/generator.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/mock_transaction_history_repository.dart'; @@ -27,7 +26,6 @@ class MockProfitLossRepository extends ProfitLossRepository { required PerformanceMode performanceMode, required CoinsRepo coinsRepository, required Mm2Api mm2Api, - required KomodoDefiSdk sdk, String cacheTableName = 'mock_profit_loss', }) { return MockProfitLossRepository( @@ -42,7 +40,6 @@ class MockProfitLossRepository extends ProfitLossRepository { client: Client(), performanceMode: performanceMode, demoDataGenerator: DemoDataCache.withDefaults(), - sdk: sdk, ), profitLossCalculator: RealisedProfitLossCalculator( BinanceRepository( diff --git a/lib/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart b/lib/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart index 6e41f3e126..f6b51274cc 100644 --- a/lib/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart +++ b/lib/bloc/cex_market_data/profit_loss/profit_loss_bloc.dart @@ -151,7 +151,7 @@ class ProfitLossBloc extends Bloc { final List coins = List.from(event.coins); for (final coin in event.coins) { final isCoinSupported = await _profitLossRepository.isCoinChartSupported( - coin.abbr, + coin.id, event.fiatCoinId, allowInactiveCoins: allowInactiveCoins, ); @@ -202,7 +202,7 @@ class ProfitLossBloc extends Bloc { // from breaking the entire portfolio chart. try { final profitLosses = await _profitLossRepository.getProfitLoss( - coin.abbr, + coin.id, event.fiatCoinId, event.walletId, useCache: useCache, diff --git a/lib/bloc/cex_market_data/profit_loss/profit_loss_repository.dart b/lib/bloc/cex_market_data/profit_loss/profit_loss_repository.dart index 7e63b92e8f..a574583f63 100644 --- a/lib/bloc/cex_market_data/profit_loss/profit_loss_repository.dart +++ b/lib/bloc/cex_market_data/profit_loss/profit_loss_repository.dart @@ -4,7 +4,7 @@ import 'dart:math'; import 'package:hive/hive.dart'; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart' as cex; import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'; -import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:komodo_persistence_layer/komodo_persistence_layer.dart'; import 'package:web_dex/bloc/cex_market_data/charts.dart'; import 'package:web_dex/bloc/cex_market_data/mockup/performance_mode.dart'; @@ -58,7 +58,6 @@ class ProfitLossRepository { required cex.CexRepository cexRepository, required CoinsRepo coinsRepository, required Mm2Api mm2Api, - required KomodoDefiSdk sdk, PerformanceMode? demoMode, }) { if (demoMode != null) { @@ -67,7 +66,6 @@ class ProfitLossRepository { coinsRepository: coinsRepository, cacheTableName: 'mock_${cacheTableName}_${demoMode.name}', mm2Api: mm2Api, - sdk: sdk, ); } @@ -92,23 +90,23 @@ class ProfitLossRepository { /// Returns `true` if the coin is supported by the CEX API for charting. /// Returns `false` if the coin is not supported by the CEX API for charting. Future isCoinChartSupported( - String coinId, + AssetId coinId, String fiatCoinId, { bool allowFiatAsBase = false, bool allowInactiveCoins = false, }) async { if (!allowInactiveCoins) { - final coin = await _coinsRepository.getEnabledCoin(coinId); + final coin = await _coinsRepository.getEnabledCoin(coinId.id); if (coin == null || coin.isActivating || !coin.isActive) { return false; } } final supportedCoins = await _cexRepository.getCoinList(); - final coinTicker = abbr2Ticker(coinId).toUpperCase(); + final coinTicker = abbr2Ticker(coinId.id).toUpperCase(); // Allow fiat coins through, as they are represented by a constant value, // 1, in the repository layer and are not supported by the CEX API - if (allowFiatAsBase && coinId == fiatCoinId.toUpperCase()) { + if (allowFiatAsBase && coinId.id == fiatCoinId.toUpperCase()) { return true; } @@ -132,14 +130,14 @@ class ProfitLossRepository { /// /// Returns the list of [ProfitLoss] for the coin. Future> getProfitLoss( - String coinId, + AssetId coinId, String fiatCoinId, String walletId, { bool useCache = true, }) async { if (useCache) { final String compoundKey = ProfitLossCache.getPrimaryKey( - coinId, + coinId.id, fiatCoinId, walletId, ); @@ -164,13 +162,13 @@ class ProfitLossRepository { await _transactionHistoryRepo.fetchCompletedTransactions( // TODO: Refactor referenced coinsBloc method to a repository. // NB: Even though the class is called [CoinsBloc], it is not a Bloc. - _coinsRepository.getCoin(coinId)!, + coinId, ); if (transactions.isEmpty) { await _profitLossCacheProvider.insert( ProfitLossCache( - coinId: coinId, + coinId: coinId.id, profitLosses: List.empty(), fiatCoinId: fiatCoinId, lastUpdated: DateTime.now(), @@ -183,13 +181,13 @@ class ProfitLossRepository { final List profitLosses = await _profitLossCalculator.getProfitFromTransactions( transactions, - coinId: coinId, + coinId: coinId.id, fiatCoinId: fiatCoinId, ); await _profitLossCacheProvider.insert( ProfitLossCache( - coinId: coinId, + coinId: coinId.id, profitLosses: profitLosses, fiatCoinId: fiatCoinId, lastUpdated: DateTime.now(), diff --git a/lib/bloc/coins_bloc/asset_coin_extension.dart b/lib/bloc/coins_bloc/asset_coin_extension.dart index 2b3fb45b16..3a5e4fec36 100644 --- a/lib/bloc/coins_bloc/asset_coin_extension.dart +++ b/lib/bloc/coins_bloc/asset_coin_extension.dart @@ -1,5 +1,5 @@ -import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/model/coin.dart'; import 'package:web_dex/model/coin_type.dart'; @@ -28,6 +28,7 @@ extension AssetCoinExtension on Asset { return Coin( type: type, abbr: id.id, + id: id, name: id.name, explorerUrl: config.valueOrNull('explorer_url') ?? '', explorerTxUrl: config.valueOrNull('explorer_tx_url') ?? '', @@ -94,3 +95,48 @@ extension AssetCoinExtension on Asset { } } } + +extension CoinSubClassExtension on CoinType { + CoinSubClass toCoinSubClass() { + switch (this) { + case CoinType.ftm20: + return CoinSubClass.ftm20; + case CoinType.arb20: + return CoinSubClass.arbitrum; + case CoinType.slp: + return CoinSubClass.slp; + case CoinType.qrc20: + return CoinSubClass.qrc20; + case CoinType.avx20: + return CoinSubClass.avx20; + case CoinType.smartChain: + return CoinSubClass.smartChain; + case CoinType.mvr20: + return CoinSubClass.moonriver; + case CoinType.etc: + return CoinSubClass.ethereumClassic; + case CoinType.hco20: + return CoinSubClass.hecoChain; + case CoinType.hrc20: + return CoinSubClass.hrc20; + case CoinType.iris: + return CoinSubClass.tendermintToken; + case CoinType.cosmos: + return CoinSubClass.tendermint; + case CoinType.ubiq: + return CoinSubClass.ubiq; + case CoinType.bep20: + return CoinSubClass.bep20; + case CoinType.plg20: + return CoinSubClass.matic; + case CoinType.utxo: + return CoinSubClass.utxo; + case CoinType.sbch: + return CoinSubClass.smartBch; + case CoinType.erc20: + return CoinSubClass.erc20; + case CoinType.krc20: + return CoinSubClass.krc20; + } + } +} diff --git a/lib/bloc/coins_bloc/coins_repo.dart b/lib/bloc/coins_bloc/coins_repo.dart index 568da5f34b..f8c1b25041 100644 --- a/lib/bloc/coins_bloc/coins_repo.dart +++ b/lib/bloc/coins_bloc/coins_repo.dart @@ -66,6 +66,8 @@ class CoinsRepo { } void flushCache() { + // Intentionally avoid flushing the prices cache - prices are independent + // of the user's session and should be updated on a regular basis. _addressCache.clear(); _balancesCache.clear(); } @@ -84,6 +86,15 @@ class CoinsRepo { ); } + Coin? getCoinFromId(AssetId id) { + final asset = _kdfSdk.assets.available[id]; + if (asset == null) return null; + return _assetToCoinWithoutAddress(asset); + } + + @Deprecated('Use KomodoDefiSdk assets or getCoinFromId instead. ' + 'This uses the deprecated assetsFromTicker method that uses a separate ' + 'cache that does not update with custom token activation.') Coin? getCoin(String coinId) { try { final asset = _kdfSdk.assets.assetsFromTicker(coinId).single; @@ -154,9 +165,14 @@ class CoinsRepo { Coin? parentCoin; if (asset.id.isChildAsset) { - final parentCoinId = asset.id.parentId!.id; - final parentAsset = _kdfSdk.assets.assetsFromTicker(parentCoinId).single; - parentCoin = _assetToCoinWithoutAddress(parentAsset); + final parentCoinId = asset.id.parentId!; + final parentAsset = _kdfSdk.assets.available[parentCoinId]; + if (parentAsset == null) { + log('Parent coin $parentCoinId not found.', isError: true).ignore(); + parentCoin = null; + } else { + parentCoin = _assetToCoinWithoutAddress(parentAsset); + } } return coin.copyWith( @@ -169,28 +185,18 @@ class CoinsRepo { /// Attempts to get the balance of a coin. If the coin is not found, it will /// return a zero balance. - Future tryGetBalanceInfo(String abbr) async { + Future tryGetBalanceInfo(AssetId coinId) async { try { - final assets = _kdfSdk.assets.findAssetsByTicker(abbr).nonNulls; - if (assets.isEmpty) { - throw Exception("Asset $abbr not found"); + final asset = _kdfSdk.assets.available[coinId]; + if (asset == null) { + throw ArgumentError.value(coinId, 'coinId', 'Coin $coinId not found'); } - if (assets.length == 1) { - final pubkeys = await _kdfSdk.pubkeys.getPubkeys(assets.single); - return pubkeys.balance; - } - - final balances = await Future.wait( - assets.map((asset) => _kdfSdk.pubkeys.getPubkeys(asset)), - ); - return balances.fold( - kdf_rpc.BalanceInfo.zero(), - (a, b) => a + b.balance, - ); + final pubkeys = await _kdfSdk.pubkeys.getPubkeys(asset); + return pubkeys.balance; } catch (e, s) { log( - 'Failed to get coin $abbr balance: $e', + 'Failed to get coin $coinId balance: $e', isError: true, path: 'coins_repo => tryGetBalanceInfo', trace: s, @@ -209,14 +215,24 @@ class CoinsRepo { continue; } - final asset = _kdfSdk.assets.findAssetsByTicker(coin.abbr).single; + final asset = _kdfSdk.assets.available[coin.id]; + if (asset == null) { + log( + 'Coin ${coin.id} not found. Skipping activation.', + isError: true, + ).ignore(); + continue; + } await _broadcastAsset(coin.copyWith(state: CoinState.activating)); if (coin.parentCoin != null) { await _activateParentAsset(coin); } // ignore: deprecated_member_use - await _kdfSdk.assets.activateAsset(asset).last; + final progress = await _kdfSdk.assets.activateAsset(asset).last; + if (!progress.isSuccess) { + throw StateError('Failed to activate coin ${coin.abbr}'); + } await _broadcastAsset(coin.copyWith(state: CoinState.active)); } catch (e, s) { @@ -231,12 +247,14 @@ class CoinsRepo { } Future _activateParentAsset(Coin coin) async { - final parentAsset = - _kdfSdk.assets.findAssetsByTicker(coin.parentCoin!.abbr).single; + final parentAsset = _kdfSdk.assets.available[coin.parentCoin!.id]; + if (parentAsset == null) { + throw ArgumentError('Parent asset ${coin.parentCoin!.id} not found'); + } + await _broadcastAsset( coin.parentCoin!.copyWith(state: CoinState.activating), ); - // ignore: deprecated_member_use await _kdfSdk.assets.activateAsset(parentAsset).last; await _broadcastAsset( coin.parentCoin!.copyWith(state: CoinState.active), @@ -418,8 +436,12 @@ class CoinsRepo { return prices; } - Future getBalanceInfo(String abbr) async { - final pubkeys = await getSdkAsset(_kdfSdk, abbr).getPubkeys(_kdfSdk); + Future getBalanceInfo(AssetId coinId) async { + final asset = _kdfSdk.assets.available[coinId]; + if (asset == null) { + throw ArgumentError.value(coinId, 'getBalanceInfo', 'Asset not found'); + } + final pubkeys = await _kdfSdk.pubkeys.getPubkeys(asset); return pubkeys.balance; } @@ -445,7 +467,7 @@ class CoinsRepo { walletCoinsCopy.values.where((coin) => coin.isActive).toList(); final newBalances = - await Future.wait(coins.map((coin) => tryGetBalanceInfo(coin.abbr))); + await Future.wait(coins.map((coin) => tryGetBalanceInfo(coin.id))); for (int i = 0; i < coins.length; i++) { final newBalance = newBalances[i].total.toDouble(); diff --git a/lib/bloc/coins_manager/coins_manager_bloc.dart b/lib/bloc/coins_manager/coins_manager_bloc.dart index d0584c8903..e6ea09035f 100644 --- a/lib/bloc/coins_manager/coins_manager_bloc.dart +++ b/lib/bloc/coins_manager/coins_manager_bloc.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart' show Bloc, Emitter; +import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; import 'package:web_dex/bloc/coins_bloc/coins_repo.dart'; -import 'package:web_dex/blocs/current_wallet_bloc.dart'; import 'package:web_dex/model/coin.dart'; import 'package:web_dex/model/coin_type.dart'; import 'package:web_dex/model/coin_utils.dart'; @@ -16,12 +16,12 @@ part 'coins_manager_state.dart'; class CoinsManagerBloc extends Bloc { CoinsManagerBloc({ required CoinsRepo coinsRepo, - required CoinsManagerAction action, - required CurrentWalletBloc currentWalletBloc, + required KomodoDefiSdk sdk, }) : _coinsRepo = coinsRepo, - _currentWalletBloc = currentWalletBloc, - super(CoinsManagerState.initial(action: action, coins: [])) { + _sdk = sdk, + super(CoinsManagerState.initial(coins: [])) { on(_onCoinsUpdate); + on(_onCoinsListReset); on(_onCoinTypeSelect); on(_onCoinsSwitch); on(_onCoinSelect); @@ -31,7 +31,7 @@ class CoinsManagerBloc extends Bloc { } final CoinsRepo _coinsRepo; - final CurrentWalletBloc _currentWalletBloc; + final KomodoDefiSdk _sdk; List mergeCoinLists(List originalList, List newList) { Map coinMap = {}; @@ -57,7 +57,7 @@ class CoinsManagerBloc extends Bloc { final List filters = []; List list = mergeCoinLists( - await _getOriginalCoinList(_coinsRepo, state.action, _currentWalletBloc), + await _getOriginalCoinList(_coinsRepo, event.action, _sdk), state.coins, ); @@ -72,7 +72,21 @@ class CoinsManagerBloc extends Bloc { list = filter(list); } - emit(state.copyWith(coins: list)); + emit(state.copyWith(coins: list, action: event.action)); + } + + Future _onCoinsListReset( + CoinsManagerCoinsListReset event, + Emitter emit, + ) async { + emit(CoinsManagerState.initial(coins: [], action: event.action)); + final List coins = await _getOriginalCoinList( + _coinsRepo, + event.action, + _sdk, + ) + ..sort((a, b) => a.abbr.compareTo(b.abbr)); + emit(state.copyWith(coins: coins, action: event.action)); } void _onCoinTypeSelect( @@ -85,7 +99,7 @@ class CoinsManagerBloc extends Bloc { emit(state.copyWith(selectedCoinTypes: newTypes)); - add(const CoinsManagerCoinsUpdate()); + add(CoinsManagerCoinsUpdate(state.action)); } Future _onCoinsSwitch( @@ -143,7 +157,7 @@ class CoinsManagerBloc extends Bloc { Emitter emit, ) { emit(state.copyWith(selectedCoinTypes: [])); - add(const CoinsManagerCoinsUpdate()); + add(CoinsManagerCoinsUpdate(state.action)); } FutureOr _onSearchUpdate( @@ -151,7 +165,7 @@ class CoinsManagerBloc extends Bloc { Emitter emit, ) { emit(state.copyWith(searchPhrase: event.text)); - add(const CoinsManagerCoinsUpdate()); + add(CoinsManagerCoinsUpdate(state.action)); } List _filterByPhrase(List coins) { @@ -191,34 +205,29 @@ class CoinsManagerBloc extends Bloc { Future> _getOriginalCoinList( CoinsRepo coinsRepo, CoinsManagerAction action, - CurrentWalletBloc currentWalletBloc, + KomodoDefiSdk sdk, ) async { - final WalletType? walletType = currentWalletBloc.wallet?.config.type; + final WalletType? walletType = (await sdk.currentWallet())?.config.type; if (walletType == null) return []; switch (action) { case CoinsManagerAction.add: - return await _getDeactivatedCoins(coinsRepo, walletType); + return await _getDeactivatedCoins(coinsRepo, sdk, walletType); case CoinsManagerAction.remove: - return await _getActivatedCoins(coinsRepo); + return await coinsRepo.getWalletCoins(); case CoinsManagerAction.none: return []; } } -Future> _getActivatedCoins(CoinsRepo coinsRepo) async { - return (await coinsRepo.getEnabledCoins()) - .where((coin) => !coin.isActivating) - .toList(); -} - Future> _getDeactivatedCoins( CoinsRepo coinsRepo, + KomodoDefiSdk sdk, WalletType walletType, ) async { - final Map enabledCoins = await coinsRepo.getEnabledCoinsMap(); - final Map disabledCoins = (coinsRepo.getKnownCoinsMap()) - ..removeWhere((key, coin) => enabledCoins.containsKey(key)); + final Iterable enabledCoins = await sdk.assets.getEnabledCoins(); + final Map disabledCoins = coinsRepo.getKnownCoinsMap() + ..removeWhere((key, coin) => enabledCoins.contains(key)); switch (walletType) { case WalletType.iguana: diff --git a/lib/bloc/coins_manager/coins_manager_event.dart b/lib/bloc/coins_manager/coins_manager_event.dart index dd6dd7275e..06275ebab6 100644 --- a/lib/bloc/coins_manager/coins_manager_event.dart +++ b/lib/bloc/coins_manager/coins_manager_event.dart @@ -4,8 +4,14 @@ abstract class CoinsManagerEvent { const CoinsManagerEvent(); } +class CoinsManagerCoinsListReset extends CoinsManagerEvent { + const CoinsManagerCoinsListReset(this.action); + final CoinsManagerAction action; +} + class CoinsManagerCoinsUpdate extends CoinsManagerEvent { - const CoinsManagerCoinsUpdate(); + const CoinsManagerCoinsUpdate(this.action); + final CoinsManagerAction action; } class CoinsManagerCoinTypeSelect extends CoinsManagerEvent { diff --git a/lib/bloc/coins_manager/coins_manager_state.dart b/lib/bloc/coins_manager/coins_manager_state.dart index 3296f85ffc..41202711f9 100644 --- a/lib/bloc/coins_manager/coins_manager_state.dart +++ b/lib/bloc/coins_manager/coins_manager_state.dart @@ -17,8 +17,8 @@ class CoinsManagerState extends Equatable { final bool isSwitching; static CoinsManagerState initial({ - required CoinsManagerAction action, required List coins, + CoinsManagerAction action = CoinsManagerAction.add, }) { return CoinsManagerState( action: action, diff --git a/lib/bloc/transaction_history/transaction_history_bloc.dart b/lib/bloc/transaction_history/transaction_history_bloc.dart index 072ece57d1..bd4441d1cd 100644 --- a/lib/bloc/transaction_history/transaction_history_bloc.dart +++ b/lib/bloc/transaction_history/transaction_history_bloc.dart @@ -4,10 +4,10 @@ import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/bloc/transaction_history/transaction_history_event.dart'; import 'package:web_dex/bloc/transaction_history/transaction_history_state.dart'; import 'package:web_dex/generated/codegen_loader.g.dart'; -import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/model/coin.dart'; import 'package:web_dex/model/text_error.dart'; import 'package:web_dex/shared/utils/utils.dart'; diff --git a/lib/bloc/transaction_history/transaction_history_repo.dart b/lib/bloc/transaction_history/transaction_history_repo.dart index 66e1f348f0..f8fe97ecb3 100644 --- a/lib/bloc/transaction_history/transaction_history_repo.dart +++ b/lib/bloc/transaction_history/transaction_history_repo.dart @@ -2,19 +2,29 @@ import 'dart:async'; import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; import 'package:komodo_defi_types/komodo_defi_types.dart'; -import 'package:web_dex/model/coin.dart'; -import 'package:web_dex/shared/utils/utils.dart'; -class TransactionHistoryRepo { - TransactionHistoryRepo({ +/// Throws [TransactionFetchException] if the transaction history could not be +/// fetched. +abstract class TransactionHistoryRepo { + Future?> fetch(AssetId assetId); + Future> fetchCompletedTransactions(AssetId assetId); +} + +class SdkTransactionHistoryRepository implements TransactionHistoryRepo { + SdkTransactionHistoryRepository({ required KomodoDefiSdk sdk, }) : _sdk = sdk; final KomodoDefiSdk _sdk; - Future?> fetch(Coin coin, [String? fromId]) async { - final asset = getSdkAsset(_sdk, coin.abbr); + @override + Future?> fetch(AssetId assetId, {String? fromId}) async { + final asset = _sdk.assets.available[assetId]; + if (asset == null) { + throw TransactionFetchException('Asset $assetId not found'); + } try { + final asset = _sdk.assets.available[assetId]!; final transactionHistory = await _sdk.transactions.getTransactionHistory( asset, pagination: fromId == null @@ -37,11 +47,10 @@ class TransactionHistoryRepo { /// Fetches transactions for the provided [coin] where the transaction /// timestamp is not 0 (transaction is completed and/or confirmed). - Future> fetchCompletedTransactions(Coin coin) async { - final List transactions = (await fetch(coin) ?? []) - ..sort( - (a, b) => a.timestamp.compareTo(b.timestamp), - ) + @override + Future> fetchCompletedTransactions(AssetId assetId) async { + final List transactions = (await fetch(assetId) ?? []) + ..sort((a, b) => a.timestamp.compareTo(b.timestamp)) ..removeWhere( (transaction) => transaction.timestamp == DateTime.fromMillisecondsSinceEpoch(0), diff --git a/lib/model/coin.dart b/lib/model/coin.dart index cd796c5438..f42b899c59 100644 --- a/lib/model/coin.dart +++ b/lib/model/coin.dart @@ -2,6 +2,7 @@ import 'package:collection/collection.dart'; import 'package:komodo_defi_sdk/komodo_defi_sdk.dart'; import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/app_config/app_config.dart'; +import 'package:web_dex/bloc/coins_bloc/asset_coin_extension.dart'; import 'package:web_dex/model/cex_price.dart'; import 'package:web_dex/model/coin_type.dart'; import 'package:web_dex/model/coin_utils.dart'; @@ -14,6 +15,7 @@ class Coin { Coin({ required this.type, required this.abbr, + required this.id, required this.name, required this.explorerUrl, required this.explorerTxUrl, @@ -42,6 +44,7 @@ class Coin { final String abbr; final String name; + final AssetId id; final String? coingeckoId; final String? coinpaprikaId; final CoinType type; @@ -212,6 +215,7 @@ class Coin { return Coin( type: type, abbr: abbr, + id: assetId, name: name, explorerUrl: explorerUrl, explorerTxUrl: explorerTxUrl, @@ -235,9 +239,23 @@ class Coin { ); } + AssetId get assetId => AssetId( + id: abbr, + name: name, + symbol: AssetSymbol( + assetConfigId: abbr, + coinGeckoId: coingeckoId, + coinPaprikaId: coinpaprikaId, + ), + chainId: AssetChainId(chainId: 0), + derivationPath: derivationPath ?? '', + subClass: type.toCoinSubClass(), + ); + Coin copyWith({ CoinType? type, String? abbr, + AssetId? id, String? name, String? explorerUrl, String? explorerTxUrl, @@ -267,6 +285,7 @@ class Coin { return Coin( type: type ?? this.type, abbr: abbr ?? this.abbr, + id: id ?? this.id, name: name ?? this.name, explorerUrl: explorerUrl ?? this.explorerUrl, explorerTxUrl: explorerTxUrl ?? this.explorerTxUrl, diff --git a/lib/views/wallet/coin_details/transactions/transaction_details.dart b/lib/views/wallet/coin_details/transactions/transaction_details.dart index 964f1a6a87..67a3709493 100644 --- a/lib/views/wallet/coin_details/transactions/transaction_details.dart +++ b/lib/views/wallet/coin_details/transactions/transaction_details.dart @@ -264,9 +264,7 @@ class TransactionDetails extends StatelessWidget { } Widget _buildFee(BuildContext context) { - final String? fee = transaction.fee?.formatTotal(); - final String formattedFee = - getNumberWithoutExponent(double.parse(fee ?? '').abs().toString()); + final String formattedFee = transaction.fee?.formatTotal() ?? ''; final coinsBloc = context.read(); final double? usd = coinsBloc.state.getUsdPriceByAmount(formattedFee, _feeCoin); diff --git a/lib/views/wallet/coins_manager/coins_manager_page.dart b/lib/views/wallet/coins_manager/coins_manager_page.dart index 78519be0b6..1c17d1a4a4 100644 --- a/lib/views/wallet/coins_manager/coins_manager_page.dart +++ b/lib/views/wallet/coins_manager/coins_manager_page.dart @@ -3,9 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:komodo_ui_kit/komodo_ui_kit.dart'; import 'package:web_dex/bloc/coins_bloc/coins_bloc.dart'; -import 'package:web_dex/bloc/coins_bloc/coins_repo.dart'; import 'package:web_dex/bloc/coins_manager/coins_manager_bloc.dart'; -import 'package:web_dex/blocs/current_wallet_bloc.dart'; import 'package:web_dex/generated/codegen_loader.g.dart'; import 'package:web_dex/router/state/wallet_state.dart'; import 'package:web_dex/views/common/page_header/page_header.dart'; @@ -24,8 +22,9 @@ class CoinsManagerPage extends StatelessWidget { @override Widget build(BuildContext context) { - assert(action == CoinsManagerAction.add || - action == CoinsManagerAction.remove); + assert( + action == CoinsManagerAction.add || action == CoinsManagerAction.remove, + ); final title = action == CoinsManagerAction.add ? LocaleKeys.addAssets.tr() @@ -39,9 +38,14 @@ class CoinsManagerPage extends StatelessWidget { ), content: Flexible( child: Padding( - padding: const EdgeInsets.only(top: 20.0), - child: - BlocBuilder(builder: (context, state) { + padding: const EdgeInsets.only(top: 20.0), + child: BlocConsumer( + listenWhen: (previous, current) => + previous.walletCoins != current.walletCoins, + listener: (context, state) => context + .read() + .add(CoinsManagerCoinsUpdate(action)), + builder: (context, state) { if (!state.loginActivationFinished) { return const Center( child: Padding( @@ -50,24 +54,10 @@ class CoinsManagerPage extends StatelessWidget { ), ); } - return BlocProvider( - key: Key('coins-manager-page-${action.toString()}'), - create: (context) => CoinsManagerBloc( - action: action, - coinsRepo: RepositoryProvider.of(context), - currentWalletBloc: - RepositoryProvider.of(context), - )..add(const CoinsManagerCoinsUpdate()), - child: BlocListener( - listenWhen: (previous, current) => - previous.walletCoins != current.walletCoins, - listener: (context, state) => context - .read() - .add(const CoinsManagerCoinsUpdate()), - child: const CoinsManagerListWrapper(), - ), - ); - })), + return const CoinsManagerListWrapper(); + }, + ), + ), ), ); } diff --git a/lib/views/wallet/wallet_page/wallet_main/wallet_manage_section.dart b/lib/views/wallet/wallet_page/wallet_main/wallet_manage_section.dart index 5eda95e631..3ac5fa0612 100644 --- a/lib/views/wallet/wallet_page/wallet_main/wallet_manage_section.dart +++ b/lib/views/wallet/wallet_page/wallet_main/wallet_manage_section.dart @@ -1,7 +1,9 @@ import 'package:app_theme/app_theme.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:komodo_ui_kit/komodo_ui_kit.dart'; +import 'package:web_dex/bloc/coins_manager/coins_manager_bloc.dart'; import 'package:web_dex/common/screen.dart'; import 'package:web_dex/generated/codegen_loader.g.dart'; import 'package:web_dex/model/authorize_mode.dart'; @@ -62,7 +64,7 @@ class WalletManageSection extends StatelessWidget { children: [ UiPrimaryButton( buttonKey: const Key('add-assets-button'), - onPressed: _onAddAssetsPress, + onPressed: () => _onAddAssetsPress(context), text: LocaleKeys.addAssets.tr(), height: 30.0, width: 110, @@ -77,7 +79,7 @@ class WalletManageSection extends StatelessWidget { padding: const EdgeInsets.only(left: 3.0), child: UiPrimaryButton( buttonKey: const Key('remove-assets-button'), - onPressed: _onRemoveAssetsPress, + onPressed: () => _onRemoveAssetsPress(context), text: LocaleKeys.removeAssets.tr(), height: 30.0, width: 125, @@ -147,7 +149,7 @@ class WalletManageSection extends StatelessWidget { children: [ UiPrimaryButton( buttonKey: const Key('add-assets-button'), - onPressed: _onAddAssetsPress, + onPressed: () => _onAddAssetsPress(context), text: LocaleKeys.addAssets.tr(), height: 25.0, width: 110, @@ -162,7 +164,7 @@ class WalletManageSection extends StatelessWidget { padding: const EdgeInsets.only(left: 3.0), child: UiPrimaryButton( buttonKey: const Key('remove-assets-button'), - onPressed: _onRemoveAssetsPress, + onPressed: () => _onRemoveAssetsPress(context), text: LocaleKeys.remove.tr(), height: 25.0, width: 80, @@ -199,11 +201,17 @@ class WalletManageSection extends StatelessWidget { ); } - void _onAddAssetsPress() { + void _onAddAssetsPress(BuildContext context) { + context + .read() + .add(const CoinsManagerCoinsListReset(CoinsManagerAction.add)); routingState.walletState.action = coinsManagerRouteAction.addAssets; } - void _onRemoveAssetsPress() { + void _onRemoveAssetsPress(BuildContext context) { + context + .read() + .add(const CoinsManagerCoinsListReset(CoinsManagerAction.remove)); routingState.walletState.action = coinsManagerRouteAction.removeAssets; } } diff --git a/packages/komodo_ui_kit/pubspec.lock b/packages/komodo_ui_kit/pubspec.lock index 13075d3978..f85054c62e 100644 --- a/packages/komodo_ui_kit/pubspec.lock +++ b/packages/komodo_ui_kit/pubspec.lock @@ -95,7 +95,7 @@ packages: description: path: "packages/komodo_defi_rpc_methods" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -104,7 +104,7 @@ packages: description: path: "packages/komodo_defi_types" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -113,7 +113,7 @@ packages: description: path: "packages/komodo_ui" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" diff --git a/pubspec.lock b/pubspec.lock index 326d373f46..55d0e46e29 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -666,7 +666,7 @@ packages: description: path: "packages/komodo_coins" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -675,7 +675,7 @@ packages: description: path: "packages/komodo_defi_framework" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0" @@ -684,7 +684,7 @@ packages: description: path: "packages/komodo_defi_local_auth" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -693,7 +693,7 @@ packages: description: path: "packages/komodo_defi_rpc_methods" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -702,7 +702,7 @@ packages: description: path: "packages/komodo_defi_sdk" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -711,7 +711,7 @@ packages: description: path: "packages/komodo_defi_types" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -727,7 +727,7 @@ packages: description: path: "packages/komodo_ui" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" @@ -743,7 +743,7 @@ packages: description: path: "packages/komodo_wallet_build_transformer" ref: dev - resolved-ref: afcdfd97b909b6f7cbd9f04c25f57a11031bcaf6 + resolved-ref: "204fdfe48ca06bbe61252eaaed5901aee8ec9a75" url: "https://github.com/KomodoPlatform/komodo-defi-sdk-flutter.git" source: git version: "0.2.0+0" diff --git a/test_units/tests/cex_market_data/generate_demo_data_test.dart b/test_units/tests/cex_market_data/generate_demo_data_test.dart index 47f92d01ae..386692f8ad 100644 --- a/test_units/tests/cex_market_data/generate_demo_data_test.dart +++ b/test_units/tests/cex_market_data/generate_demo_data_test.dart @@ -52,17 +52,19 @@ void testGenerateDemoData() { final goodTransactions = await generator.generateTransactions('BTC', PerformanceMode.good); final badTransactions = await generator.generateTransactions( - 'BTC', PerformanceMode.veryBad); + 'BTC', + PerformanceMode.veryBad, + ); double goodBalance = generator.initialBalance; double badBalance = generator.initialBalance; for (final tx in goodTransactions) { - goodBalance += double.parse(tx.myBalanceChange); + goodBalance += tx.balanceChanges.netChange.toDouble(); } for (final tx in badTransactions) { - badBalance += double.parse(tx.myBalanceChange); + badBalance += tx.balanceChanges.netChange.toDouble(); } expect(goodBalance, greaterThan(badBalance)); @@ -70,18 +72,17 @@ void testGenerateDemoData() { test('generateTransactions produces valid transaction objects', () async { final transactions = await generator.generateTransactions( - 'BTC', PerformanceMode.mediocre); + 'BTC', + PerformanceMode.mediocre, + ); for (final tx in transactions) { - expect(tx.coin, equals('BTC')); + expect(tx.assetId.id, equals('BTC')); expect(tx.confirmations, inInclusiveRange(1, 3)); - expect(tx.feeDetails.coin, equals('USDT')); expect(tx.from, isNotEmpty); expect(tx.to, isNotEmpty); expect(tx.internalId, isNotEmpty); expect(tx.txHash, isNotEmpty); - expect(double.tryParse(tx.myBalanceChange), isNotNull); - expect(double.tryParse(tx.totalAmount), isNotNull); } }); diff --git a/test_units/tests/utils/test_util.dart b/test_units/tests/utils/test_util.dart index f5d8a7f130..117f87dde2 100644 --- a/test_units/tests/utils/test_util.dart +++ b/test_units/tests/utils/test_util.dart @@ -1,11 +1,29 @@ +import 'package:komodo_defi_types/komodo_defi_types.dart'; import 'package:web_dex/model/cex_price.dart'; import 'package:web_dex/model/coin.dart'; import 'package:web_dex/model/coin_type.dart'; -Coin setCoin( - {double? usdPrice, double? change24h, String? coinAbbr, double? balance}) { +Coin setCoin({ + double? usdPrice, + double? change24h, + String? coinAbbr, + double? balance, +}) { return Coin( abbr: coinAbbr ?? 'KMD', + id: AssetId( + id: coinAbbr ?? 'KMD', + name: 'Komodo', + parentId: null, + symbol: AssetSymbol( + assetConfigId: coinAbbr ?? 'KMD', + coinGeckoId: 'komodo', + coinPaprikaId: 'kmd-komodo', + ), + derivationPath: "m/44'/141'/0'", + chainId: AssetChainId(chainId: 0), + subClass: CoinSubClass.smartChain, + ), accounts: null, activeByDefault: true, coingeckoId: "komodo",