Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions lib/bloc/coins_bloc/coins_repo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import 'package:web_dex/mm2/mm2_api/rpc/withdraw/withdraw_request.dart';
import 'package:web_dex/model/cex_price.dart';
import 'package:web_dex/model/coin.dart';
import 'package:web_dex/model/kdf_auth_metadata_extension.dart';
import 'package:web_dex/model/wallet.dart';
import 'package:web_dex/model/text_error.dart';
import 'package:web_dex/model/withdraw_details/withdraw_details.dart';
import 'package:web_dex/services/arrr_activation/arrr_activation_service.dart';
Expand Down Expand Up @@ -67,6 +68,8 @@ class CoinsRepo {
final ArrrActivationService _arrrActivationService;

final _log = Logger('CoinsRepo');
static const _unsupportedTrezorSiaMessage =
'SIA is not supported for Trezor wallets in this release.';

/// { acc: { abbr: address }}, used in Fiat Page
final Map<String, Map<String, String>> _addressCache = {};
Expand Down Expand Up @@ -383,6 +386,31 @@ class CoinsRepo {
return;
}

final walletType = (await _kdfSdk.currentWallet())?.config.type;
if (walletType == WalletType.trezor) {
final unsupportedSiaAssets =
assets.where((asset) => asset.id.subClass == CoinSubClass.sia);
if (unsupportedSiaAssets.isNotEmpty) {
_log.warning(
'Skipping unsupported Trezor SIA activation for '
'${unsupportedSiaAssets.map((a) => a.id.id).join(', ')}: '
'$_unsupportedTrezorSiaMessage',
);
for (final siaAsset in unsupportedSiaAssets) {
_broadcastAsset(
_assetToCoinWithoutAddress(siaAsset)
.copyWith(state: CoinState.suspended),
);
}
}
assets = assets
.where((asset) => asset.id.subClass != CoinSubClass.sia)
.toList();
if (assets.isEmpty) {
return;
Comment on lines +406 to +410
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return an error for unsupported Trezor SIA activation

When the requested set is only SIA assets on a Trezor, activateAssetsSync() now filters them out and returns successfully. Callers such as activateCoinIfNeeded() in lib/views/dex/dex_helpers.dart:226-255 only surface a guardrail from the catch path, and that helper is reused by maker/taker/bridge/NFT entry points, so those flows will still let a Trezor user pick SIA and continue with an inactive coin instead of showing the intended unsupported-asset message.

Useful? React with 👍 / 👎.

Comment on lines +406 to +410
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Emit a state change when Trezor SIA activation is skipped

If a Trezor wallet already has SIA in activated_coins from an older build, CoinsBloc._onLogin() still pre-populates that asset as CoinState.activating and waits for activation updates (lib/bloc/coins_bloc/coins_bloc.dart:381-392 and :597-615). The new early return here drops the request without broadcasting anything back through enabledAssetsChanges, so the SIA entry never gets removed from walletCoins and remains stuck as an "activating" asset for the rest of the session; it can also keep the initial 80% activation threshold from being reached until the one-minute timeout.

Useful? React with 👍 / 👎.

}
}

// Debug logging for activation
if (kDebugElectrumLogs) {
final coinIdList = assets.map((e) => e.id.id).join(', ');
Expand Down
76 changes: 55 additions & 21 deletions lib/bloc/coins_manager/coins_manager_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:web_dex/bloc/settings/settings_repository.dart';
import 'package:web_dex/blocs/trading_entities_bloc.dart';
import 'package:web_dex/model/coin.dart';
import 'package:web_dex/model/coin_utils.dart';
import 'package:web_dex/model/wallet.dart';
import 'package:web_dex/shared/utils/extensions/kdf_user_extensions.dart';
import 'package:web_dex/router/state/wallet_state.dart';
import 'package:web_dex/views/wallet/coins_manager/coins_manager_helpers.dart';
Expand Down Expand Up @@ -68,13 +69,17 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
) async {
final List<FilterFunction> filters = [];

final mergedCoinsList = _mergeCoinLists(
final originalCoins = await _filterUnsupportedHardwareCoins(
await _getOriginalCoinList(
_coinsRepo,
event.action,
cachedKnownCoinsMap: _cachedKnownCoinsMap,
cachedWalletCoins: _cachedWalletCoins,
),
event.action,
);
final mergedCoinsList = _mergeCoinLists(
originalCoins,
state.coins,
).toList();

Expand All @@ -86,8 +91,15 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
state.selectedCoins,
event.action,
);
final visibleSelectedCoins = await _filterUnsupportedHardwareCoins(
selectedCoins,
event.action,
);

final uniqueCombinedList = <Coin>{...mergedCoinsList, ...selectedCoins};
final uniqueCombinedList = <Coin>{
...mergedCoinsList,
...visibleSelectedCoins,
};

final testFilteredCoins = await _filterTestCoinsIfNeeded(
uniqueCombinedList.toList(),
Expand All @@ -111,7 +123,7 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
state.copyWith(
coins: sortedCoins.unique((coin) => coin.id),
action: event.action,
selectedCoins: selectedCoins,
selectedCoins: visibleSelectedCoins,
),
);
}
Expand Down Expand Up @@ -147,11 +159,14 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
_cachedTestCoinsEnabled =
(await _settingsRepository.loadSettings()).testCoinsEnabled;

final List<Coin> coins = await _getOriginalCoinList(
_coinsRepo,
final List<Coin> coins = await _filterUnsupportedHardwareCoins(
await _getOriginalCoinList(
_coinsRepo,
event.action,
cachedKnownCoinsMap: _cachedKnownCoinsMap,
cachedWalletCoins: _cachedWalletCoins,
),
event.action,
cachedKnownCoinsMap: _cachedKnownCoinsMap,
cachedWalletCoins: _cachedWalletCoins,
);

// Add wallet coins to selected coins if in add mode so that they
Expand All @@ -164,17 +179,21 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
: <Coin>[],
event.action,
);
final visibleSelectedCoins = await _filterUnsupportedHardwareCoins(
selectedCoins,
event.action,
);
Comment on lines +182 to +185
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep active Trezor SIA coins visible in add-assets

This second filter removes wallet-owned SIA coins from selectedCoins immediately after _mergeWalletCoinsIfNeeded() re-added them. In this app, add-assets is the only reachable coin-management UI I could find (main_layout.dart:178-183, wallet_manage_section.dart:117-121, while CoinsManagerSwitchButton is unused), so any Trezor wallet that already has SIA in metadata from earlier dev builds will have those assets disappear from the list and lose its only in-app way to deselect/deactivate them.

Useful? React with 👍 / 👎.


final filteredCoins = await _filterTestCoinsIfNeeded(
{...coins, ...selectedCoins}.toList(),
{...coins, ...visibleSelectedCoins}.toList(),
);
final sortedCoins = _sortCoins(filteredCoins, event.action, state.sortData);

emit(
state.copyWith(
coins: sortedCoins.unique((coin) => coin.id),
action: event.action,
selectedCoins: selectedCoins,
selectedCoins: visibleSelectedCoins,
),
);
}
Expand All @@ -185,9 +204,7 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
) {
final List<CoinSubClass> newTypes =
state.selectedCoinTypes.contains(event.type)
? state.selectedCoinTypes
.where((type) => type != event.type)
.toList()
? state.selectedCoinTypes.where((type) => type != event.type).toList()
: [...state.selectedCoinTypes, event.type];

emit(state.copyWith(selectedCoinTypes: newTypes));
Expand Down Expand Up @@ -249,10 +266,12 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
} on ZhtlcActivationCancelled {
// Revert optimistic selection and show a friendly message
selectedCoins.remove(coin);
emit(state.copyWith(
selectedCoins: selectedCoins.toList(),
errorMessage: 'Activation canceled.',
));
emit(
state.copyWith(
selectedCoins: selectedCoins.toList(),
errorMessage: 'Activation canceled.',
),
);
return;
}
} else {
Expand Down Expand Up @@ -358,12 +377,26 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {

List<Coin> _filterByType(List<Coin> coins) {
return coins
.where(
(coin) => state.selectedCoinTypes.contains(coin.id.subClass),
)
.where((coin) => state.selectedCoinTypes.contains(coin.id.subClass))
.toList();
}

Future<List<Coin>> _filterUnsupportedHardwareCoins(
List<Coin> coins,
CoinsManagerAction action,
) async {
if (action != CoinsManagerAction.add) {
return coins;
}

final currentWalletType = (await _sdk.auth.currentUser)?.wallet.config.type;
if (currentWalletType != WalletType.trezor) {
return coins;
}

return coins.where((coin) => coin.id.subClass != CoinSubClass.sia).toList();
}

/// Merges wallet coins into selected coins list when in add mode
Future<List<Coin>> _mergeWalletCoinsIfNeeded(
List<Coin> selectedCoins,
Expand All @@ -383,8 +416,9 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
// This ensures toggles remain OFF if auto-activation was bypassed.
if (walletCoin.id.subClass == CoinSubClass.zhtlc) {
try {
final saved =
await _sdk.activationConfigService.getSavedZhtlc(walletCoin.id);
final saved = await _sdk.activationConfigService.getSavedZhtlc(
walletCoin.id,
);
if (saved == null) {
continue;
}
Expand Down
27 changes: 27 additions & 0 deletions lib/bloc/withdraw_form/withdraw_form_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import 'package:decimal/decimal.dart';

class WithdrawFormBloc extends Bloc<WithdrawFormEvent, WithdrawFormState> {
static final Logger _logger = Logger('WithdrawFormBloc');
static const _unsupportedSiaHardwareWalletMessage =
'SIA is not supported for hardware wallets in this release.';
final KomodoDefiSdk _sdk;
final WalletType? _walletType;

Expand Down Expand Up @@ -589,6 +591,17 @@ class WithdrawFormBloc extends Bloc<WithdrawFormEvent, WithdrawFormState> {
Emitter<WithdrawFormState> emit,
) async {
if (state.hasValidationErrors) return;
if (_isUnsupportedSiaHardwareWalletFlow) {
emit(
state.copyWith(
previewError: () =>
TextError(error: _unsupportedSiaHardwareWalletMessage),
isSending: false,
isAwaitingTrezorConfirmation: false,
),
);
return;
}

try {
emit(
Expand Down Expand Up @@ -650,6 +663,17 @@ class WithdrawFormBloc extends Bloc<WithdrawFormEvent, WithdrawFormState> {
Emitter<WithdrawFormState> emit,
) async {
if (state.hasValidationErrors) return;
if (_isUnsupportedSiaHardwareWalletFlow) {
emit(
state.copyWith(
transactionError: () =>
TextError(error: _unsupportedSiaHardwareWalletMessage),
isSending: false,
isAwaitingTrezorConfirmation: false,
),
);
return;
}

try {
emit(
Expand Down Expand Up @@ -736,6 +760,9 @@ class WithdrawFormBloc extends Bloc<WithdrawFormEvent, WithdrawFormState> {
}
}

bool get _isUnsupportedSiaHardwareWalletFlow =>
_walletType == WalletType.trezor && state.asset.protocol is SiaProtocol;

void _onCancelled(
WithdrawFormCancelled event,
Emitter<WithdrawFormState> emit,
Expand Down
2 changes: 1 addition & 1 deletion sdk
Submodule sdk updated 0 files
Loading