From df2f1514136ed445f2fc762e58c48fa0b9d608c3 Mon Sep 17 00:00:00 2001 From: Daniel Padrino Date: Fri, 12 Jun 2026 10:55:09 -0300 Subject: [PATCH] fix(payin): skip Cardano pay-in check when no Tatum API key is configured The Cardano register strategy polls Tatum every minute and always includes its payment deposit address, so on environments without a (funded) Tatum key every cycle fails with an ERROR (~60/h on dev, currently a 402 because the key's plan is out of credits). Follow the exchange-credentials pattern (#3859): expose isConfigured on CardanoClient (Tatum key present) and skip the cron with a single WARN when unset. A key that is set but rejected still errors, so a real prod misconfiguration stays visible. Solana/Tron are webhook-driven and make no unprompted Tatum calls, so no guard is needed there. --- src/integration/blockchain/cardano/cardano-client.ts | 4 ++++ .../blockchain/cardano/services/cardano.service.ts | 4 ++++ .../payin/services/payin-cardano.service.ts | 4 ++++ .../strategies/register/impl/cardano.strategy.ts | 12 ++++++++++++ 4 files changed, 24 insertions(+) diff --git a/src/integration/blockchain/cardano/cardano-client.ts b/src/integration/blockchain/cardano/cardano-client.ts index 34aeb21b63..57f72821b5 100644 --- a/src/integration/blockchain/cardano/cardano-client.ts +++ b/src/integration/blockchain/cardano/cardano-client.ts @@ -62,6 +62,10 @@ export class CardanoClient extends BlockchainClient { return this.wallet.address; } + get isConfigured(): boolean { + return !!Config.blockchain.cardano.cardanoTatumApiKey; + } + async getBlockHeight(): Promise { const info = await this.getNetworkInfo(); return info.tip; diff --git a/src/integration/blockchain/cardano/services/cardano.service.ts b/src/integration/blockchain/cardano/services/cardano.service.ts index 95696c69d6..f91be53505 100644 --- a/src/integration/blockchain/cardano/services/cardano.service.ts +++ b/src/integration/blockchain/cardano/services/cardano.service.ts @@ -27,6 +27,10 @@ export class CardanoService extends BlockchainService { return this.client.walletAddress; } + get isConfigured(): boolean { + return this.client.isConfigured; + } + verifySignature(message: string, address: string, signature: string, key?: string): boolean { try { return verifyCardanoSignature(signature, key, message, address); diff --git a/src/subdomains/supporting/payin/services/payin-cardano.service.ts b/src/subdomains/supporting/payin/services/payin-cardano.service.ts index b363f73c42..3daddd3e2a 100644 --- a/src/subdomains/supporting/payin/services/payin-cardano.service.ts +++ b/src/subdomains/supporting/payin/services/payin-cardano.service.ts @@ -12,6 +12,10 @@ export class PayInCardanoService { return this.cardanoService.getWalletAddress(); } + get isConfigured(): boolean { + return this.cardanoService.isConfigured; + } + async getNativeCoinBalanceForAddress(address: string): Promise { return this.cardanoService.getNativeCoinBalanceForAddress(address); } diff --git a/src/subdomains/supporting/payin/strategies/register/impl/cardano.strategy.ts b/src/subdomains/supporting/payin/strategies/register/impl/cardano.strategy.ts index 51c3cd1c25..cec4af850a 100644 --- a/src/subdomains/supporting/payin/strategies/register/impl/cardano.strategy.ts +++ b/src/subdomains/supporting/payin/strategies/register/impl/cardano.strategy.ts @@ -22,6 +22,8 @@ export class CardanoStrategy extends RegisterStrategy { private readonly cardanoPaymentDepositAddress: string; + private unconfiguredWarned = false; + constructor( private readonly payInCardanoService: PayInCardanoService, private readonly transactionRequestService: TransactionRequestService, @@ -41,6 +43,16 @@ export class CardanoStrategy extends RegisterStrategy { //*** JOBS ***// @DfxCron(CronExpression.EVERY_MINUTE, { process: Process.PAY_IN, timeout: 7200 }) async checkPayInEntries(): Promise { + // not configured (no Tatum API key) -> skip, warn once + if (!this.payInCardanoService.isConfigured) { + if (!this.unconfiguredWarned) { + this.unconfiguredWarned = true; + this.logger.warn('Cardano has no Tatum API key configured — skipping pay-in check'); + } + + return; + } + const activeDepositAddresses = await this.transactionRequestService.getActiveDepositAddresses( Util.hoursBefore(1), this.blockchain,