@openora/core 0.4.1-canary.94 → 0.4.1-canary.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/audit/plugin.d.ts.map +1 -1
- package/dist/audit/plugin.js +13 -0
- package/dist/audit/plugin.js.map +1 -1
- package/dist/contracts/adapters/audit.d.ts +1 -1
- package/dist/contracts/adapters/audit.d.ts.map +1 -1
- package/dist/contracts/adapters/audit.js.map +1 -1
- package/dist/contracts/schemas/events.d.ts +5 -0
- package/dist/contracts/schemas/events.d.ts.map +1 -1
- package/dist/contracts/schemas/events.js +9 -0
- package/dist/contracts/schemas/events.js.map +1 -1
- package/dist/testing/mock.d.ts +6 -1
- package/dist/testing/mock.d.ts.map +1 -1
- package/dist/testing/mock.js +9 -0
- package/dist/testing/mock.js.map +1 -1
- package/dist/wallet/__tests__/reconciliation-diff.test.d.ts +2 -0
- package/dist/wallet/__tests__/reconciliation-diff.test.d.ts.map +1 -0
- package/dist/wallet/__tests__/reconciliation-diff.test.js +49 -0
- package/dist/wallet/__tests__/reconciliation-diff.test.js.map +1 -0
- package/dist/wallet/__tests__/reconciliation.service.int.test.d.ts +2 -0
- package/dist/wallet/__tests__/reconciliation.service.int.test.d.ts.map +1 -0
- package/dist/wallet/__tests__/reconciliation.service.int.test.js +395 -0
- package/dist/wallet/__tests__/reconciliation.service.int.test.js.map +1 -0
- package/dist/wallet/__tests__/wallet-asset.router.int.test.js +6 -1
- package/dist/wallet/__tests__/wallet-asset.router.int.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-auto-rule.router.int.test.js +12 -2
- package/dist/wallet/__tests__/wallet-auto-rule.router.int.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-auto-withdrawal-config.router.int.test.js +12 -2
- package/dist/wallet/__tests__/wallet-auto-withdrawal-config.router.int.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet-custody-routes.router.test.d.ts +2 -0
- package/dist/wallet/__tests__/wallet-custody-routes.router.test.d.ts.map +1 -0
- package/dist/wallet/__tests__/{wallet-custody-stubs.router.test.js → wallet-custody-routes.router.test.js} +58 -21
- package/dist/wallet/__tests__/wallet-custody-routes.router.test.js.map +1 -0
- package/dist/wallet/__tests__/wallet-webhook.router.int.test.js +25 -3
- package/dist/wallet/__tests__/wallet-webhook.router.int.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet.router.int.test.js +6 -1
- package/dist/wallet/__tests__/wallet.router.int.test.js.map +1 -1
- package/dist/wallet/__tests__/wallet.service.int.test.js +34 -11
- package/dist/wallet/__tests__/wallet.service.int.test.js.map +1 -1
- package/dist/wallet/contract/index.d.ts.map +1 -1
- package/dist/wallet/contract/index.js +7 -7
- package/dist/wallet/contract/index.js.map +1 -1
- package/dist/wallet/plugin.d.ts.map +1 -1
- package/dist/wallet/plugin.js +69 -36
- package/dist/wallet/plugin.js.map +1 -1
- package/dist/wallet/router/index.d.ts +6 -3
- package/dist/wallet/router/index.d.ts.map +1 -1
- package/dist/wallet/router/index.js +23 -21
- package/dist/wallet/router/index.js.map +1 -1
- package/dist/wallet/service/custody-sweep.service.d.ts.map +1 -1
- package/dist/wallet/service/custody-sweep.service.js +9 -12
- package/dist/wallet/service/custody-sweep.service.js.map +1 -1
- package/dist/wallet/service/reconciliation-finding.service.d.ts +39 -0
- package/dist/wallet/service/reconciliation-finding.service.d.ts.map +1 -0
- package/dist/wallet/service/reconciliation-finding.service.js +36 -0
- package/dist/wallet/service/reconciliation-finding.service.js.map +1 -0
- package/dist/wallet/service/reconciliation.service.d.ts +112 -0
- package/dist/wallet/service/reconciliation.service.d.ts.map +1 -0
- package/dist/wallet/service/reconciliation.service.js +509 -0
- package/dist/wallet/service/reconciliation.service.js.map +1 -0
- package/dist/wallet/service/wallet.service.d.ts +7 -2
- package/dist/wallet/service/wallet.service.d.ts.map +1 -1
- package/dist/wallet/service/wallet.service.js +45 -3
- package/dist/wallet/service/wallet.service.js.map +1 -1
- package/package.json +1 -1
- package/dist/wallet/__tests__/wallet-custody-stubs.router.test.d.ts +0 -2
- package/dist/wallet/__tests__/wallet-custody-stubs.router.test.d.ts.map +0 -1
- package/dist/wallet/__tests__/wallet-custody-stubs.router.test.js.map +0 -1
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { and, count, desc, eq, gte, inArray, isNull, lt } from 'drizzle-orm';
|
|
3
|
+
import { createLogger, findOneOrThrow, makeConflictError, makeNotFoundError, moneyEquals, pageToOffset, serializeRow, } from '@openora/core/server';
|
|
4
|
+
import { DEFAULT_PAYMENT_PROVIDER, } from '@openora/core/contracts';
|
|
5
|
+
import { walletCustodySweep, walletJobRun, walletReconciliationFinding, walletTransaction, } from '../schema/index.js';
|
|
6
|
+
import { recordReconciliationFinding } from './reconciliation-finding.service.js';
|
|
7
|
+
const logger = createLogger('wallet-reconciliation');
|
|
8
|
+
export const ReconciliationFindingNotFoundError = makeNotFoundError('ReconciliationFinding');
|
|
9
|
+
export const ReconciliationCreditTransactionNotFoundError = makeNotFoundError('ReconciliationCreditTransaction');
|
|
10
|
+
export const ReconciliationCreditMismatchError = makeConflictError('ReconciliationCreditMismatchError', "The referenced transaction is not a manual credit matching this finding's currency and amount");
|
|
11
|
+
/**
|
|
12
|
+
* Pure diff of one vendor deposit event against its (maybe absent) ledger row - the
|
|
13
|
+
* whole decision reconciliation makes for a deposit, extracted so it is unit-testable
|
|
14
|
+
* without a database. Never routes through moneyToNumber (see money.md): an exact
|
|
15
|
+
* decimal compare, not a float one.
|
|
16
|
+
*/
|
|
17
|
+
export function diffDeposit(event, tx) {
|
|
18
|
+
if (!tx) {
|
|
19
|
+
return 'missing_deposit';
|
|
20
|
+
}
|
|
21
|
+
if (tx.currency.toUpperCase() !== event.currency.toUpperCase()) {
|
|
22
|
+
return 'currency_mismatch';
|
|
23
|
+
}
|
|
24
|
+
if (!moneyEquals(tx.amount, event.amount)) {
|
|
25
|
+
return 'amount_mismatch';
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function chunk(items, size) {
|
|
30
|
+
const chunks = [];
|
|
31
|
+
for (let i = 0; i < items.length; i += size) {
|
|
32
|
+
chunks.push(items.slice(i, i + size));
|
|
33
|
+
}
|
|
34
|
+
return chunks;
|
|
35
|
+
}
|
|
36
|
+
// Vendor listTransactions batches are thousands of rows; a well-under-the-parameter-
|
|
37
|
+
// ceiling chunk size keeps every lookup a single inArray(...) round trip per chunk,
|
|
38
|
+
// never one query per vendor transaction.
|
|
39
|
+
const PROVIDER_REF_LOOKUP_CHUNK_SIZE = 1000;
|
|
40
|
+
// A claimed run stuck this long is presumed crashed (the process died mid-cycle) rather
|
|
41
|
+
// than still working, so the next tick may mark it `abandoned` and take the slot over.
|
|
42
|
+
// Distinct from the vendor-side ambiguity thresholds: this one is about our own worker.
|
|
43
|
+
const DEFAULT_STALE_RUN_AFTER_MINUTES = 30;
|
|
44
|
+
/** Fallback when reconciliation runs without a `wallet.sweep` config block. */
|
|
45
|
+
const DEFAULT_UNKNOWN_AFTER_MINUTES = 60;
|
|
46
|
+
const JOB_NAME = 'wallet-reconciliation';
|
|
47
|
+
/**
|
|
48
|
+
* Ceiling on catching up after an outage, as a multiple of `lookbackHours`. Recovering
|
|
49
|
+
* from a week of downtime must not ask a vendor for one unbounded page of history.
|
|
50
|
+
*/
|
|
51
|
+
const MAX_CATCH_UP_MULTIPLE = 7;
|
|
52
|
+
function toFindingDto(row) {
|
|
53
|
+
return serializeRow(row, { dateFields: ['createdAt', 'resolvedAt'], decimalFields: [] });
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Owns the reconciliation job cycle (claim -> per-provider diff -> stuck-withdrawal /
|
|
57
|
+
* stuck-sweep sweep -> finish + audit + alert) and the admin surface over its findings
|
|
58
|
+
* (list/resolve). Never credits or moves money itself - every finding is a report; the
|
|
59
|
+
* only paths that touch a balance are `WalletService.reconcileWithdrawalStatus` (already
|
|
60
|
+
* idempotent) and the pre-existing manual-adjustment path a `credited` resolution merely
|
|
61
|
+
* references.
|
|
62
|
+
*/
|
|
63
|
+
export class ReconciliationService {
|
|
64
|
+
drizzle;
|
|
65
|
+
events;
|
|
66
|
+
wallet;
|
|
67
|
+
paymentProviders;
|
|
68
|
+
audit;
|
|
69
|
+
platformConfig;
|
|
70
|
+
constructor({ drizzle, events, wallet, paymentProviders, audit, platformConfig, }) {
|
|
71
|
+
this.drizzle = drizzle;
|
|
72
|
+
this.events = events;
|
|
73
|
+
this.wallet = wallet;
|
|
74
|
+
this.paymentProviders = paymentProviders;
|
|
75
|
+
this.audit = audit;
|
|
76
|
+
this.platformConfig = platformConfig;
|
|
77
|
+
}
|
|
78
|
+
async listFindings(filter) {
|
|
79
|
+
const db = this.drizzle.db;
|
|
80
|
+
const conditions = [];
|
|
81
|
+
if (filter.status) {
|
|
82
|
+
conditions.push(eq(walletReconciliationFinding.status, filter.status));
|
|
83
|
+
}
|
|
84
|
+
if (filter.kind) {
|
|
85
|
+
conditions.push(eq(walletReconciliationFinding.kind, filter.kind));
|
|
86
|
+
}
|
|
87
|
+
if (filter.providerName) {
|
|
88
|
+
conditions.push(eq(walletReconciliationFinding.providerName, filter.providerName));
|
|
89
|
+
}
|
|
90
|
+
const where = conditions.length > 0 ? and(...conditions) : undefined;
|
|
91
|
+
const [rows, [{ n } = { n: 0 }]] = await Promise.all([
|
|
92
|
+
db
|
|
93
|
+
.select()
|
|
94
|
+
.from(walletReconciliationFinding)
|
|
95
|
+
.where(where)
|
|
96
|
+
.orderBy(desc(walletReconciliationFinding.createdAt), desc(walletReconciliationFinding.id))
|
|
97
|
+
.limit(filter.limit)
|
|
98
|
+
.offset(pageToOffset(filter.page, filter.limit)),
|
|
99
|
+
db.select({ n: count() }).from(walletReconciliationFinding).where(where),
|
|
100
|
+
]);
|
|
101
|
+
return {
|
|
102
|
+
items: rows.map(toFindingDto),
|
|
103
|
+
total: Number(n),
|
|
104
|
+
page: filter.page,
|
|
105
|
+
limit: filter.limit,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Conditional `UPDATE ... WHERE status = 'open'` is the whole double-resolve guard -
|
|
110
|
+
* a second resolve of an already-resolved finding matches zero rows and returns the
|
|
111
|
+
* row unchanged, with no second audit entry. `credited` requires the referenced
|
|
112
|
+
* transaction to already exist (the manual-adjustment path creates it - this never
|
|
113
|
+
* credits anything itself) and match the finding's currency/amount exactly.
|
|
114
|
+
*/
|
|
115
|
+
async resolveFinding(adminId, id, resolution, meta) {
|
|
116
|
+
return this.drizzle.db.transaction(async (txn) => {
|
|
117
|
+
let transactionId;
|
|
118
|
+
let resolutionNote = null;
|
|
119
|
+
if (resolution.outcome === 'credited') {
|
|
120
|
+
const [finding] = await txn
|
|
121
|
+
.select()
|
|
122
|
+
.from(walletReconciliationFinding)
|
|
123
|
+
.where(eq(walletReconciliationFinding.id, id));
|
|
124
|
+
if (!finding) {
|
|
125
|
+
throw new ReconciliationFindingNotFoundError(id);
|
|
126
|
+
}
|
|
127
|
+
const [tx] = await txn
|
|
128
|
+
.select()
|
|
129
|
+
.from(walletTransaction)
|
|
130
|
+
.where(eq(walletTransaction.id, resolution.transactionId));
|
|
131
|
+
if (!tx) {
|
|
132
|
+
throw new ReconciliationCreditTransactionNotFoundError(resolution.transactionId);
|
|
133
|
+
}
|
|
134
|
+
if (tx.type !== 'manual_credit' ||
|
|
135
|
+
finding.currency === null ||
|
|
136
|
+
tx.currency.toUpperCase() !== finding.currency.toUpperCase() ||
|
|
137
|
+
finding.amount === null ||
|
|
138
|
+
!moneyEquals(tx.amount, finding.amount)) {
|
|
139
|
+
throw new ReconciliationCreditMismatchError();
|
|
140
|
+
}
|
|
141
|
+
transactionId = tx.id;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
resolutionNote = resolution.note;
|
|
145
|
+
}
|
|
146
|
+
const updated = await txn
|
|
147
|
+
.update(walletReconciliationFinding)
|
|
148
|
+
.set({
|
|
149
|
+
status: 'resolved',
|
|
150
|
+
resolvedBy: adminId,
|
|
151
|
+
resolvedAt: new Date(),
|
|
152
|
+
resolutionNote,
|
|
153
|
+
...(transactionId ? { transactionId } : {}),
|
|
154
|
+
})
|
|
155
|
+
.where(and(eq(walletReconciliationFinding.id, id), eq(walletReconciliationFinding.status, 'open')))
|
|
156
|
+
.returning();
|
|
157
|
+
if (updated.length === 0) {
|
|
158
|
+
const [existing] = await txn
|
|
159
|
+
.select()
|
|
160
|
+
.from(walletReconciliationFinding)
|
|
161
|
+
.where(eq(walletReconciliationFinding.id, id));
|
|
162
|
+
// Already resolved by a concurrent/earlier call: return it unchanged, no audit entry.
|
|
163
|
+
return toFindingDto(findOneOrThrow(existing ? [existing] : [], new ReconciliationFindingNotFoundError(id)));
|
|
164
|
+
}
|
|
165
|
+
const row = findOneOrThrow(updated, new ReconciliationFindingNotFoundError(id));
|
|
166
|
+
await this.audit.recordInTransaction(txn, {
|
|
167
|
+
actorId: adminId,
|
|
168
|
+
actorType: 'admin',
|
|
169
|
+
action: 'wallet.reconciliation_finding.resolved',
|
|
170
|
+
resourceType: 'wallet_reconciliation_finding',
|
|
171
|
+
resourceId: row.id,
|
|
172
|
+
before: { status: 'open' },
|
|
173
|
+
after: {
|
|
174
|
+
status: row.status,
|
|
175
|
+
outcome: resolution.outcome,
|
|
176
|
+
transactionId: row.transactionId,
|
|
177
|
+
resolutionNote: row.resolutionNote,
|
|
178
|
+
},
|
|
179
|
+
...meta,
|
|
180
|
+
});
|
|
181
|
+
return toFindingDto(row);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The window is anchored to the last completed run, not to the wall clock. BullMQ
|
|
186
|
+
* repeatable jobs are delayed jobs: a tick missed while no worker was running is
|
|
187
|
+
* skipped, never backfilled. Against a fixed `now - lookbackHours` window that means
|
|
188
|
+
* any outage longer than `lookbackHours` leaves a span nothing ever reconciles and
|
|
189
|
+
* nothing ever reports - the worst possible failure mode for a compensating control.
|
|
190
|
+
* Catching up is capped, and a capped window is reported rather than passed over.
|
|
191
|
+
*/
|
|
192
|
+
async resolveWindow(until, lookbackHours) {
|
|
193
|
+
const lookbackStart = new Date(until.getTime() - lookbackHours * 3_600_000);
|
|
194
|
+
const [last] = await this.drizzle.db
|
|
195
|
+
.select({ finishedAt: walletJobRun.finishedAt })
|
|
196
|
+
.from(walletJobRun)
|
|
197
|
+
.where(and(eq(walletJobRun.jobName, JOB_NAME), eq(walletJobRun.status, 'completed')))
|
|
198
|
+
.orderBy(desc(walletJobRun.finishedAt))
|
|
199
|
+
.limit(1);
|
|
200
|
+
const anchor = last?.finishedAt;
|
|
201
|
+
if (!anchor || anchor >= lookbackStart) {
|
|
202
|
+
return { since: lookbackStart, unreconciledHours: 0 };
|
|
203
|
+
}
|
|
204
|
+
const floor = new Date(until.getTime() - lookbackHours * MAX_CATCH_UP_MULTIPLE * 3_600_000);
|
|
205
|
+
const since = anchor < floor ? floor : anchor;
|
|
206
|
+
return {
|
|
207
|
+
since,
|
|
208
|
+
unreconciledHours: Math.round((since.getTime() - anchor.getTime()) / 3_600_000),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Claim -> per-provider deposit/withdrawal diff -> stuck-withdrawal / stuck-sweep
|
|
213
|
+
* sweep -> finish + one audit entry + an alert past threshold. Returns null without
|
|
214
|
+
* doing any work when another cycle already owns the claim - the caller (cron tick or
|
|
215
|
+
* the on-demand route's worker) treats that as a normal, expected outcome.
|
|
216
|
+
*/
|
|
217
|
+
async runCycle(runId = randomUUID()) {
|
|
218
|
+
const jobRunId = await this.claimRun(runId);
|
|
219
|
+
if (!jobRunId) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const counts = {
|
|
223
|
+
missingDeposit: 0,
|
|
224
|
+
currencyMismatch: 0,
|
|
225
|
+
amountMismatch: 0,
|
|
226
|
+
withdrawalsReconciled: 0,
|
|
227
|
+
unknownAtProvider: 0,
|
|
228
|
+
stuckSweeps: 0,
|
|
229
|
+
unreconciledHours: 0,
|
|
230
|
+
};
|
|
231
|
+
try {
|
|
232
|
+
const cfg = this.platformConfig?.wallet?.reconciliation;
|
|
233
|
+
if (cfg) {
|
|
234
|
+
const until = new Date();
|
|
235
|
+
const { since, unreconciledHours } = await this.resolveWindow(until, cfg.lookbackHours);
|
|
236
|
+
counts.unreconciledHours = unreconciledHours;
|
|
237
|
+
if (unreconciledHours > 0) {
|
|
238
|
+
logger.error({ runId, unreconciledHours, since }, 'wallet reconciliation: catch-up window capped, an earlier span stays unreconciled');
|
|
239
|
+
}
|
|
240
|
+
for (const providerName of this.paymentProviders.names()) {
|
|
241
|
+
await this.reconcileProvider(runId, providerName, since, until, counts);
|
|
242
|
+
}
|
|
243
|
+
await this.reconcileStuckWithdrawals(runId, cfg.stuckAfterMinutes, counts);
|
|
244
|
+
// Deliberately not gated on `wallet.sweep` being configured. An operator can
|
|
245
|
+
// adopt reconciliation without sweeping, and a stuck sweep is real player money
|
|
246
|
+
// parked vendor-side in an ambiguous state - the last finding class that should
|
|
247
|
+
// quietly switch itself off because a different feature's config block is absent.
|
|
248
|
+
await this.reconcileStuckSweeps(runId, this.platformConfig?.wallet?.sweep?.unknownAfterMinutes ?? DEFAULT_UNKNOWN_AFTER_MINUTES, counts);
|
|
249
|
+
}
|
|
250
|
+
const openFindings = await this.countOpenFindings();
|
|
251
|
+
await this.finishRun(jobRunId, 'completed', { ...counts, openFindings });
|
|
252
|
+
await this.audit.record({
|
|
253
|
+
actorType: 'system',
|
|
254
|
+
action: 'wallet.reconciliation_run.completed',
|
|
255
|
+
resourceType: 'wallet_job_run',
|
|
256
|
+
resourceId: runId,
|
|
257
|
+
after: { runId, ...counts, openFindings },
|
|
258
|
+
});
|
|
259
|
+
if (cfg && openFindings > cfg.alertThreshold) {
|
|
260
|
+
logger.error({ runId, openFindings, threshold: cfg.alertThreshold }, 'wallet reconciliation: open findings exceed threshold');
|
|
261
|
+
this.events.emit('wallet.reconciliation.alert', {
|
|
262
|
+
runId,
|
|
263
|
+
openFindings,
|
|
264
|
+
threshold: cfg.alertThreshold,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
return { runId };
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
await this.finishRun(jobRunId, 'failed', {
|
|
271
|
+
...counts,
|
|
272
|
+
error: err instanceof Error ? err.message : String(err),
|
|
273
|
+
});
|
|
274
|
+
await this.audit.record({
|
|
275
|
+
actorType: 'system',
|
|
276
|
+
action: 'wallet.reconciliation_run.failed',
|
|
277
|
+
resourceType: 'wallet_job_run',
|
|
278
|
+
resourceId: runId,
|
|
279
|
+
after: { runId, ...counts },
|
|
280
|
+
});
|
|
281
|
+
throw err;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async reconcileProvider(runId, providerName, since, until, counts) {
|
|
285
|
+
const provider = this.paymentProviders.get(providerName);
|
|
286
|
+
if (!provider?.adapter.listTransactions) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const events = await provider.adapter.listTransactions({ since, until });
|
|
290
|
+
// Every sweep (an internal transfer of vendor-side funds, never a ledger row) shows
|
|
291
|
+
// up in the vendor's own transaction list too - exclude it BEFORE diffing, or every
|
|
292
|
+
// sweep files a false missing_deposit/unmatched-withdrawal finding.
|
|
293
|
+
const swept = await this.sweptExternalIds(providerName, since);
|
|
294
|
+
const relevant = events.filter((event) => !swept.has(event.externalId));
|
|
295
|
+
const deposits = relevant.filter((event) => event.kind === 'deposit');
|
|
296
|
+
const withdrawals = relevant.filter((event) => event.kind === 'withdrawal');
|
|
297
|
+
await this.reconcileDeposits(runId, providerName, deposits, counts);
|
|
298
|
+
for (const event of withdrawals) {
|
|
299
|
+
// Reconciliation is the same normalization a webhook produces, polled instead of
|
|
300
|
+
// pushed - already idempotent, already guards on status === 'processing'.
|
|
301
|
+
await this.wallet.reconcileWithdrawalStatus(event);
|
|
302
|
+
counts.withdrawalsReconciled += 1;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async sweptExternalIds(providerName, since) {
|
|
306
|
+
const rows = await this.drizzle.db
|
|
307
|
+
.select({ externalId: walletCustodySweep.externalId })
|
|
308
|
+
.from(walletCustodySweep)
|
|
309
|
+
.where(and(eq(walletCustodySweep.providerName, providerName), gte(walletCustodySweep.createdAt, since)));
|
|
310
|
+
return new Set(rows.map((row) => row.externalId).filter((id) => id !== null));
|
|
311
|
+
}
|
|
312
|
+
async reconcileDeposits(runId, providerName, deposits, counts) {
|
|
313
|
+
if (deposits.length === 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const byExternalId = await this.batchLookupByProviderRefId(deposits.map((d) => d.externalId));
|
|
317
|
+
for (const event of deposits) {
|
|
318
|
+
const tx = byExternalId.get(event.externalId);
|
|
319
|
+
const result = diffDeposit(event, tx);
|
|
320
|
+
if (result === null) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
counts[result === 'missing_deposit'
|
|
324
|
+
? 'missingDeposit'
|
|
325
|
+
: result === 'currency_mismatch'
|
|
326
|
+
? 'currencyMismatch'
|
|
327
|
+
: 'amountMismatch'] += 1;
|
|
328
|
+
await recordReconciliationFinding(this.drizzle.db, {
|
|
329
|
+
runId,
|
|
330
|
+
providerName,
|
|
331
|
+
kind: result,
|
|
332
|
+
currency: event.currency,
|
|
333
|
+
network: event.network ?? tx?.network ?? null,
|
|
334
|
+
amount: event.amount,
|
|
335
|
+
address: event.address,
|
|
336
|
+
tag: event.tag ?? null,
|
|
337
|
+
txHash: event.txHash,
|
|
338
|
+
externalId: event.externalId,
|
|
339
|
+
transactionId: tx?.id ?? null,
|
|
340
|
+
detail: result === 'currency_mismatch'
|
|
341
|
+
? `ledger currency ${tx?.currency}, vendor reported ${event.currency}`
|
|
342
|
+
: result === 'amount_mismatch'
|
|
343
|
+
? `ledger amount ${tx?.amount}, vendor reported ${event.amount}`
|
|
344
|
+
: null,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// Single chunked inArray(...) batch read (chunks well under the parameter ceiling) -
|
|
349
|
+
// never one query per vendor transaction over a window that is routinely thousands of rows.
|
|
350
|
+
async batchLookupByProviderRefId(externalIds) {
|
|
351
|
+
const byExternalId = new Map();
|
|
352
|
+
for (const batch of chunk(externalIds, PROVIDER_REF_LOOKUP_CHUNK_SIZE)) {
|
|
353
|
+
const rows = await this.drizzle.db
|
|
354
|
+
.select()
|
|
355
|
+
.from(walletTransaction)
|
|
356
|
+
.where(inArray(walletTransaction.providerRefId, batch));
|
|
357
|
+
for (const row of rows) {
|
|
358
|
+
if (row.providerRefId) {
|
|
359
|
+
byExternalId.set(row.providerRefId, row);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return byExternalId;
|
|
364
|
+
}
|
|
365
|
+
// Covered exactly by wallet_transaction_status_type_created_at_idx - equality on
|
|
366
|
+
// status and type, then a range on createdAt, in that column order.
|
|
367
|
+
async reconcileStuckWithdrawals(runId, stuckAfterMinutes, counts) {
|
|
368
|
+
const cutoff = new Date(Date.now() - stuckAfterMinutes * 60 * 1000);
|
|
369
|
+
const stuck = await this.drizzle.db
|
|
370
|
+
.select()
|
|
371
|
+
.from(walletTransaction)
|
|
372
|
+
.where(and(eq(walletTransaction.status, 'processing'), eq(walletTransaction.type, 'withdrawal'), lt(walletTransaction.createdAt, cutoff)));
|
|
373
|
+
for (const tx of stuck) {
|
|
374
|
+
const providerName = tx.providerName ?? DEFAULT_PAYMENT_PROVIDER;
|
|
375
|
+
const provider = this.paymentProviders.get(providerName);
|
|
376
|
+
// Nothing to look up at all (crashed before the vendor ever responded with a
|
|
377
|
+
// reference) - still worth a finding, deduped on the transaction's own id.
|
|
378
|
+
if (!tx.providerRefId) {
|
|
379
|
+
counts.unknownAtProvider += 1;
|
|
380
|
+
await recordReconciliationFinding(this.drizzle.db, {
|
|
381
|
+
runId,
|
|
382
|
+
providerName,
|
|
383
|
+
kind: 'unknown_at_provider',
|
|
384
|
+
currency: tx.currency,
|
|
385
|
+
network: tx.network,
|
|
386
|
+
amount: tx.amount,
|
|
387
|
+
transactionId: tx.id,
|
|
388
|
+
externalId: tx.id,
|
|
389
|
+
detail: 'withdrawal has no providerRefId to look up at the vendor',
|
|
390
|
+
});
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const status = await provider?.adapter.getWithdrawalStatus?.(tx.providerRefId);
|
|
394
|
+
if (status) {
|
|
395
|
+
await this.wallet.reconcileWithdrawalStatus({
|
|
396
|
+
kind: 'withdrawal',
|
|
397
|
+
externalId: tx.providerRefId,
|
|
398
|
+
status: status.status,
|
|
399
|
+
...(status.txHash ? { txHash: status.txHash } : {}),
|
|
400
|
+
});
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
counts.unknownAtProvider += 1;
|
|
404
|
+
await recordReconciliationFinding(this.drizzle.db, {
|
|
405
|
+
runId,
|
|
406
|
+
providerName,
|
|
407
|
+
kind: 'unknown_at_provider',
|
|
408
|
+
currency: tx.currency,
|
|
409
|
+
network: tx.network,
|
|
410
|
+
amount: tx.amount,
|
|
411
|
+
transactionId: tx.id,
|
|
412
|
+
externalId: tx.providerRefId,
|
|
413
|
+
detail: 'vendor has no record of this withdrawal',
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// Covered exactly by wallet_custody_sweep_status_created_at_idx. Human resolution
|
|
418
|
+
// only - this NEVER touches the sweep row's status or releases its in-flight guard.
|
|
419
|
+
async reconcileStuckSweeps(runId, unknownAfterMinutes, counts) {
|
|
420
|
+
const cutoff = new Date(Date.now() - unknownAfterMinutes * 60 * 1000);
|
|
421
|
+
const stuck = await this.drizzle.db
|
|
422
|
+
.select()
|
|
423
|
+
.from(walletCustodySweep)
|
|
424
|
+
.where(and(
|
|
425
|
+
// `pending` belongs here alongside `unknown`. A worker that dies between the
|
|
426
|
+
// claim insert and the vendor call leaves a `pending` row with no externalId:
|
|
427
|
+
// resolveInFlightSweeps skips it (nothing to poll) and the partial unique
|
|
428
|
+
// index still counts it as in-flight, so that container would never sweep
|
|
429
|
+
// again and nothing would say why. Same lost-response ambiguity as `unknown`,
|
|
430
|
+
// so it files a finding for a human rather than releasing the guard.
|
|
431
|
+
inArray(walletCustodySweep.status, ['pending', 'unknown']), lt(walletCustodySweep.createdAt, cutoff)));
|
|
432
|
+
for (const sweep of stuck) {
|
|
433
|
+
counts.stuckSweeps += 1;
|
|
434
|
+
await recordReconciliationFinding(this.drizzle.db, {
|
|
435
|
+
runId,
|
|
436
|
+
providerName: sweep.providerName,
|
|
437
|
+
kind: 'stuck_sweep',
|
|
438
|
+
currency: sweep.currency,
|
|
439
|
+
network: sweep.network,
|
|
440
|
+
amount: sweep.amount,
|
|
441
|
+
txHash: sweep.txHash,
|
|
442
|
+
externalId: sweep.externalId ?? sweep.id,
|
|
443
|
+
detail: `custody sweep ${sweep.id} has been ${sweep.status} since ${sweep.updatedAt.toISOString()}`,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async countOpenFindings() {
|
|
448
|
+
const [row] = await this.drizzle.db
|
|
449
|
+
.select({ n: count() })
|
|
450
|
+
.from(walletReconciliationFinding)
|
|
451
|
+
.where(eq(walletReconciliationFinding.status, 'open'));
|
|
452
|
+
return Number(row?.n ?? 0);
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* The claim IS the insert - a partial unique index on (jobName) WHERE finishedAt IS
|
|
456
|
+
* NULL makes a conflicting insert the concurrency guard. A stale in-flight run (older
|
|
457
|
+
* than the configured staleness window - presumed crashed) is marked `abandoned` and its slot freed
|
|
458
|
+
* for this call to retry the claim once.
|
|
459
|
+
*/
|
|
460
|
+
async claimRun(runId) {
|
|
461
|
+
const claimed = await this.retryClaim(runId);
|
|
462
|
+
if (claimed) {
|
|
463
|
+
return claimed;
|
|
464
|
+
}
|
|
465
|
+
const [existing] = await this.drizzle.db
|
|
466
|
+
.select()
|
|
467
|
+
.from(walletJobRun)
|
|
468
|
+
.where(and(eq(walletJobRun.jobName, JOB_NAME), isNull(walletJobRun.finishedAt)));
|
|
469
|
+
if (!existing) {
|
|
470
|
+
// The blocking run finished between our insert conflict and this read - retry once.
|
|
471
|
+
return this.retryClaim(runId);
|
|
472
|
+
}
|
|
473
|
+
const staleAfterMs = (this.platformConfig?.wallet?.reconciliation?.staleRunAfterMinutes ??
|
|
474
|
+
DEFAULT_STALE_RUN_AFTER_MINUTES) * 60_000;
|
|
475
|
+
if (existing.startedAt.getTime() >= Date.now() - staleAfterMs) {
|
|
476
|
+
// A live run genuinely owns the claim - return immediately, no retry loop.
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const abandoned = await this.drizzle.db
|
|
480
|
+
.update(walletJobRun)
|
|
481
|
+
.set({ status: 'abandoned', finishedAt: new Date() })
|
|
482
|
+
.where(and(eq(walletJobRun.id, existing.id), isNull(walletJobRun.finishedAt)))
|
|
483
|
+
.returning({ id: walletJobRun.id });
|
|
484
|
+
if (abandoned.length === 0) {
|
|
485
|
+
// Someone else already resolved the stale run concurrently.
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
return this.retryClaim(runId);
|
|
489
|
+
}
|
|
490
|
+
async retryClaim(runId) {
|
|
491
|
+
const [inserted] = await this.drizzle.db
|
|
492
|
+
.insert(walletJobRun)
|
|
493
|
+
.values({ jobName: JOB_NAME, runId })
|
|
494
|
+
.onConflictDoNothing()
|
|
495
|
+
.returning({ id: walletJobRun.id });
|
|
496
|
+
return inserted?.id ?? null;
|
|
497
|
+
}
|
|
498
|
+
// Keyed on the claimed row's own id, never on runId: a job retried by the queue
|
|
499
|
+
// carries the same runId as the attempt that failed, so `WHERE run_id = ...` would
|
|
500
|
+
// reach back and rewrite that earlier row's `failed`/`abandoned` verdict to
|
|
501
|
+
// `completed` - erasing the only evidence that the first attempt went wrong.
|
|
502
|
+
async finishRun(jobRunId, status, summary) {
|
|
503
|
+
await this.drizzle.db
|
|
504
|
+
.update(walletJobRun)
|
|
505
|
+
.set({ finishedAt: new Date(), status, summary })
|
|
506
|
+
.where(eq(walletJobRun.id, jobRunId));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
//# sourceMappingURL=reconciliation.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciliation.service.js","sourceRoot":"","sources":["../../../src/wallet/service/reconciliation.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,6 @@ export declare const AmbiguousNetworkError: new (currency: unknown, networks: un
|
|
|
22
22
|
export declare const UnsupportedNetworkError: new (currency: unknown, network: unknown) => Error;
|
|
23
23
|
export declare const WithdrawalDisabledError: new (currency: unknown) => Error;
|
|
24
24
|
export declare const BelowMinimumWithdrawalError: new (amount: unknown, minimum: unknown, currency: unknown, network: unknown) => Error;
|
|
25
|
-
export declare const CurrencyMismatchError: new (requested: unknown, walletCurrency: unknown) => Error;
|
|
26
25
|
export declare const AmbiguousDepositAddressError: new (address: unknown, network: unknown) => Error;
|
|
27
26
|
/** The catalog fields a payout decision needs - a structural subset of a wallet_asset row. */
|
|
28
27
|
type WithdrawalAsset = {
|
|
@@ -501,9 +500,15 @@ export declare class WalletService {
|
|
|
501
500
|
limit: number;
|
|
502
501
|
}>;
|
|
503
502
|
getOrCreateDepositAddress(userId: User['id'], currency: string, network?: string): Promise<DepositAddressResult>;
|
|
503
|
+
/**
|
|
504
|
+
* `providerName` is the vendor the webhook route already resolved (verifier + adapter
|
|
505
|
+
* came from the same registry entry) - it is only used to label a finding when this
|
|
506
|
+
* deposit can't be attributed, never to look anything up. Defaults to the single
|
|
507
|
+
* default binding for callers (tests, a poller with no named provider) that don't care.
|
|
508
|
+
*/
|
|
504
509
|
creditDepositByAddress(event: Extract<PaymentWebhookEvent, {
|
|
505
510
|
kind: 'deposit';
|
|
506
|
-
}
|
|
511
|
+
}>, providerName?: string): Promise<void>;
|
|
507
512
|
private userIdForWallet;
|
|
508
513
|
private findByIdempotencyKey;
|
|
509
514
|
private findDepositAddress;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.service.d.ts","sourceRoot":"","sources":["../../../src/wallet/service/wallet.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,EAMd,cAAc,EAWf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAEnB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAQL,KAAK,MAAM,EAEX,KAAK,iBAAiB,EAIvB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"wallet.service.d.ts","sourceRoot":"","sources":["../../../src/wallet/service/wallet.service.ts"],"names":[],"mappings":"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"}
|