Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
e25247c
dont query available balance if not logged in
smk762 Oct 27, 2025
dd26ada
avoid best_orders calls unless on dex/bridge; fail gracefully & retry
smk762 Oct 27, 2025
2791414
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 28, 2025
ea30e4e
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 28, 2025
bf4637c
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 28, 2025
48f9246
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 29, 2025
ee03dc6
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 29, 2025
65dbe07
earlier returns when not logged in
smk762 Oct 29, 2025
39be934
fix(trading-bot): use max_maker_vol for spendable balance
takenagain Oct 29, 2025
6a0b1a5
chore: add FdMonitor.swift to Xcode project configuration
DeckerSU Oct 29, 2025
232ed48
feat(trading-bot): add loading indicator when fetching max maker vol
takenagain Oct 29, 2025
b2b5ed0
chore: update DEVELOPMENT_TEAM identifier in Xcode project configuration
DeckerSU Oct 30, 2025
b075fa8
fix(trading-bot): buy coin fiat value delay
takenagain Oct 30, 2025
ab73523
refactor: use conventional formatAmt
takenagain Oct 30, 2025
4eb7672
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Oct 30, 2025
e8d4260
ensure `available to swap` is populated post-login without interaction
smk762 Oct 30, 2025
15b6e75
refactor: add logging for errors not propagated to UI layer
takenagain Oct 30, 2025
0213e29
fix(trading-bot): add guard against swap button spamming
takenagain Oct 30, 2025
8b73ddf
Merge branch 'dev' into fix/trading-bot-max-volume
takenagain Oct 30, 2025
896d022
isolate version settings in shared_preferences.json for backwards com…
smk762 Oct 31, 2025
bf4fea7
Merge branch 'dev' into siloed-configs
smk762 Oct 31, 2025
b42a343
Merge branch 'dev' into fix/trading-bot-max-volume
smk762 Oct 31, 2025
f52a907
fix(dex): propagate best_orders failures, avoid masking as no liquidi…
CharlVS Oct 31, 2025
4d4a258
chore(settings): add logging and avoid silent skipping
takenagain Oct 31, 2025
b148ab8
Merge pull request #3329 from KomodoPlatform/refactor/siloed-configs-…
smk762 Nov 1, 2025
b965753
Merge branch 'dev' into siloed-configs
CharlVS Nov 2, 2025
5da3aaf
fix ci (#3336)
ca333 Nov 2, 2025
51b3578
Merge branch 'dev' into siloed-configs
takenagain Nov 2, 2025
2d88bfe
refactor(settings): respect DI without duplication of logic
takenagain Nov 2, 2025
c3ec8f2
fix(transaction-history): revert to timestamp-based transaction sorting
DeckerSU Nov 2, 2025
acdb840
gets min_trade_volume to avoid bot errors
smk762 Nov 3, 2025
fe010c5
Merge branch 'dev' into tweak-prelogin-orderbook
smk762 Nov 3, 2025
e2d8273
fix(transaction-history): update transaction sorting logic for unconf…
DeckerSU Nov 3, 2025
8bbe3b8
Merge pull request #3343 from KomodoPlatform/fix/trading-bot-min-value
takenagain Nov 4, 2025
ac45bc1
Merge branch 'dev' into fix/trading-bot-max-volume
takenagain Nov 4, 2025
cefa1e6
docs: update CHANGELOG.md for v0.9.3 release (#3350)
CharlVS Nov 4, 2025
d617479
Merge branch 'dev' into siloed-configs
CharlVS Nov 4, 2025
768fcea
Merge branch 'dev' into tweak-prelogin-orderbook
ca333 Nov 4, 2025
07806d0
Merge pull request #3263 from KomodoPlatform/tweak-prelogin-orderbook
ca333 Nov 4, 2025
1bd420b
Merge branch 'dev' into fix/trading-bot-max-volume
ca333 Nov 4, 2025
328d0ca
Merge pull request #3300 from KomodoPlatform/fix/trading-bot-max-volume
ca333 Nov 4, 2025
e6c8757
Merge branch 'dev' into patch-ios-build-fix-1
ca333 Nov 4, 2025
07d5d30
Merge pull request #3301 from KomodoPlatform/patch-ios-build-fix-1
ca333 Nov 4, 2025
fd93e94
Merge branch 'dev' into patch-fix-tx-history-sync-display
ca333 Nov 4, 2025
01938ab
Merge pull request #3338 from KomodoPlatform/patch-fix-tx-history-syn…
ca333 Nov 4, 2025
e670088
Merge branch 'dev' into siloed-configs
ca333 Nov 4, 2025
e0c88cf
Merge pull request #3321 from KomodoPlatform/siloed-configs
ca333 Nov 4, 2025
d32e4cb
Merge branch 'main' into dev
ca333 Nov 4, 2025
eb2b0b8
chore: update subproject commit reference in sdk
DeckerSU Nov 4, 2025
1d3ab65
disable NFT page in sidebar menu
smk762 Nov 5, 2025
dacf503
fix macos app icons
smk762 Nov 5, 2025
a5931b4
Merge pull request #3362 from KomodoPlatform/hide-nft-tab
ca333 Nov 5, 2025
35b3423
Merge branch 'dev' into fix-macos-logo
ca333 Nov 5, 2025
9d8647c
Merge pull request #3363 from KomodoPlatform/fix-macos-logo
ca333 Nov 5, 2025
3067c67
bypass ARRR autoactivation if sync params have not been previously de…
smk762 Nov 5, 2025
2901378
Merge pull request #3370 from KomodoPlatform/zhtlc-default-bypass
ca333 Nov 5, 2025
0587b34
fix missing import
smk762 Nov 5, 2025
e55e914
Merge branch 'dev' into zhtlc-default-bypass
ca333 Nov 5, 2025
f439819
Merge pull request #3371 from KomodoPlatform/zhtlc-default-bypass
ca333 Nov 5, 2025
4df5e84
feat: add photo library usage description to Info.plist for QR code i…
DeckerSU Nov 5, 2025
61c1f56
Enhance iOS file sharing functionality by adding share position origi…
DeckerSU Nov 5, 2025
96c1baa
Update iOS file loader to use scaffold context for share position ori…
DeckerSU Nov 5, 2025
b37b0f8
Merge pull request #3374 from KomodoPlatform/patch-fix-download-logs-ios
ca333 Nov 5, 2025
3a05712
Merge branch 'dev' into patch-fix-ios-permissions
ca333 Nov 5, 2025
ef2925e
Merge pull request #3372 from KomodoPlatform/patch-fix-ios-permissions
ca333 Nov 5, 2025
5780096
Fix: Prevent state loss in private key retrieval and improve empty ke…
DeckerSU Nov 6, 2025
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
15 changes: 9 additions & 6 deletions .github/actions/validate-build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ runs:
run: |
SDK_KDF_ASSETS_DIR=build/web/assets/packages/komodo_defi_framework

# Check that the web build folder contains a wasm file in the format build/web/kdf/*.wasm
if [ ! -f build/web/kdf/kdf/bin/*.wasm ]; then
# Check that the web build folder contains a wasm file in the format build/web/kdf/kdf/bin/*.wasm
shopt -s nullglob
wasm_files=(build/web/kdf/kdf/bin/*.wasm)
if [ ${#wasm_files[@]} -eq 0 ]; then
echo "Error: Web build failed. No wasm file found in build/web/kdf/kdf/bin"
# List files for debugging
echo "Listing files in build/web recursively"
ls -R build/web
echo "Listing files in build/web/kdf recursively"
ls -R build/web/kdf 2>/dev/null || echo "build/web/kdf directory does not exist"

echo "Listing files in web recursively"
ls -R web
echo "Listing files in web/kdf recursively"
ls -R web/kdf 2>/dev/null || echo "web/kdf directory does not exist"

exit 1
fi
echo "Found wasm files: ${wasm_files[@]}"

# Check that the index.html is present and that it is equal to the source index.html
if ! cmp -s web/index.html build/web/index.html; then
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/desktop-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
with:
p12-file-base64: ${{ secrets.MACOS_P12_BASE64 }}
p12-password: ${{ secrets.MACOS_P12_PASSWORD }}
bundle-id: "com.komodo.komodowallet"
bundle-id: "com.komodo.wallet"
profile-type: "MAC_APP_DEVELOPMENT"
issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
api-key-id: ${{ secrets.APPSTORE_KEY_ID }}
Expand All @@ -73,6 +73,10 @@ jobs:
- name: Fetch packages, generate assets, and build for ${{ matrix.platform }}
env:
GITHUB_API_PUBLIC_READONLY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Disable code signing for macOS PR builds
CODE_SIGNING_ALLOWED: ${{ matrix.platform == 'macos' && github.event_name == 'pull_request' && 'NO' || '' }}
CODE_SIGNING_REQUIRED: ${{ matrix.platform == 'macos' && github.event_name == 'pull_request' && 'NO' || '' }}
EXPANDED_CODE_SIGN_IDENTITY: ${{ matrix.platform == 'macos' && github.event_name == 'pull_request' && '-' || '' }}
uses: ./.github/actions/generate-assets
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@ venv/
/macos/build
AGENTS_1.md
# .dmg Release
dist/
dist/

# KDF generated binaries
web/kdf/kdf/bin/
282 changes: 202 additions & 80 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@
"orderBookNoAsks": "No asks found",
"orderBookNoBids": "No bids found",
"orderBookEmpty": "Orderbook is empty",
"dexNoSwapOffers": "No swap offers available for the selected asset.",
"bridgeNoCrossNetworkRoutes": "No cross-network routes found for this asset.",
"freshAddress": "Fresh address",
"userActionRequired": "User action required",
"unknown": "Unknown",
Expand Down Expand Up @@ -748,6 +750,7 @@
"trend7d": "7d trend",
"tradingDisabledTooltip": "Trading features are currently disabled",
"tradingDisabled": "Trading unavailable in your location",
"nftDisabledTooltip": "NFT functionality is currently disabled. Improvements are on the way!",
"includeBlockedAssets": "Include blocked assets",
"unbanPubkeysResults": "Unban Pubkeys Results",
"unbannedPubkeys": {
Expand All @@ -766,6 +769,7 @@
"noBannedPubkeys": "No banned pubkeys found",
"unbanPubkeysFailed": "Failed to unban pubkeys",
"privateKeyRetrievalFailed": "Failed to retrieve private keys. Please try again.",
"privateKeysEmptyError": "No private keys found. Assets may need to be activated. Please try again later.",
"fetchingPrivateKeysTitle": "Fetching Private Keys...",
"fetchingPrivateKeysMessage": "Please wait while we securely fetch your private keys...",
"pubkeyType": "Type",
Expand Down
10 changes: 7 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
49484A33FCF0585DB40EBAD9 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C74478EE63B90E2A48A7AB3C /* GoogleService-Info.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
F1D1A3B2C3D4E5F6A7B8C9D1 /* FdMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1D1A3B2C3D4E5F6A7B8C9D0 /* FdMonitor.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
Expand Down Expand Up @@ -45,6 +46,7 @@
6DB340A008F6FECB3B82619D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F1D1A3B2C3D4E5F6A7B8C9D0 /* FdMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FdMonitor.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
91B045D447C7C6266906543C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -122,6 +124,7 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
F1D1A3B2C3D4E5F6A7B8C9D0 /* FdMonitor.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
Expand Down Expand Up @@ -303,6 +306,7 @@
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
F1D1A3B2C3D4E5F6A7B8C9D1 /* FdMonitor.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -387,7 +391,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = G3VBBBMD8T;
DEVELOPMENT_TEAM = 8HPBYKKKQP;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -530,7 +534,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = G3VBBBMD8T;
DEVELOPMENT_TEAM = 8HPBYKKKQP;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -565,7 +569,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = G3VBBBMD8T;
DEVELOPMENT_TEAM = 8HPBYKKKQP;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
Expand Down
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
</dict>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to your photo library to import QR codes</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
5 changes: 5 additions & 0 deletions lib/app_config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ const Duration kPerformanceLogInterval = Duration(minutes: 1);
/// - Balance and price update polling
const bool kDebugElectrumLogs = true;

/// Temporary failure simulation toggles for testing UI/flows.
/// Guarded by kDebugMode in calling sites.
const bool kSimulateBestOrdersFailure = false;
const double kSimulatedBestOrdersFailureRate = 0.5; // 50%

// This information is here because it is not contextual and is branded.
// Names of their own are not localized. Also, the application is initialized before
// the localization package is initialized.
Expand Down
28 changes: 22 additions & 6 deletions lib/bloc/bridge_form/bridge_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,17 @@ class BridgeBloc extends Bloc<BridgeEvent, BridgeState> {
),
);

// Before login, show 0.00 instead of spinner
if (!_isLoggedIn) {
emit(
state.copyWith(
availableBalanceState: () => AvailableBalanceState.unavailable,
maxSellAmount: () => null,
),
);
return;
}

_autoActivateCoin(event.coin.abbr);
_subscribeMaxSellAmount();

Expand Down Expand Up @@ -392,22 +403,27 @@ class BridgeBloc extends Bloc<BridgeEvent, BridgeState> {
return;
}

if (state.availableBalanceState == AvailableBalanceState.initial ||
event.setLoadingStatus) {
// If not logged in, show 0.00 (unavailable) and skip spinner
if (!_isLoggedIn) {
emit(
state.copyWith(
availableBalanceState: () => AvailableBalanceState.loading,
availableBalanceState: () => AvailableBalanceState.unavailable,
maxSellAmount: () => null,
),
);
return;
}

if (!_isLoggedIn) {
if (state.availableBalanceState == AvailableBalanceState.initial ||
event.setLoadingStatus) {
emit(
state.copyWith(
availableBalanceState: () => AvailableBalanceState.unavailable,
availableBalanceState: () => AvailableBalanceState.loading,
),
);
} else {
}

{
Rational? maxSellAmount = await _dexRepository.getMaxTakerVolume(
state.sellCoin!.abbr,
);
Expand Down
45 changes: 44 additions & 1 deletion lib/bloc/coins_bloc/coins_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -523,10 +523,18 @@ class CoinsBloc extends Bloc<CoinsEvent, CoinsState> {
.map((assetsSet) => assetsSet.single);

// Filter out blocked assets
final coinsToActivate = _tradingStatusService.filterAllowedAssets(
var coinsToActivate = _tradingStatusService.filterAllowedAssets(
availableAssets.toList(),
);

// During initial login auto-activation, skip ZHTLC assets that would
// trigger configuration dialogs (i.e. no saved configuration yet).
if (_isInitialActivationInProgress) {
coinsToActivate = await _filterAssetsForInitialActivation(
coinsToActivate,
);
}

final enableFutures = coinsToActivate
.map((asset) => _coinsRepo.activateAssetsSync([asset]))
.toList();
Expand All @@ -536,6 +544,41 @@ class CoinsBloc extends Bloc<CoinsEvent, CoinsState> {
await Future.wait(enableFutures);
}

/// Filters assets for initial auto-activation on login.
///
/// - Keeps all non-ZHTLC assets
/// - Keeps ZHTLC assets only if a saved configuration already exists
Future<List<Asset>> _filterAssetsForInitialActivation(
List<Asset> assets,
) async {
final filtered = <Asset>[];
for (final asset in assets) {
if (asset.id.subClass != CoinSubClass.zhtlc) {
filtered.add(asset);
continue;
}

try {
final saved =
await _kdfSdk.activationConfigService.getSavedZhtlc(asset.id);
if (saved != null) {
filtered.add(asset);
} else {
_log.info(
'Skipping auto-activation of ZHTLC asset ${asset.id.id} during login: no saved configuration found',
);
}
} catch (e, s) {
_log.shout(
'Error checking saved ZHTLC configuration for ${asset.id.id}',
e,
s,
);
}
}
return filtered;
}

CoinsState _prePopulateListWithActivatingCoins(Iterable<String> coins) {
final knownCoins = _coinsRepo.getKnownCoinsMap();
final activatingCoins = Map<String, Coin>.fromIterable(
Expand Down
16 changes: 16 additions & 0 deletions lib/bloc/coins_manager/coins_manager_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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:komodo_defi_types/komodo_defi_types.dart' show CoinSubClass;
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
import 'package:logging/logging.dart';
import 'package:web_dex/analytics/events/portfolio_events.dart';
Expand Down Expand Up @@ -374,6 +375,21 @@ class CoinsManagerBloc extends Bloc<CoinsManagerEvent, CoinsManagerState> {
final selectedCoinIds = result.map((c) => c.id.id).toSet();

for (final walletCoin in walletCoins) {
// Do not pre-select ZHTLC coins without saved configuration.
// 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);
if (saved == null) {
continue;
}
} catch (_) {
// On any error, be conservative and keep toggle OFF
continue;
}
}

if (!selectedCoinIds.contains(walletCoin.id.id)) {
result.add(walletCoin);
}
Expand Down
Loading
Loading