diff --git a/src/subdomains/supporting/log/__tests__/log-job.service.spec.ts b/src/subdomains/supporting/log/__tests__/log-job.service.spec.ts index b641ccbdec..c2c9e95469 100644 --- a/src/subdomains/supporting/log/__tests__/log-job.service.spec.ts +++ b/src/subdomains/supporting/log/__tests__/log-job.service.spec.ts @@ -1928,5 +1928,46 @@ describe('LogJobService', () => { // Per-leg unfiltered clamps must not exist — they would leave total = 881163.51 and skip this path. expect(verboseSpy.mock.calls.some((call) => String(call[0]).includes('totalPlusPending < 0'))).toBe(true); }); + + it('keeps signed negative unfiltered pending legs in the log when net totalPlusPending is positive', async () => { + // Active Yapeal/EUR custody asset (sellable keeps it in the asset-log reduce). + const yapealEurAsset = createCustomAsset({ + id: 8005, + blockchain: Blockchain.YAPEAL, + dexName: 'EUR', + sellable: true, + }); + + // Net-positive pending so the pending object is built (not aggregate-clamped away): + // fromKrakenUnfiltered = +900000 (unmatched Kraken WITHDRAWAL to bank) + // toKrakenUnfiltered = -100000 (unmatched Kraken DEPOSIT from bank) + // Net totalPlusPending = +800000 → pending is present; toKraken must stay negative for observability. + const fromKrakenWithdrawalTx = createCustomExchangeTx({ + id: 5003, + type: ExchangeTxType.WITHDRAWAL, + currency: 'EUR', + method: 'Bank Frick (SEPA) International', + address: 'YAPEAL AG', + amount: 900000, + }); + const toKrakenDepositTx = createCustomExchangeTx({ + id: 5004, + type: ExchangeTxType.DEPOSIT, + status: 'ok', + currency: 'EUR', + method: 'Bank Frick (SEPA) International', + address: yapealEUR.bic.padEnd(11, 'XXX'), + amount: 100000, + }); + setupUnfilteredKrakenNetting([fromKrakenWithdrawalTx, toKrakenDepositTx]); + + const assetLog = await service['getAssetLog']([yapealEurAsset]); + + // Pending must exist (net positive — not clamped away by totalPlusPending < 0). + expect(assetLog[yapealEurAsset.id].plusBalance.pending).toBeDefined(); + // Load-bearing: negative leg must be present and signed (getJsonValue returnNegativeValue=true). + expect(assetLog[yapealEurAsset.id].plusBalance.pending.toKraken).toBe(-100000); + expect(assetLog[yapealEurAsset.id].plusBalance.pending.fromKraken).toBe(900000); + }); }); }); diff --git a/src/subdomains/supporting/log/log-job.service.ts b/src/subdomains/supporting/log/log-job.service.ts index 77867dddd8..b7961638c2 100644 --- a/src/subdomains/supporting/log/log-job.service.ts +++ b/src/subdomains/supporting/log/log-job.service.ts @@ -1048,10 +1048,30 @@ export class LogJobService { exchangeOrder: this.getJsonValue(exchangeOrder, amountType(curr)), bridgeOrder: this.getJsonValue(bridgeOrder, amountType(curr)), fromOlky: this.getJsonValue(pendingOlkyYapealAmount, amountType(curr)), - fromKraken: this.getJsonValue(useUnfilteredTx ? fromKrakenUnfiltered : fromKraken, amountType(curr)), - toKraken: this.getJsonValue(useUnfilteredTx ? toKrakenUnfiltered : toKraken, amountType(curr)), - fromScrypt: this.getJsonValue(useUnfilteredTx ? fromScryptUnfiltered : fromScrypt, amountType(curr)), - toScrypt: this.getJsonValue(useUnfilteredTx ? toScryptUnfiltered : toScrypt, amountType(curr)), + fromKraken: this.getJsonValue( + useUnfilteredTx ? fromKrakenUnfiltered : fromKraken, + amountType(curr), + false, + true, + ), + toKraken: this.getJsonValue( + useUnfilteredTx ? toKrakenUnfiltered : toKraken, + amountType(curr), + false, + true, + ), + fromScrypt: this.getJsonValue( + useUnfilteredTx ? fromScryptUnfiltered : fromScrypt, + amountType(curr), + false, + true, + ), + toScrypt: this.getJsonValue( + useUnfilteredTx ? toScryptUnfiltered : toScrypt, + amountType(curr), + false, + true, + ), } : undefined, // monitoring: errors.length