From 3f8f5c7a959befbe1f43068e8405bc60c3207a57 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:56:13 +0100 Subject: [PATCH 1/3] Disable card payments in API responses (#3449) * Disable card payments in asset and fiat DTOs Card payments are no longer supported since 2025-01-01. Hardcode cardBuyable/cardSellable to false in DTO mappers and return zero limits for card payment method. * Reject card payments early in buy validation Block card payment requests in PaymentInfoService with PAYMENT_METHOD_NOT_ALLOWED error, consistent with the existing check in transaction-helper. --- src/shared/models/asset/dto/asset-dto.mapper.ts | 4 ++-- src/shared/models/fiat/dto/fiat-dto.mapper.ts | 9 +++------ src/shared/services/payment-info.service.ts | 5 +---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/shared/models/asset/dto/asset-dto.mapper.ts b/src/shared/models/asset/dto/asset-dto.mapper.ts index c4da5e7506..a418b3c767 100644 --- a/src/shared/models/asset/dto/asset-dto.mapper.ts +++ b/src/shared/models/asset/dto/asset-dto.mapper.ts @@ -24,8 +24,8 @@ export class AssetDtoMapper { sellable: asset.sellable, instantBuyable: asset.instantBuyable, instantSellable: asset.instantSellable, - cardBuyable: asset.cardBuyable, - cardSellable: asset.cardSellable, + cardBuyable: false, + cardSellable: false, blockchain: asset.blockchain, sortOrder: asset.sortOrder, }; diff --git a/src/shared/models/fiat/dto/fiat-dto.mapper.ts b/src/shared/models/fiat/dto/fiat-dto.mapper.ts index cef7f22fff..a7d34198f9 100644 --- a/src/shared/models/fiat/dto/fiat-dto.mapper.ts +++ b/src/shared/models/fiat/dto/fiat-dto.mapper.ts @@ -13,8 +13,8 @@ export class FiatDtoMapper { name: fiat.name, buyable: fiat.buyable, sellable: fiat.sellable, - cardBuyable: fiat.cardBuyable, - cardSellable: fiat.cardSellable, + cardBuyable: false, + cardSellable: false, instantBuyable: fiat.instantBuyable, instantSellable: fiat.instantSellable, }; @@ -37,10 +37,7 @@ export class FiatDtoMapper { fiat.instantBuyable || fiat.instantSellable ? this.convert(spec.minVolume, Config.tradingLimits.yearlyDefault, fiat) : this.zeroLimits, - [FiatPaymentMethod.CARD]: - fiat.cardBuyable || fiat.cardSellable - ? this.convert(spec.minVolume, Config.tradingLimits.cardDefault, fiat) - : this.zeroLimits, + [FiatPaymentMethod.CARD]: this.zeroLimits, }, allowedIbanCountries, }); diff --git a/src/shared/services/payment-info.service.ts b/src/shared/services/payment-info.service.ts index 7a66f77207..b5cddd76ee 100644 --- a/src/shared/services/payment-info.service.ts +++ b/src/shared/services/payment-info.service.ts @@ -48,10 +48,7 @@ export class PaymentInfoService { throw this.createError('Asset blockchain mismatch', QuoteError.ASSET_UNSUPPORTED, forQuote); if ('paymentMethod' in dto && dto.paymentMethod === FiatPaymentMethod.CARD) { - if (!dto.currency.cardSellable) - throw this.createError('Currency not sellable via Card', QuoteError.CURRENCY_UNSUPPORTED, forQuote); - if (!dto.asset.cardBuyable) - throw this.createError('Asset not buyable via Card', QuoteError.ASSET_UNSUPPORTED, forQuote); + throw this.createError('Card payments are not supported', QuoteError.PAYMENT_METHOD_NOT_ALLOWED, forQuote); } else if ('paymentMethod' in dto && dto.paymentMethod === FiatPaymentMethod.INSTANT) { if (!dto.currency.instantSellable) throw this.createError('Currency not sellable via Instant', QuoteError.CURRENCY_UNSUPPORTED, forQuote); From 1bf84b3708e5eb2d1705e1487d7877d53c1d42c3 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:58:29 +0100 Subject: [PATCH 2/3] Add Edge wallet (#3451) * Add Edge wallet entry * Remove trailing newline to match existing migrations --- migration/1773740800000-AddEdgeWallet.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 migration/1773740800000-AddEdgeWallet.js diff --git a/migration/1773740800000-AddEdgeWallet.js b/migration/1773740800000-AddEdgeWallet.js new file mode 100644 index 0000000000..e14bc66c2f --- /dev/null +++ b/migration/1773740800000-AddEdgeWallet.js @@ -0,0 +1,20 @@ +module.exports = class AddEdgeWallet1773740800000 { + name = 'AddEdgeWallet1773740800000'; + + async up(queryRunner) { + await queryRunner.query(` + IF NOT EXISTS (SELECT 1 FROM "dbo"."wallet" WHERE "name" = 'Edge') + INSERT INTO "dbo"."wallet" ( + "name", "isKycClient", "amlRules", "autoTradeApproval", + "mailConfig", "usesDummyAddresses", "displayFraudWarning", "buySpecificIbanEnabled" + ) VALUES ( + 'Edge', 0, '0', 1, + 'BuyCrypto;BuyFiat;RefReward;Info', 0, 0, 0 + ) + `); + } + + async down(queryRunner) { + await queryRunner.query(`DELETE FROM "dbo"."wallet" WHERE "name" = 'Edge'`); + } +}; \ No newline at end of file From db868844e80aff16b904059d171d4ed9a7d9f551 Mon Sep 17 00:00:00 2001 From: bernd2022 <104787072+bernd2022@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:25:30 +0100 Subject: [PATCH 3/3] fix: resolve ICP token tx explorer URLs to correct dashboard path (#3446) ICP token transactions (e.g. ckBTC) were linking to the ICP native ledger block index instead of the token-specific dashboard page. Map known token canister IDs to their dashboard paths so explorer links point to the correct transaction. --- .../blockchain/shared/util/blockchain.util.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/integration/blockchain/shared/util/blockchain.util.ts b/src/integration/blockchain/shared/util/blockchain.util.ts index bddccea0ec..4463e4d15a 100644 --- a/src/integration/blockchain/shared/util/blockchain.util.ts +++ b/src/integration/blockchain/shared/util/blockchain.util.ts @@ -51,10 +51,9 @@ export function txExplorerUrl(blockchain: Blockchain, txId: string): string | un const txPath = TxPaths[blockchain]; if (!baseUrl || !txPath) return undefined; - // ICP token txIds have format "canisterId:blockIndex" — extract block index only + // ICP token txIds have format "canisterId:blockIndex" if (blockchain === Blockchain.INTERNET_COMPUTER && txId.includes(':')) { - const blockIndex = txId.split(':')[1]; - return `${baseUrl}/${txPath}/${blockIndex}`; + return icpTokenTxUrl(baseUrl, txPath, txId); } return `${baseUrl}/${txPath}/${txId}`; @@ -73,6 +72,20 @@ export function addressExplorerUrl(blockchain: Blockchain, address: string): str // --- HELPERS --- // +// ICP token canister ID to dashboard path mapping +const IcpTokenDashboardPaths: Record = { + 'mxzaz-hqaaa-aaaar-qaada-cai': 'bitcoin', // ckBTC +}; + +function icpTokenTxUrl(baseUrl: string, txPath: string, txId: string): string | undefined { + const [canisterId, blockIndex] = txId.split(':'); + + const tokenPath = IcpTokenDashboardPaths[canisterId]; + if (!tokenPath) return undefined; + + return `${baseUrl}/${tokenPath}/${txPath}/${blockIndex}`; +} + const BlockchainExplorerUrls: { [b in Blockchain]: string } = { [Blockchain.DEFICHAIN]: 'https://defiscan.live', [Blockchain.BITCOIN]: 'https://mempool.space',