Skip to content

Commit f176228

Browse files
committed
Merge branch 'dev' into feat/trezor-sdk-migration
2 parents 3d5bf12 + 923e87c commit f176228

File tree

47 files changed

+217
-694
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+217
-694
lines changed

lib/bloc/app_bloc_root.dart

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
88
import 'package:get_it/get_it.dart';
99
import 'package:komodo_cex_market_data/komodo_cex_market_data.dart';
1010
import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
11-
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
11+
import 'package:komodo_ui/komodo_ui.dart';
1212
import 'package:shared_preferences/shared_preferences.dart';
1313
import 'package:universal_html/html.dart' as html;
1414
import 'package:web_dex/app_config/app_config.dart';
@@ -65,7 +65,6 @@ import 'package:web_dex/router/state/routing_state.dart';
6565
import 'package:web_dex/services/orders_service/my_orders_service.dart';
6666
import 'package:web_dex/shared/utils/debug_utils.dart';
6767
import 'package:web_dex/shared/utils/utils.dart';
68-
import 'package:web_dex/shared/widgets/coin_icon.dart';
6968

7069
class AppBlocRoot extends StatelessWidget {
7170
const AppBlocRoot({
@@ -354,8 +353,8 @@ class _MyAppViewState extends State<_MyAppView> {
354353
void didChangeDependencies() {
355354
super.didChangeDependencies();
356355

357-
final coinsRepository = RepositoryProvider.of<CoinsRepo>(context);
358-
_precacheCoinIcons(coinsRepository).ignore();
356+
final sdk = RepositoryProvider.of<KomodoDefiSdk>(context);
357+
_precacheCoinIcons(sdk).ignore();
359358
}
360359

361360
/// Hides the native app launch loader. Currently only implemented for web.
@@ -392,7 +391,7 @@ class _MyAppViewState extends State<_MyAppView> {
392391

393392
Completer<void>? _currentPrecacheOperation;
394393

395-
Future<void> _precacheCoinIcons(CoinsRepo coinsRepo) async {
394+
Future<void> _precacheCoinIcons(KomodoDefiSdk sdk) async {
396395
if (_currentPrecacheOperation != null &&
397396
!_currentPrecacheOperation!.isCompleted) {
398397
// completeError throws an uncaught exception, which causes the UI
@@ -405,10 +404,9 @@ class _MyAppViewState extends State<_MyAppView> {
405404

406405
try {
407406
final stopwatch = Stopwatch()..start();
408-
final coins =
409-
coinsRepo.getKnownCoinsMap(excludeExcludedAssets: true).keys;
407+
final availableAssetIds = sdk.assets.available.keys;
410408

411-
await for (final abbr in Stream.fromIterable(coins)) {
409+
await for (final assetId in Stream.fromIterable(availableAssetIds)) {
412410
// TODO: Test if necessary to complete prematurely with error if build
413411
// context is stale. Alternatively, we can check if the context is
414412
// not mounted and return early with error.
@@ -419,17 +417,18 @@ class _MyAppViewState extends State<_MyAppView> {
419417
// }
420418

421419
// ignore: use_build_context_synchronously
422-
await CoinIcon.precacheCoinIcon(context, abbr)
423-
.onError((_, __) => debugPrint('Error precaching coin icon $abbr'));
420+
await AssetIcon.precacheAssetIcon(context, assetId).onError(
421+
(_, __) => debugPrint('Error precaching coin icon $assetId'));
424422
}
425423

426424
_currentPrecacheOperation!.complete();
427425

426+
if (!mounted) return;
428427
context.read<AnalyticsBloc>().logEvent(
429428
CoinsDataUpdatedEventData(
430429
updateSource: 'remote',
431430
updateDurationMs: stopwatch.elapsedMilliseconds,
432-
coinsCount: coins.length,
431+
coinsCount: availableAssetIds.length,
433432
),
434433
);
435434
} catch (e) {

lib/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,31 @@ class PortfolioGrowthBloc
5151
PortfolioGrowthPeriodChanged event,
5252
Emitter<PortfolioGrowthState> emit,
5353
) {
54-
if (state is! PortfolioGrowthChartLoadSuccess) {
54+
final currentState = state;
55+
if (currentState is PortfolioGrowthChartLoadSuccess) {
56+
emit(
57+
PortfolioGrowthChartLoadSuccess(
58+
portfolioGrowth: currentState.portfolioGrowth,
59+
percentageIncrease: currentState.percentageIncrease,
60+
selectedPeriod: event.selectedPeriod,
61+
totalBalance: currentState.totalBalance,
62+
totalChange24h: currentState.totalChange24h,
63+
percentageChange24h: currentState.percentageChange24h,
64+
),
65+
);
66+
} else if (currentState is GrowthChartLoadFailure) {
5567
emit(
5668
GrowthChartLoadFailure(
57-
error: (state as GrowthChartLoadFailure).error,
69+
error: currentState.error,
5870
selectedPeriod: event.selectedPeriod,
5971
),
6072
);
73+
} else if (currentState is PortfolioGrowthChartUnsupported) {
74+
emit(
75+
PortfolioGrowthChartUnsupported(selectedPeriod: event.selectedPeriod),
76+
);
77+
} else {
78+
emit(const PortfolioGrowthInitial());
6179
}
6280

6381
add(
@@ -85,9 +103,11 @@ class PortfolioGrowthBloc
85103
);
86104
}
87105

88-
await _loadChart(coins, event, useCache: true)
89-
.then(emit.call)
90-
.catchError((Object error, StackTrace stackTrace) {
106+
await _loadChart(
107+
coins,
108+
event,
109+
useCache: true,
110+
).then(emit.call).catchError((Object error, StackTrace stackTrace) {
91111
const errorMessage = 'Failed to load cached chart';
92112
_log.warning(errorMessage, error, stackTrace);
93113
// ignore cached errors, as the periodic refresh attempts should recover
@@ -103,9 +123,11 @@ class PortfolioGrowthBloc
103123
// cached chart, as the cached chart may contain inactive coins.
104124
final activeCoins = await _removeInactiveCoins(coins);
105125
if (activeCoins.isNotEmpty) {
106-
await _loadChart(activeCoins, event, useCache: false)
107-
.then(emit.call)
108-
.catchError((Object error, StackTrace stackTrace) {
126+
await _loadChart(
127+
activeCoins,
128+
event,
129+
useCache: false,
130+
).then(emit.call).catchError((Object error, StackTrace stackTrace) {
109131
_log.shout('Failed to load chart', error, stackTrace);
110132
// Don't emit an error state here. If cached and uncached attempts
111133
// both fail, the periodic refresh attempts should recovery
@@ -260,18 +282,16 @@ class PortfolioGrowthBloc
260282
double _calculateTotalChange24h(List<Coin> coins) {
261283
// Calculate the 24h change by summing the change percentage of each coin
262284
// multiplied by its USD balance and divided by 100 (to convert percentage to decimal)
263-
return coins.fold(
264-
0.0,
265-
(sum, coin) {
266-
// Use the price change from the CexPrice if available
267-
final usdBalance = coin.lastKnownUsdBalance(sdk) ?? 0.0;
268-
// Get the coin price from the repository's prices cache
269-
final price = portfolioGrowthRepository
270-
.getCachedPrice(coin.id.symbol.configSymbol.toUpperCase());
271-
final change24h = price?.change24h ?? 0.0;
272-
return sum + (change24h * usdBalance / 100);
273-
},
274-
);
285+
return coins.fold(0.0, (sum, coin) {
286+
// Use the price change from the CexPrice if available
287+
final usdBalance = coin.lastKnownUsdBalance(sdk) ?? 0.0;
288+
// Get the coin price from the repository's prices cache
289+
final price = portfolioGrowthRepository.getCachedPrice(
290+
coin.id.symbol.configSymbol.toUpperCase(),
291+
);
292+
final change24h = price?.change24h ?? 0.0;
293+
return sum + (change24h * usdBalance / 100);
294+
});
275295
}
276296

277297
/// Calculate the percentage change over 24h for the entire portfolio

lib/bloc/coins_bloc/asset_coin_extension.dart

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
77

88
extension AssetCoinExtension on Asset {
99
Coin toCoin() {
10-
final CoinType type = protocol.subClass.toCoinType();
1110
// temporary measure to get metadata, like `wallet_only`, that isn't exposed
1211
// by the SDK (and might be phased out completely later on)
1312
// TODO: Remove this once the SDK exposes all the necessary metadata
@@ -16,17 +15,14 @@ extension AssetCoinExtension on Asset {
1615
final isCustomToken =
1716
(config.valueOrNull<bool>('is_custom_token') ?? false) ||
1817
logoImageUrl != null;
19-
// TODO: Remove this once the SDK exposes all the necessary metadata
20-
// This is the logic from the previous _getCoinMode function
21-
final isSegwit = id.id.toLowerCase().contains('-segwit');
2218

2319
final ProtocolData protocolData = ProtocolData(
2420
platform: id.parentId?.id ?? platform ?? '',
2521
contractAddress: contractAddress ?? '',
2622
);
2723

2824
return Coin(
29-
type: type,
25+
type: protocol.subClass.toCoinType(),
3026
abbr: id.id,
3127
id: id,
3228
name: id.name,
@@ -46,7 +42,7 @@ extension AssetCoinExtension on Asset {
4642
priority: 0,
4743
state: CoinState.inactive,
4844
walletOnly: config.valueOrNull<bool>('wallet_only') ?? false,
49-
mode: isSegwit ? CoinMode.segwit : CoinMode.standard,
45+
mode: id.isSegwit ? CoinMode.segwit : CoinMode.standard,
5046
derivationPath: id.derivationPath,
5147
);
5248
}
@@ -80,10 +76,10 @@ extension CoinTypeExtension on CoinSubClass {
8076
return CoinType.hco20;
8177
case CoinSubClass.hrc20:
8278
return CoinType.hrc20;
83-
case CoinSubClass.tendermintToken:
84-
return CoinType.iris;
8579
case CoinSubClass.tendermint:
86-
return CoinType.cosmos;
80+
return CoinType.tendermint;
81+
case CoinSubClass.tendermintToken:
82+
return CoinType.tendermintToken;
8783
case CoinSubClass.ubiq:
8884
return CoinType.ubiq;
8985
case CoinSubClass.bep20:
@@ -150,10 +146,10 @@ extension CoinSubClassExtension on CoinType {
150146
return CoinSubClass.hecoChain;
151147
case CoinType.hrc20:
152148
return CoinSubClass.hrc20;
153-
case CoinType.iris:
154-
return CoinSubClass.tendermintToken;
155-
case CoinType.cosmos:
149+
case CoinType.tendermint:
156150
return CoinSubClass.tendermint;
151+
case CoinType.tendermintToken:
152+
return CoinSubClass.tendermintToken;
157153
case CoinType.ubiq:
158154
return CoinSubClass.ubiq;
159155
case CoinType.bep20:

lib/bloc/coins_bloc/coins_repo.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'
99
import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
1010
import 'package:komodo_defi_types/komodo_defi_type_utils.dart';
1111
import 'package:komodo_defi_types/komodo_defi_types.dart';
12-
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
12+
import 'package:komodo_ui/komodo_ui.dart';
1313
import 'package:logging/logging.dart';
1414
import 'package:web_dex/app_config/app_config.dart' show excludedAssetList;
1515
import 'package:web_dex/bloc/coins_bloc/asset_coin_extension.dart';
@@ -315,8 +315,8 @@ class CoinsRepo {
315315
// Register outside of the try-catch to ensure icon is available even
316316
// in a suspended or failing activation status.
317317
if (coin.logoImageUrl?.isNotEmpty == true) {
318-
CoinIcon.registerCustomIcon(
319-
coin.id.id,
318+
AssetIcon.registerCustomIcon(
319+
coin.id,
320320
NetworkImage(coin.logoImageUrl!),
321321
);
322322
}
@@ -361,8 +361,8 @@ class CoinsRepo {
361361
// Register outside of the try-catch to ensure icon is available even
362362
// in a suspended or failing activation status.
363363
if (coin.logoImageUrl?.isNotEmpty == true) {
364-
CoinIcon.registerCustomIcon(
365-
coin.id.id,
364+
AssetIcon.registerCustomIcon(
365+
coin.id,
366366
NetworkImage(coin.logoImageUrl!),
367367
);
368368
}

lib/bloc/custom_token_import/data/custom_token_import_repository.dart

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import 'package:http/http.dart' as http;
55
import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
66
import 'package:komodo_defi_types/komodo_defi_type_utils.dart';
77
import 'package:komodo_defi_types/komodo_defi_types.dart';
8+
import 'package:komodo_ui/komodo_ui.dart';
89
import 'package:web_dex/bloc/coins_bloc/asset_coin_extension.dart';
910
import 'package:web_dex/bloc/coins_bloc/coins_repo.dart';
1011
import 'package:web_dex/shared/utils/utils.dart';
11-
import 'package:web_dex/shared/widgets/coin_icon.dart';
1212

1313
abstract class ICustomTokenImportRepository {
1414
Future<Asset> fetchCustomToken(CoinSubClass network, String address);
@@ -107,8 +107,8 @@ class KdfCustomTokenImportRepository implements ICustomTokenImportRepository {
107107
}).copyWith(isCustomToken: true),
108108
);
109109

110-
CoinIcon.registerCustomIcon(
111-
newCoin.id.id,
110+
AssetIcon.registerCustomIcon(
111+
newCoin.id,
112112
NetworkImage(
113113
tokenApi?['image']?['large'] ??
114114
'assets/coin_icons/png/${ticker.toLowerCase()}.png',
@@ -143,7 +143,7 @@ class KdfCustomTokenImportRepository implements ICustomTokenImportRepository {
143143
final data = jsonDecode(response.body);
144144
return data;
145145
} catch (e) {
146-
log('Error fetching token image URL: $e');
146+
log('Error fetching token data from $url: $e');
147147
return null;
148148
}
149149
}
@@ -155,27 +155,27 @@ class KdfCustomTokenImportRepository implements ICustomTokenImportRepository {
155155
String? getNetworkApiName(CoinSubClass coinType) {
156156
switch (coinType) {
157157
case CoinSubClass.erc20:
158-
return 'ethereum';
158+
return 'ethereum'; // https://api.coingecko.com/api/v3/coins/ethereum/contract/0x56072C95FAA701256059aa122697B133aDEd9279
159159
case CoinSubClass.bep20:
160-
return 'binance-smart-chain';
161-
case CoinSubClass.qrc20:
162-
return 'qtum';
163-
case CoinSubClass.ftm20:
164-
return 'fantom';
160+
return 'bsc'; // https://api.coingecko.com/api/v3/coins/bsc/contract/0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
165161
case CoinSubClass.arbitrum:
166-
return 'arbitrum-one';
162+
return 'arbitrum-one'; // https://api.coingecko.com/api/v3/coins/arbitrum-one/contract/0xCBeb19549054CC0a6257A77736FC78C367216cE7
167163
case CoinSubClass.avx20:
168-
return 'avalanche';
164+
return 'avalanche'; // https://api.coingecko.com/api/v3/coins/avalanche/contract/0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E
169165
case CoinSubClass.moonriver:
170-
return 'moonriver';
171-
case CoinSubClass.hecoChain:
172-
return 'huobi-token';
166+
return 'moonriver'; // https://api.coingecko.com/api/v3/coins/moonriver/contract/0x0caE51e1032e8461f4806e26332c030E34De3aDb
173167
case CoinSubClass.matic:
174-
return 'polygon-pos';
175-
case CoinSubClass.hrc20:
176-
return 'harmony-shard-0';
168+
return 'polygon-pos'; // https://api.coingecko.com/api/v3/coins/polygon-pos/contract/0xdF7837DE1F2Fa4631D716CF2502f8b230F1dcc32
177169
case CoinSubClass.krc20:
178-
return 'kcc';
170+
return 'kcc'; // https://api.coingecko.com/api/v3/coins/kcc/contract/0x0039f574ee5cc39bdd162e9a88e3eb1f111baf48
171+
case CoinSubClass.qrc20:
172+
return null; // Unable to find working url
173+
case CoinSubClass.ftm20:
174+
return null; // Unable to find working url
175+
case CoinSubClass.hecoChain:
176+
return null; // Unable to find working url
177+
case CoinSubClass.hrc20:
178+
return null; // Unable to find working url
179179
default:
180180
return null;
181181
}

lib/bloc/fiat/base_fiat_provider.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ abstract class BaseFiatProvider {
118118
return 'ETH';
119119
case CoinType.bep20:
120120
return 'BSC'; // It is BNB for some providers like Banxa
121-
case CoinType.cosmos:
121+
case CoinType.tendermint:
122122
return 'ATOM';
123123
case CoinType.avx20:
124124
return 'AVAX';
@@ -228,7 +228,7 @@ abstract class BaseFiatProvider {
228228
case 'BNB':
229229
return CoinType.bep20;
230230
case 'ATOM':
231-
return CoinType.cosmos;
231+
return CoinType.tendermint;
232232
case 'AVAX':
233233
return CoinType.avx20;
234234
case 'ETC':

lib/bloc/fiat/models/i_currency.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class CryptoCurrency extends ICurrency {
129129
// "ETH-ERC20", which is not how it is stored in our coins configuration
130130
// files. "ETH" is the expected abbreviation, which would just be `symbol`.
131131
if (chainType == CoinType.utxo ||
132-
(chainType == CoinType.cosmos && symbol == 'ATOM') ||
132+
(chainType == CoinType.tendermint && symbol == 'ATOM') ||
133133
(chainType == CoinType.erc20 && symbol == 'ETH') ||
134134
(chainType == CoinType.bep20 && symbol == 'BNB') ||
135135
(chainType == CoinType.avx20 && symbol == 'AVAX') ||

lib/model/coin.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class Coin {
107107
bool get isErcType => protocolType == 'ERC20' || protocolType == 'ETH';
108108

109109
bool get isTxMemoSupported =>
110-
type == CoinType.iris || type == CoinType.cosmos;
110+
type == CoinType.tendermint || type == CoinType.tendermintToken;
111111

112112
@Deprecated(
113113
'TODO: Adapt SDK to cater for this use case and remove this method.')
@@ -121,7 +121,7 @@ class Coin {
121121
}
122122

123123
bool get isCustomFeeSupported {
124-
return type != CoinType.iris && type != CoinType.cosmos;
124+
return type != CoinType.tendermintToken && type != CoinType.tendermint;
125125
}
126126

127127
bool get hasFaucet => coinsWithFaucet.contains(abbr);

lib/model/coin_type.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ enum CoinType {
1616
sbch,
1717
ubiq,
1818
krc20,
19-
cosmos,
20-
iris,
19+
tendermintToken,
20+
tendermint,
2121
slp,
2222
}

0 commit comments

Comments
 (0)