@pacspace-io/sdk 0.1.0 → 0.2.1
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/README.md +67 -11
- package/dist/client.d.ts +34 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +296 -21
- package/dist/client.js.map +1 -1
- package/dist/errors/index.d.ts +24 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +44 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +51 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +107 -8
- package/dist/index.js.map +1 -1
- package/dist/resources/balance.d.ts +221 -15
- package/dist/resources/balance.d.ts.map +1 -1
- package/dist/resources/balance.js +772 -27
- package/dist/resources/balance.js.map +1 -1
- package/dist/resources/submission.d.ts +79 -0
- package/dist/resources/submission.d.ts.map +1 -0
- package/dist/resources/submission.js +398 -0
- package/dist/resources/submission.js.map +1 -0
- package/dist/types/balance.d.ts +493 -28
- package/dist/types/balance.d.ts.map +1 -1
- package/dist/types/common.d.ts +3 -3
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/config.d.ts +53 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/submission.d.ts +125 -0
- package/dist/types/submission.d.ts.map +1 -0
- package/dist/types/submission.js +3 -0
- package/dist/types/submission.js.map +1 -0
- package/dist/utils/polling.d.ts +2 -2
- package/dist/utils/polling.d.ts.map +1 -1
- package/dist/utils/polling.js +2 -6
- package/dist/utils/polling.js.map +1 -1
- package/dist/webhooks/index.d.ts +1 -1
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/types.d.ts +31 -31
- package/dist/webhooks/types.d.ts.map +1 -1
- package/dist/webhooks/types.js +0 -3
- package/dist/webhooks/types.js.map +1 -1
- package/dist/webhooks/verify.d.ts +5 -0
- package/dist/webhooks/verify.d.ts.map +1 -1
- package/dist/webhooks/verify.js +19 -4
- package/dist/webhooks/verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BalanceResource = void 0;
|
|
4
4
|
const polling_1 = require("../utils/polling");
|
|
5
|
+
const submission_1 = require("./submission");
|
|
6
|
+
const toRecordStatus = (status) => {
|
|
7
|
+
const normalized = String(status ?? '').toUpperCase();
|
|
8
|
+
if (normalized === 'PROCESSING')
|
|
9
|
+
return 'PROCESSING';
|
|
10
|
+
if (normalized === 'VERIFIED')
|
|
11
|
+
return 'VERIFIED';
|
|
12
|
+
if (normalized === 'FAILED')
|
|
13
|
+
return 'FAILED';
|
|
14
|
+
return 'QUEUED';
|
|
15
|
+
};
|
|
16
|
+
const toCheckpointType = (value) => {
|
|
17
|
+
return String(value) === 'recordId' ? 'recordId' : 'proofRoot';
|
|
18
|
+
};
|
|
19
|
+
const toApiCheckpointType = (value) => {
|
|
20
|
+
if (!value)
|
|
21
|
+
return undefined;
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
5
24
|
/**
|
|
6
25
|
* PacSpace Balance API resource.
|
|
7
26
|
*
|
|
@@ -15,8 +34,12 @@ const polling_1 = require("../utils/polling");
|
|
|
15
34
|
*/
|
|
16
35
|
class BalanceResource {
|
|
17
36
|
/** @internal */
|
|
18
|
-
constructor(client) {
|
|
37
|
+
constructor(client, submissionOptions) {
|
|
19
38
|
this.client = client;
|
|
39
|
+
this.submission = new submission_1.SubmissionCoordinator({
|
|
40
|
+
emitBatch: (deltas) => this.emitBatch(deltas),
|
|
41
|
+
options: submissionOptions,
|
|
42
|
+
});
|
|
20
43
|
}
|
|
21
44
|
// -------------------------------------------------------------------------
|
|
22
45
|
// Emit
|
|
@@ -51,7 +74,8 @@ class BalanceResource {
|
|
|
51
74
|
body.referenceId = referenceId;
|
|
52
75
|
if (metadata !== undefined)
|
|
53
76
|
body.metadata = metadata;
|
|
54
|
-
|
|
77
|
+
const response = await this.client.post('/api/v1/balance/delta', body, requestOptions);
|
|
78
|
+
return this.normalizeEmitResponse(response);
|
|
55
79
|
}
|
|
56
80
|
/**
|
|
57
81
|
* Record a delta and wait for it to be verified.
|
|
@@ -82,11 +106,139 @@ class BalanceResource {
|
|
|
82
106
|
signal,
|
|
83
107
|
});
|
|
84
108
|
// If already terminal, return immediately
|
|
85
|
-
if (['
|
|
109
|
+
if (['VERIFIED', 'FAILED'].includes(initial.status)) {
|
|
86
110
|
return initial;
|
|
87
111
|
}
|
|
88
|
-
// Poll for terminal status using the
|
|
89
|
-
|
|
112
|
+
// Poll for terminal status using the balance delta endpoint, then merge
|
|
113
|
+
// the latest status with the original emit metadata.
|
|
114
|
+
const terminalStatus = await (0, polling_1.pollUntilTerminal)(() => this.deltaStatus(initial.recordId, { signal }), { timeout, pollInterval, signal });
|
|
115
|
+
return this.mergeEmitWithStatus(initial, terminalStatus);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Check the status of a previously emitted delta.
|
|
119
|
+
*
|
|
120
|
+
* @param recordId - The record ID returned from emit.
|
|
121
|
+
* @param options - Request overrides.
|
|
122
|
+
* @returns Delta status with receipt and transaction details.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const status = await pac.balance.deltaStatus('rec_abc123');
|
|
127
|
+
* console.log(status.status); // 'QUEUED', 'PROCESSING', etc.
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
async deltaStatus(recordId, options) {
|
|
131
|
+
const response = await this.client.get(`/api/v1/balance/delta/${encodeURIComponent(recordId)}`, options);
|
|
132
|
+
return this.normalizeDeltaStatusResponse(response);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Alias for `deltaStatus()` with lifecycle-oriented naming.
|
|
136
|
+
*/
|
|
137
|
+
async getRecordStatus(recordId, options) {
|
|
138
|
+
return this.deltaStatus(recordId, options);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Poll record lifecycle until it reaches a terminal status.
|
|
142
|
+
*
|
|
143
|
+
* Terminal statuses are `VERIFIED` and `FAILED`.
|
|
144
|
+
*/
|
|
145
|
+
async waitForVerified(recordId, options) {
|
|
146
|
+
const { timeout = 60000, pollInterval = 2000, signal, ...requestOptions } = options ?? {};
|
|
147
|
+
return (0, polling_1.pollUntilTerminal)(() => this.getRecordStatus(recordId, {
|
|
148
|
+
...requestOptions,
|
|
149
|
+
signal,
|
|
150
|
+
}), { timeout, pollInterval, signal });
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Retrieve tenant usage counters and remaining allotment.
|
|
154
|
+
*/
|
|
155
|
+
async usage(options) {
|
|
156
|
+
return this.client.get('/api/v1/balance/usage', options);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Detect missing per-customer sequence ranges.
|
|
160
|
+
*
|
|
161
|
+
* Use this to identify gaps and re-emit missing deltas safely.
|
|
162
|
+
*/
|
|
163
|
+
async gaps(customerId, options) {
|
|
164
|
+
const { fromSequence, toSequence, limit, ...requestOptions } = options ?? {};
|
|
165
|
+
const params = new URLSearchParams();
|
|
166
|
+
if (fromSequence !== undefined)
|
|
167
|
+
params.set('fromSequence', fromSequence);
|
|
168
|
+
if (toSequence !== undefined)
|
|
169
|
+
params.set('toSequence', toSequence);
|
|
170
|
+
if (limit !== undefined)
|
|
171
|
+
params.set('limit', String(limit));
|
|
172
|
+
const query = params.toString();
|
|
173
|
+
const path = `/api/v1/balance/gaps/${encodeURIComponent(customerId)}${query ? `?${query}` : ''}`;
|
|
174
|
+
const response = await this.client.get(path, requestOptions);
|
|
175
|
+
return this.normalizeSequenceGapsResponse(response);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Record multiple deltas in a single batch request.
|
|
179
|
+
*
|
|
180
|
+
* Ideal for end-of-day reconciliation or importing historical data.
|
|
181
|
+
* Up to 100 deltas per batch.
|
|
182
|
+
*
|
|
183
|
+
* @param deltas - Array of deltas to record.
|
|
184
|
+
* @param options - Request overrides.
|
|
185
|
+
* @returns Per-delta results with totals.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const result = await pac.balance.emitBatch([
|
|
190
|
+
* { customerId: 'cust_123', delta: -100, reason: 'usage' },
|
|
191
|
+
* { customerId: 'cust_456', delta: -200, reason: 'usage' },
|
|
192
|
+
* ]);
|
|
193
|
+
* console.log(result.totalQueued); // 2
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
async emitBatch(deltas, options) {
|
|
197
|
+
const { ...requestOptions } = options ?? {};
|
|
198
|
+
const response = await this.client.post('/api/v1/balance/delta/batch', { deltas }, requestOptions);
|
|
199
|
+
return this.normalizeBulkEmitResponse(response);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Queue one tenant-produced summary for SDK-managed submission.
|
|
203
|
+
*/
|
|
204
|
+
queueSummary(summary) {
|
|
205
|
+
return this.submission.queueSummary(summary);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Queue multiple tenant-produced summaries.
|
|
209
|
+
*/
|
|
210
|
+
queueSummaries(summaries) {
|
|
211
|
+
return this.submission.queueSummaries(summaries);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Flush queued summaries immediately.
|
|
215
|
+
*/
|
|
216
|
+
async flushSummaries(options) {
|
|
217
|
+
return this.submission.flushSummaries(options);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Start periodic summary submission scheduling.
|
|
221
|
+
*/
|
|
222
|
+
startSummaryScheduler() {
|
|
223
|
+
this.submission.start();
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Stop periodic summary submission scheduling.
|
|
227
|
+
*/
|
|
228
|
+
stopSummaryScheduler() {
|
|
229
|
+
this.submission.stop();
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get queue/scheduler state for summary submission automation.
|
|
233
|
+
*/
|
|
234
|
+
getSummaryQueueState() {
|
|
235
|
+
return this.submission.getQueueState();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Stop scheduler and flush queued summaries (best for graceful shutdown).
|
|
239
|
+
*/
|
|
240
|
+
async shutdownSummaryScheduler() {
|
|
241
|
+
await this.submission.shutdown();
|
|
90
242
|
}
|
|
91
243
|
// -------------------------------------------------------------------------
|
|
92
244
|
// Derive
|
|
@@ -113,7 +265,7 @@ class BalanceResource {
|
|
|
113
265
|
* ```
|
|
114
266
|
*/
|
|
115
267
|
async derive(customerId, options) {
|
|
116
|
-
const { startingBalance, startingCheckpoint, startingCheckpointType, ...requestOptions } = options ?? {};
|
|
268
|
+
const { startingBalance, startingCheckpoint, startingCheckpointType, limit, offset, ...requestOptions } = options ?? {};
|
|
117
269
|
// Build query string
|
|
118
270
|
const params = new URLSearchParams();
|
|
119
271
|
if (startingBalance !== undefined) {
|
|
@@ -122,12 +274,20 @@ class BalanceResource {
|
|
|
122
274
|
if (startingCheckpoint !== undefined) {
|
|
123
275
|
params.set('startingCheckpoint', startingCheckpoint);
|
|
124
276
|
}
|
|
125
|
-
|
|
126
|
-
|
|
277
|
+
const apiCheckpointType = toApiCheckpointType(startingCheckpointType);
|
|
278
|
+
if (apiCheckpointType !== undefined) {
|
|
279
|
+
params.set('startingCheckpointType', apiCheckpointType);
|
|
280
|
+
}
|
|
281
|
+
if (limit !== undefined) {
|
|
282
|
+
params.set('limit', String(limit));
|
|
283
|
+
}
|
|
284
|
+
if (offset !== undefined) {
|
|
285
|
+
params.set('offset', String(offset));
|
|
127
286
|
}
|
|
128
287
|
const query = params.toString();
|
|
129
288
|
const path = `/api/v1/balance/derive/${encodeURIComponent(customerId)}${query ? `?${query}` : ''}`;
|
|
130
|
-
|
|
289
|
+
const response = await this.client.get(path, requestOptions);
|
|
290
|
+
return this.normalizeDeriveResponse(response);
|
|
131
291
|
}
|
|
132
292
|
// -------------------------------------------------------------------------
|
|
133
293
|
// Compare
|
|
@@ -167,10 +327,12 @@ class BalanceResource {
|
|
|
167
327
|
if (startingCheckpoint !== undefined) {
|
|
168
328
|
body.startingCheckpoint = startingCheckpoint;
|
|
169
329
|
}
|
|
170
|
-
|
|
171
|
-
|
|
330
|
+
const apiCheckpointType = toApiCheckpointType(startingCheckpointType);
|
|
331
|
+
if (apiCheckpointType !== undefined) {
|
|
332
|
+
body.startingCheckpointType = apiCheckpointType;
|
|
172
333
|
}
|
|
173
|
-
|
|
334
|
+
const response = await this.client.post('/api/v1/balance/compare', body, requestOptions);
|
|
335
|
+
return this.normalizeCompareResponse(response);
|
|
174
336
|
}
|
|
175
337
|
// -------------------------------------------------------------------------
|
|
176
338
|
// Receipt
|
|
@@ -178,22 +340,59 @@ class BalanceResource {
|
|
|
178
340
|
/**
|
|
179
341
|
* Generate a verifiable receipt for a customer.
|
|
180
342
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
343
|
+
* When `options.period` is provided, returns a period-specific receipt (proof root,
|
|
344
|
+
* verifyUrl, verificationReference) suitable for sharing on invoices. When
|
|
345
|
+
* omitted, returns the full record receipt with all verified deltas.
|
|
183
346
|
*
|
|
184
347
|
* @param customerId - The customer account to generate a receipt for.
|
|
185
|
-
* @param options -
|
|
186
|
-
* @returns Receipt with verification data.
|
|
348
|
+
* @param options - Optional period (YYYY-MM) and request overrides.
|
|
349
|
+
* @returns Receipt with verification data; shape depends on whether period is set.
|
|
187
350
|
*
|
|
188
351
|
* @example
|
|
189
352
|
* ```typescript
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* console.log(receipt.
|
|
353
|
+
* // Period-specific receipt (shareable proof for invoices)
|
|
354
|
+
* const receipt = await pac.balance.receipt('cust_123', { period: '2026-02' });
|
|
355
|
+
* console.log(receipt.proofRoot); // Include on invoice
|
|
356
|
+
* console.log(receipt.verifyUrl); // Share with counterparty
|
|
357
|
+
*
|
|
358
|
+
* // Full record receipt
|
|
359
|
+
* const full = await pac.balance.receipt('cust_123');
|
|
360
|
+
* console.log(full.finalBalance);
|
|
193
361
|
* ```
|
|
194
362
|
*/
|
|
195
363
|
async receipt(customerId, options) {
|
|
196
|
-
|
|
364
|
+
const opts = options ?? {};
|
|
365
|
+
const hasScopedReceipt = opts.period !== undefined ||
|
|
366
|
+
opts.timePreset !== undefined ||
|
|
367
|
+
opts.startDate !== undefined ||
|
|
368
|
+
opts.endDate !== undefined;
|
|
369
|
+
if (hasScopedReceipt) {
|
|
370
|
+
return this.receiptForPeriod(customerId, opts);
|
|
371
|
+
}
|
|
372
|
+
const { period: _period, timePreset: _timePreset, startDate: _startDate, endDate: _endDate, ...requestOptions } = opts;
|
|
373
|
+
const hasOverrides = Object.keys(requestOptions).length > 0;
|
|
374
|
+
const response = await this.client.get(`/api/v1/balance/receipt/${encodeURIComponent(customerId)}`, hasOverrides ? requestOptions : undefined);
|
|
375
|
+
return this.normalizeReceiptResponse(response);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* @internal
|
|
379
|
+
* Generate a period-specific receipt (proof root, verifyUrl). Used by receipt().
|
|
380
|
+
*/
|
|
381
|
+
async receiptForPeriod(customerId, options) {
|
|
382
|
+
const { period, timePreset, startDate, endDate, ...requestOptions } = options ?? {};
|
|
383
|
+
const params = new URLSearchParams();
|
|
384
|
+
if (period !== undefined)
|
|
385
|
+
params.set('period', period);
|
|
386
|
+
if (timePreset !== undefined)
|
|
387
|
+
params.set('timePreset', timePreset);
|
|
388
|
+
if (startDate !== undefined)
|
|
389
|
+
params.set('startDate', startDate);
|
|
390
|
+
if (endDate !== undefined)
|
|
391
|
+
params.set('endDate', endDate);
|
|
392
|
+
const query = params.toString();
|
|
393
|
+
const path = `/api/v1/balance/invoice-proof/${encodeURIComponent(customerId)}${query ? `?${query}` : ''}`;
|
|
394
|
+
const response = await this.client.get(path, requestOptions);
|
|
395
|
+
return this.normalizeInvoiceProofResponse(response);
|
|
197
396
|
}
|
|
198
397
|
// -------------------------------------------------------------------------
|
|
199
398
|
// Checkpoint
|
|
@@ -201,30 +400,576 @@ class BalanceResource {
|
|
|
201
400
|
/**
|
|
202
401
|
* Commit a period-end checkpoint.
|
|
203
402
|
*
|
|
204
|
-
* Computes a
|
|
205
|
-
* and
|
|
206
|
-
* for instant counterparty verification.
|
|
403
|
+
* Computes a proof root over all verified deltas in the billing window
|
|
404
|
+
* and records it on the public verification layer. The proof root can be
|
|
405
|
+
* included in invoices for instant counterparty verification.
|
|
207
406
|
*
|
|
208
407
|
* @param customerId - Customer to checkpoint (omit for all customers).
|
|
209
408
|
* @param options - Period (YYYY-MM) and request overrides.
|
|
210
|
-
* @returns Checkpoint details with
|
|
409
|
+
* @returns Checkpoint details with proof root and status.
|
|
211
410
|
*
|
|
212
411
|
* @example
|
|
213
412
|
* ```typescript
|
|
214
413
|
* const checkpoint = await pac.balance.checkpoint('cust_123', {
|
|
215
414
|
* period: '2026-02',
|
|
216
415
|
* });
|
|
217
|
-
* console.log(checkpoint.
|
|
416
|
+
* console.log(checkpoint.proofRoot); // Include in your invoice
|
|
218
417
|
* ```
|
|
219
418
|
*/
|
|
220
419
|
async checkpoint(customerId, options) {
|
|
221
|
-
const { period, ...requestOptions } = options ?? {};
|
|
420
|
+
const { period, timePreset, startDate, endDate, mode, fingerprints, ...requestOptions } = options ?? {};
|
|
222
421
|
const body = {};
|
|
223
422
|
if (customerId !== undefined)
|
|
224
423
|
body.customerId = customerId;
|
|
225
424
|
if (period !== undefined)
|
|
226
425
|
body.period = period;
|
|
227
|
-
|
|
426
|
+
if (timePreset !== undefined)
|
|
427
|
+
body.timePreset = timePreset;
|
|
428
|
+
if (startDate !== undefined)
|
|
429
|
+
body.startDate = startDate;
|
|
430
|
+
if (endDate !== undefined)
|
|
431
|
+
body.endDate = endDate;
|
|
432
|
+
if (mode !== undefined)
|
|
433
|
+
body.mode = mode;
|
|
434
|
+
if (fingerprints !== undefined)
|
|
435
|
+
body.fingerprints = fingerprints;
|
|
436
|
+
const response = await this.client.post('/api/v1/balance/checkpoint', body, requestOptions);
|
|
437
|
+
return this.normalizeCheckpointResponse(response);
|
|
438
|
+
}
|
|
439
|
+
// -------------------------------------------------------------------------
|
|
440
|
+
// List Checkpoints
|
|
441
|
+
// -------------------------------------------------------------------------
|
|
442
|
+
/**
|
|
443
|
+
* List committed checkpoints for your tenant.
|
|
444
|
+
*
|
|
445
|
+
* Returns a paginated list of checkpoints, optionally filtered by
|
|
446
|
+
* customer ID and/or billing period.
|
|
447
|
+
*
|
|
448
|
+
* @param options - Filter and pagination options.
|
|
449
|
+
* @returns Paginated list of checkpoints.
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```typescript
|
|
453
|
+
* const { checkpoints } = await pac.balance.listCheckpoints({
|
|
454
|
+
* period: '2026-02',
|
|
455
|
+
* limit: 10,
|
|
456
|
+
* });
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
async listCheckpoints(options) {
|
|
460
|
+
const { customerId, period, timePreset, startDate, endDate, limit, offset, ...requestOptions } = options ?? {};
|
|
461
|
+
const params = new URLSearchParams();
|
|
462
|
+
if (customerId !== undefined)
|
|
463
|
+
params.set('customerId', customerId);
|
|
464
|
+
if (period !== undefined)
|
|
465
|
+
params.set('period', period);
|
|
466
|
+
if (timePreset !== undefined)
|
|
467
|
+
params.set('timePreset', timePreset);
|
|
468
|
+
if (startDate !== undefined)
|
|
469
|
+
params.set('startDate', startDate);
|
|
470
|
+
if (endDate !== undefined)
|
|
471
|
+
params.set('endDate', endDate);
|
|
472
|
+
if (limit !== undefined)
|
|
473
|
+
params.set('limit', String(limit));
|
|
474
|
+
if (offset !== undefined)
|
|
475
|
+
params.set('offset', String(offset));
|
|
476
|
+
const query = params.toString();
|
|
477
|
+
const path = `/api/v1/balance/checkpoints${query ? `?${query}` : ''}`;
|
|
478
|
+
const response = await this.client.get(path, requestOptions);
|
|
479
|
+
return this.normalizeListCheckpointsResponse(response);
|
|
480
|
+
}
|
|
481
|
+
// -------------------------------------------------------------------------
|
|
482
|
+
// Webhook Deliveries
|
|
483
|
+
// -------------------------------------------------------------------------
|
|
484
|
+
/**
|
|
485
|
+
* List webhook delivery history.
|
|
486
|
+
*
|
|
487
|
+
* @param options - Filter and pagination options.
|
|
488
|
+
* @returns Paginated list of webhook deliveries.
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```typescript
|
|
492
|
+
* const { deliveries } = await pac.balance.listWebhookDeliveries({
|
|
493
|
+
* status: 'failed',
|
|
494
|
+
* limit: 10,
|
|
495
|
+
* });
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
async listWebhookDeliveries(options) {
|
|
499
|
+
const { status, limit, offset, ...requestOptions } = options ?? {};
|
|
500
|
+
const params = new URLSearchParams();
|
|
501
|
+
if (status !== undefined)
|
|
502
|
+
params.set('status', status);
|
|
503
|
+
if (limit !== undefined)
|
|
504
|
+
params.set('limit', String(limit));
|
|
505
|
+
if (offset !== undefined)
|
|
506
|
+
params.set('offset', String(offset));
|
|
507
|
+
const query = params.toString();
|
|
508
|
+
const path = `/api/v1/balance/webhooks${query ? `?${query}` : ''}`;
|
|
509
|
+
return this.client.get(path, requestOptions);
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Retry a failed webhook delivery.
|
|
513
|
+
*
|
|
514
|
+
* @param eventId - The event ID of the failed delivery.
|
|
515
|
+
* @param options - Request overrides.
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```typescript
|
|
519
|
+
* await pac.balance.retryWebhook('evt_abc123');
|
|
520
|
+
* ```
|
|
521
|
+
*/
|
|
522
|
+
async retryWebhook(eventId, options) {
|
|
523
|
+
return this.client.post(`/api/v1/balance/webhooks/${encodeURIComponent(eventId)}/retry`, {}, options);
|
|
524
|
+
}
|
|
525
|
+
// -------------------------------------------------------------------------
|
|
526
|
+
// Customer Ledgers
|
|
527
|
+
// -------------------------------------------------------------------------
|
|
528
|
+
/**
|
|
529
|
+
* List all customer balance records for your account.
|
|
530
|
+
*
|
|
531
|
+
* Each unique customerId passed to emit() automatically creates an
|
|
532
|
+
* isolated customer record. This method returns a paginated list.
|
|
533
|
+
*
|
|
534
|
+
* @param options - Search, pagination, and request overrides.
|
|
535
|
+
* @returns Paginated list of customer records.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* ```typescript
|
|
539
|
+
* const { customers } = await pac.balance.customers();
|
|
540
|
+
* for (const c of customers) {
|
|
541
|
+
* console.log(c.customerId, c.totalDeltas);
|
|
542
|
+
* }
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
545
|
+
async customers(options) {
|
|
546
|
+
const { search, limit, page, ...requestOptions } = options ?? {};
|
|
547
|
+
const params = new URLSearchParams();
|
|
548
|
+
if (search !== undefined)
|
|
549
|
+
params.set('search', search);
|
|
550
|
+
if (limit !== undefined)
|
|
551
|
+
params.set('limit', String(limit));
|
|
552
|
+
if (page !== undefined)
|
|
553
|
+
params.set('page', String(page));
|
|
554
|
+
const query = params.toString();
|
|
555
|
+
const path = `/api/v1/balance/customers${query ? `?${query}` : ''}`;
|
|
556
|
+
const response = await this.client.get(path, requestOptions);
|
|
557
|
+
return this.normalizeListCustomersResponse(response);
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Get the full record detail for a specific customer.
|
|
561
|
+
*
|
|
562
|
+
* Returns the derived customer reference, computed balance, delta count,
|
|
563
|
+
* and latest checkpoint. The customer reference is deterministic.
|
|
564
|
+
*
|
|
565
|
+
* @param customerId - The customer to look up.
|
|
566
|
+
* @param options - Activity pagination and request overrides.
|
|
567
|
+
* @returns Customer detail including balance and references.
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript
|
|
571
|
+
* const customer = await pac.balance.customer('cust_001');
|
|
572
|
+
* console.log(customer.customerReference); // 0xA1b2...Ef34
|
|
573
|
+
* console.log(customer.computedBalance); // 4500.00
|
|
574
|
+
* ```
|
|
575
|
+
*/
|
|
576
|
+
async customer(customerId, options) {
|
|
577
|
+
const { deltaPage, deltaLimit, ...requestOptions } = options ?? {};
|
|
578
|
+
const params = new URLSearchParams();
|
|
579
|
+
if (deltaPage !== undefined)
|
|
580
|
+
params.set('deltaPage', String(deltaPage));
|
|
581
|
+
if (deltaLimit !== undefined)
|
|
582
|
+
params.set('deltaLimit', String(deltaLimit));
|
|
583
|
+
const query = params.toString();
|
|
584
|
+
const path = `/api/v1/balance/customers/${encodeURIComponent(customerId)}${query ? `?${query}` : ''}`;
|
|
585
|
+
const response = await this.client.get(path, requestOptions);
|
|
586
|
+
return this.normalizeCustomerDetailResponse(response);
|
|
587
|
+
}
|
|
588
|
+
normalizeEmitResponse(data) {
|
|
589
|
+
const proofRoot = String(data.proofRoot ?? data.receiptId ?? '');
|
|
590
|
+
return {
|
|
591
|
+
recordId: String(data.recordId ?? ''),
|
|
592
|
+
customerId: String(data.customerId ?? ''),
|
|
593
|
+
delta: Number(data.delta ?? 0),
|
|
594
|
+
sequenceNumber: data.sequenceNumber == null ? undefined : String(data.sequenceNumber),
|
|
595
|
+
status: toRecordStatus(data.status),
|
|
596
|
+
receiptId: String(data.receiptId ?? proofRoot),
|
|
597
|
+
proofRoot,
|
|
598
|
+
itemHashes: Array.isArray(data.itemHashes)
|
|
599
|
+
? data.itemHashes.map((value) => String(value))
|
|
600
|
+
: [],
|
|
601
|
+
estimatedVerifiedDeltas: Number(data.estimatedVerifiedDeltas ?? 0),
|
|
602
|
+
estimatedCredits: Number(data.estimatedCredits ?? 0),
|
|
603
|
+
receivedAt: String(data.receivedAt ?? ''),
|
|
604
|
+
message: String(data.message ?? ''),
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
mergeEmitWithStatus(initial, status) {
|
|
608
|
+
const firstDelta = status.deltas[0];
|
|
609
|
+
const customerId = status.customerId ?? firstDelta?.customerId ?? initial.customerId;
|
|
610
|
+
const delta = status.delta ?? firstDelta?.delta ?? initial.delta;
|
|
611
|
+
const sequenceNumber = firstDelta?.sequenceNumber ?? initial.sequenceNumber;
|
|
612
|
+
return {
|
|
613
|
+
...initial,
|
|
614
|
+
recordId: status.recordId || initial.recordId,
|
|
615
|
+
customerId: customerId == null ? initial.customerId : String(customerId),
|
|
616
|
+
delta: delta == null ? initial.delta : Number(delta),
|
|
617
|
+
sequenceNumber: sequenceNumber ?? undefined,
|
|
618
|
+
status: status.status,
|
|
619
|
+
receiptId: status.receiptId ?? initial.receiptId,
|
|
620
|
+
proofRoot: status.receiptId ?? initial.proofRoot,
|
|
621
|
+
receivedAt: status.receivedAt || initial.receivedAt,
|
|
622
|
+
message: status.status === 'VERIFIED'
|
|
623
|
+
? 'Delta verified.'
|
|
624
|
+
: status.status === 'FAILED'
|
|
625
|
+
? 'Delta verification failed.'
|
|
626
|
+
: initial.message,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
normalizeDeltaStatusResponse(data) {
|
|
630
|
+
const deltas = Array.isArray(data.deltas)
|
|
631
|
+
? data.deltas.map((entry) => {
|
|
632
|
+
const item = entry;
|
|
633
|
+
return {
|
|
634
|
+
customerId: item.customerId == null ? null : String(item.customerId),
|
|
635
|
+
delta: item.delta == null ? null : Number(item.delta),
|
|
636
|
+
sequenceNumber: item.sequenceNumber == null ? null : String(item.sequenceNumber),
|
|
637
|
+
};
|
|
638
|
+
})
|
|
639
|
+
: [];
|
|
640
|
+
return {
|
|
641
|
+
recordId: String(data.recordId ?? ''),
|
|
642
|
+
status: toRecordStatus(data.status),
|
|
643
|
+
deltaCount: Number(data.deltaCount ?? deltas.length),
|
|
644
|
+
customerId: data.customerId == null ? null : String(data.customerId),
|
|
645
|
+
delta: data.delta == null ? null : Number(data.delta),
|
|
646
|
+
deltas,
|
|
647
|
+
receiptId: data.receiptId == null ? null : String(data.receiptId),
|
|
648
|
+
verificationReference: data.verificationReference == null ? null : String(data.verificationReference),
|
|
649
|
+
receivedAt: String(data.receivedAt ?? ''),
|
|
650
|
+
verifiedAt: data.verifiedAt == null ? null : String(data.verifiedAt),
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
normalizeDeriveResponse(data) {
|
|
654
|
+
const deltas = Array.isArray(data.deltas)
|
|
655
|
+
? data.deltas.map((entry) => {
|
|
656
|
+
const item = entry;
|
|
657
|
+
const proofRoot = String(item.proofRoot ?? item.receiptId ?? '');
|
|
658
|
+
return {
|
|
659
|
+
recordId: String(item.recordId ?? ''),
|
|
660
|
+
itemHash: String(item.itemHash ?? ''),
|
|
661
|
+
proofRoot,
|
|
662
|
+
receiptId: String(item.receiptId ?? proofRoot),
|
|
663
|
+
sequenceNumber: item.sequenceNumber == null ? null : String(item.sequenceNumber),
|
|
664
|
+
delta: Number(item.delta ?? 0),
|
|
665
|
+
reason: item.reason == null ? null : String(item.reason),
|
|
666
|
+
referenceId: item.referenceId == null ? null : String(item.referenceId),
|
|
667
|
+
window: String(item.window ?? ''),
|
|
668
|
+
declaredTimestamp: item.declaredTimestamp == null
|
|
669
|
+
? null
|
|
670
|
+
: String(item.declaredTimestamp),
|
|
671
|
+
blockTimestamp: item.blockTimestamp == null ? null : String(item.blockTimestamp),
|
|
672
|
+
dataPurged: Boolean(item.dataPurged),
|
|
673
|
+
verified: true,
|
|
674
|
+
};
|
|
675
|
+
})
|
|
676
|
+
: [];
|
|
677
|
+
const verificationProof = (data.verificationProof ??
|
|
678
|
+
{});
|
|
679
|
+
const windowSummaries = Array.isArray(data.windowSummaries)
|
|
680
|
+
? data.windowSummaries.map((entry) => {
|
|
681
|
+
const item = entry;
|
|
682
|
+
return {
|
|
683
|
+
window: String(item.window ?? ''),
|
|
684
|
+
deltasCount: Number(item.deltasCount ?? 0),
|
|
685
|
+
netDelta: Number(item.netDelta ?? 0),
|
|
686
|
+
firstBlockTimestamp: item.firstBlockTimestamp == null
|
|
687
|
+
? null
|
|
688
|
+
: String(item.firstBlockTimestamp),
|
|
689
|
+
lastBlockTimestamp: item.lastBlockTimestamp == null
|
|
690
|
+
? null
|
|
691
|
+
: String(item.lastBlockTimestamp),
|
|
692
|
+
};
|
|
693
|
+
})
|
|
694
|
+
: [];
|
|
695
|
+
const pagination = (data.pagination ?? {});
|
|
696
|
+
const hint = data._hint;
|
|
697
|
+
return {
|
|
698
|
+
customerId: String(data.customerId ?? ''),
|
|
699
|
+
startingBalance: Number(data.startingBalance ?? 0),
|
|
700
|
+
startingCheckpoint: String(data.startingCheckpoint ?? 'genesis'),
|
|
701
|
+
startingCheckpointType: toCheckpointType(data.startingCheckpointType),
|
|
702
|
+
deltasCount: Number(data.deltasCount ?? deltas.length),
|
|
703
|
+
computedBalance: Number(data.computedBalance ?? 0),
|
|
704
|
+
latestCheckpoint: data.latestCheckpoint == null ? null : String(data.latestCheckpoint),
|
|
705
|
+
latestReceiptId: data.latestReceiptId == null ? null : String(data.latestReceiptId),
|
|
706
|
+
deltas,
|
|
707
|
+
windowSummaries,
|
|
708
|
+
verificationProof: {
|
|
709
|
+
proofRoot: verificationProof.proofRoot == null
|
|
710
|
+
? null
|
|
711
|
+
: String(verificationProof.proofRoot),
|
|
712
|
+
message: String(verificationProof.message ?? ''),
|
|
713
|
+
},
|
|
714
|
+
pagination: {
|
|
715
|
+
total: Number(pagination.total ?? deltas.length),
|
|
716
|
+
limit: Number(pagination.limit ?? deltas.length),
|
|
717
|
+
offset: Number(pagination.offset ?? 0),
|
|
718
|
+
},
|
|
719
|
+
_hint: hint == null
|
|
720
|
+
? undefined
|
|
721
|
+
: {
|
|
722
|
+
message: String(hint.message ?? ''),
|
|
723
|
+
recommendation: String(hint.recommendation ?? ''),
|
|
724
|
+
docsUrl: String(hint.docsUrl ?? ''),
|
|
725
|
+
},
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
normalizeCompareResponse(data) {
|
|
729
|
+
const proof = (data.proof ?? {});
|
|
730
|
+
return {
|
|
731
|
+
customerId: String(data.customerId ?? ''),
|
|
732
|
+
yourBalance: Number(data.yourBalance ?? 0),
|
|
733
|
+
theirBalance: Number(data.theirBalance ?? 0),
|
|
734
|
+
neutralBalance: Number(data.neutralBalance ?? 0),
|
|
735
|
+
matchesYours: Boolean(data.matchesYours),
|
|
736
|
+
matchesTheirs: Boolean(data.matchesTheirs),
|
|
737
|
+
deltasVerified: Number(data.deltasVerified ?? 0),
|
|
738
|
+
discrepancyReport: data.discrepancyReport ?? null,
|
|
739
|
+
proof: {
|
|
740
|
+
proofRoot: proof.proofRoot == null ? null : String(proof.proofRoot),
|
|
741
|
+
latestCheckpoint: proof.latestCheckpoint == null ? null : String(proof.latestCheckpoint),
|
|
742
|
+
windowSummaries: proof.windowSummaries ??
|
|
743
|
+
[],
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
normalizeReceiptResponse(data) {
|
|
748
|
+
const verification = (data.verification ?? {});
|
|
749
|
+
return {
|
|
750
|
+
customerId: String(data.customerId ?? ''),
|
|
751
|
+
generatedAt: String(data.generatedAt ?? ''),
|
|
752
|
+
deltasCount: Number(data.deltasCount ?? 0),
|
|
753
|
+
finalBalance: Number(data.finalBalance ?? 0),
|
|
754
|
+
proofRoot: data.proofRoot == null ? null : String(data.proofRoot),
|
|
755
|
+
receiptId: data.receiptId == null ? null : String(data.receiptId),
|
|
756
|
+
latestCheckpoint: data.latestCheckpoint == null ? null : String(data.latestCheckpoint),
|
|
757
|
+
deltas: data.deltas ?? [],
|
|
758
|
+
windowSummaries: data.windowSummaries ?? [],
|
|
759
|
+
verification: {
|
|
760
|
+
message: String(verification.message ?? ''),
|
|
761
|
+
itemHashes: Array.isArray(verification.itemHashes)
|
|
762
|
+
? verification.itemHashes.map((value) => String(value))
|
|
763
|
+
: [],
|
|
764
|
+
},
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
normalizeInvoiceProofResponse(data) {
|
|
768
|
+
return {
|
|
769
|
+
customerId: String(data.customerId ?? ''),
|
|
770
|
+
period: String(data.period ?? ''),
|
|
771
|
+
proofRoot: String(data.proofRoot ?? ''),
|
|
772
|
+
verificationReference: data.verificationReference == null
|
|
773
|
+
? null
|
|
774
|
+
: String(data.verificationReference),
|
|
775
|
+
verificationExplorerUrl: data.verificationExplorerUrl == null
|
|
776
|
+
? null
|
|
777
|
+
: String(data.verificationExplorerUrl),
|
|
778
|
+
verifyUrl: data.verifyUrl == null ? null : String(data.verifyUrl),
|
|
779
|
+
deltaCount: Number(data.deltaCount ?? 0),
|
|
780
|
+
startingBalance: Number(data.startingBalance ?? 0),
|
|
781
|
+
finalBalance: Number(data.finalBalance ?? 0),
|
|
782
|
+
windowSummary: data.windowSummary ??
|
|
783
|
+
{
|
|
784
|
+
window: '',
|
|
785
|
+
deltasCount: 0,
|
|
786
|
+
netDelta: 0,
|
|
787
|
+
firstDeltaAt: null,
|
|
788
|
+
lastDeltaAt: null,
|
|
789
|
+
},
|
|
790
|
+
deltas: data.deltas ?? [],
|
|
791
|
+
verification: data.verification ??
|
|
792
|
+
{
|
|
793
|
+
proofRoot: null,
|
|
794
|
+
totalBalance: 0,
|
|
795
|
+
periodBalance: 0,
|
|
796
|
+
},
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
normalizeCheckpointResponse(data) {
|
|
800
|
+
return {
|
|
801
|
+
checkpointId: String(data.checkpointId ?? ''),
|
|
802
|
+
period: String(data.period ?? ''),
|
|
803
|
+
proofRoot: String(data.proofRoot ?? ''),
|
|
804
|
+
scope: data.scope,
|
|
805
|
+
mode: data.mode,
|
|
806
|
+
deltaCount: Number(data.deltaCount ?? 0),
|
|
807
|
+
selectedFingerprintCount: data.selectedFingerprintCount == null
|
|
808
|
+
? undefined
|
|
809
|
+
: Number(data.selectedFingerprintCount),
|
|
810
|
+
eligibleFingerprintCount: data.eligibleFingerprintCount == null
|
|
811
|
+
? undefined
|
|
812
|
+
: Number(data.eligibleFingerprintCount),
|
|
813
|
+
selectedFingerprints: Array.isArray(data.selectedFingerprints)
|
|
814
|
+
? data.selectedFingerprints.map((value) => String(value))
|
|
815
|
+
: undefined,
|
|
816
|
+
fromIndex: Number(data.fromIndex ?? 0),
|
|
817
|
+
toIndex: Number(data.toIndex ?? 0),
|
|
818
|
+
customerId: String(data.customerId ?? ''),
|
|
819
|
+
status: toRecordStatus(data.status),
|
|
820
|
+
message: String(data.message ?? ''),
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
normalizeListCheckpointsResponse(data) {
|
|
824
|
+
const checkpoints = Array.isArray(data.checkpoints)
|
|
825
|
+
? data.checkpoints.map((entry) => {
|
|
826
|
+
const item = entry;
|
|
827
|
+
return {
|
|
828
|
+
checkpointId: String(item.checkpointId ?? ''),
|
|
829
|
+
period: String(item.period ?? ''),
|
|
830
|
+
proofRoot: item.proofRoot == null ? null : String(item.proofRoot),
|
|
831
|
+
scope: item.scope,
|
|
832
|
+
mode: item.mode,
|
|
833
|
+
deltaCount: Number(item.deltaCount ?? 0),
|
|
834
|
+
selectedFingerprintCount: item.selectedFingerprintCount == null
|
|
835
|
+
? undefined
|
|
836
|
+
: Number(item.selectedFingerprintCount),
|
|
837
|
+
eligibleFingerprintCount: item.eligibleFingerprintCount == null
|
|
838
|
+
? undefined
|
|
839
|
+
: Number(item.eligibleFingerprintCount),
|
|
840
|
+
customerId: String(item.customerId ?? ''),
|
|
841
|
+
status: toRecordStatus(item.status),
|
|
842
|
+
verificationReference: item.verificationReference == null
|
|
843
|
+
? null
|
|
844
|
+
: String(item.verificationReference),
|
|
845
|
+
verifiedAt: item.verifiedAt == null ? null : String(item.verifiedAt),
|
|
846
|
+
receivedAt: String(item.receivedAt ?? ''),
|
|
847
|
+
};
|
|
848
|
+
})
|
|
849
|
+
: [];
|
|
850
|
+
const pagination = (data.pagination ?? {});
|
|
851
|
+
return {
|
|
852
|
+
checkpoints,
|
|
853
|
+
pagination: {
|
|
854
|
+
total: Number(pagination.total ?? checkpoints.length),
|
|
855
|
+
limit: Number(pagination.limit ?? checkpoints.length),
|
|
856
|
+
offset: Number(pagination.offset ?? 0),
|
|
857
|
+
},
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
normalizeSequenceGapsResponse(data) {
|
|
861
|
+
const gaps = Array.isArray(data.gaps)
|
|
862
|
+
? data.gaps.map((entry) => {
|
|
863
|
+
const item = entry;
|
|
864
|
+
return {
|
|
865
|
+
startSequence: String(item.startSequence ?? ''),
|
|
866
|
+
endSequence: String(item.endSequence ?? ''),
|
|
867
|
+
missingCount: String(item.missingCount ?? '0'),
|
|
868
|
+
};
|
|
869
|
+
})
|
|
870
|
+
: [];
|
|
871
|
+
return {
|
|
872
|
+
customerId: String(data.customerId ?? ''),
|
|
873
|
+
customerReference: String(data.customerReference ?? ''),
|
|
874
|
+
customerPartition: String(data.customerPartition ?? ''),
|
|
875
|
+
nextSequence: String(data.nextSequence ?? '0'),
|
|
876
|
+
rangeStart: String(data.rangeStart ?? '0'),
|
|
877
|
+
rangeEnd: String(data.rangeEnd ?? '0'),
|
|
878
|
+
gaps,
|
|
879
|
+
hasGaps: Boolean(data.hasGaps),
|
|
880
|
+
missingRanges: Number(data.missingRanges ?? gaps.length),
|
|
881
|
+
missingCountInPage: String(data.missingCountInPage ?? '0'),
|
|
882
|
+
truncated: Boolean(data.truncated),
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
normalizeBulkEmitResponse(data) {
|
|
886
|
+
const results = Array.isArray(data.results)
|
|
887
|
+
? data.results.map((entry) => {
|
|
888
|
+
const item = entry;
|
|
889
|
+
return {
|
|
890
|
+
index: Number(item.index ?? 0),
|
|
891
|
+
customerId: String(item.customerId ?? ''),
|
|
892
|
+
delta: Number(item.delta ?? 0),
|
|
893
|
+
recordId: item.recordId == null ? undefined : String(item.recordId),
|
|
894
|
+
itemHash: item.itemHash == null ? undefined : String(item.itemHash),
|
|
895
|
+
receiptId: item.receiptId == null ? undefined : String(item.receiptId),
|
|
896
|
+
referenceId: item.referenceId == null ? undefined : String(item.referenceId),
|
|
897
|
+
sequenceNumber: item.sequenceNumber == null
|
|
898
|
+
? undefined
|
|
899
|
+
: String(item.sequenceNumber),
|
|
900
|
+
idempotent: item.idempotent == null ? undefined : Boolean(item.idempotent),
|
|
901
|
+
status: String(item.status ?? ''),
|
|
902
|
+
error: item.error == null ? undefined : String(item.error),
|
|
903
|
+
};
|
|
904
|
+
})
|
|
905
|
+
: [];
|
|
906
|
+
return {
|
|
907
|
+
totalQueued: Number(data.totalQueued ?? results.length),
|
|
908
|
+
totalFailed: Number(data.totalFailed ?? 0),
|
|
909
|
+
results,
|
|
910
|
+
_efficiency: data._efficiency,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
normalizeListCustomersResponse(data) {
|
|
914
|
+
const customers = Array.isArray(data.customers)
|
|
915
|
+
? data.customers.map((entry) => {
|
|
916
|
+
const item = entry;
|
|
917
|
+
return {
|
|
918
|
+
customerId: String(item.customerId ?? ''),
|
|
919
|
+
customerReference: String(item.customerReference ?? ''),
|
|
920
|
+
totalDeltas: Number(item.totalDeltas ?? 0),
|
|
921
|
+
firstDeltaAt: item.firstDeltaAt == null ? null : String(item.firstDeltaAt),
|
|
922
|
+
lastDeltaAt: item.lastDeltaAt == null ? null : String(item.lastDeltaAt),
|
|
923
|
+
};
|
|
924
|
+
})
|
|
925
|
+
: [];
|
|
926
|
+
const pagination = (data.pagination ?? {});
|
|
927
|
+
return {
|
|
928
|
+
customers,
|
|
929
|
+
pagination: {
|
|
930
|
+
total: Number(pagination.total ?? customers.length),
|
|
931
|
+
page: Number(pagination.page ?? 1),
|
|
932
|
+
limit: Number(pagination.limit ?? customers.length),
|
|
933
|
+
totalPages: Number(pagination.totalPages ?? 1),
|
|
934
|
+
},
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
normalizeCustomerDetailResponse(data) {
|
|
938
|
+
return {
|
|
939
|
+
customerId: String(data.customerId ?? ''),
|
|
940
|
+
customerReference: String(data.customerReference ?? ''),
|
|
941
|
+
totalDeltas: Number(data.totalDeltas ?? 0),
|
|
942
|
+
firstDeltaAt: data.firstDeltaAt == null ? null : String(data.firstDeltaAt),
|
|
943
|
+
lastDeltaAt: data.lastDeltaAt == null ? null : String(data.lastDeltaAt),
|
|
944
|
+
customerPartition: String(data.customerPartition ?? ''),
|
|
945
|
+
computedBalance: Number(data.computedBalance ?? 0),
|
|
946
|
+
latestCheckpoint: data.latestCheckpoint == null ? null : String(data.latestCheckpoint),
|
|
947
|
+
privacyNote: String(data.privacyNote ?? ''),
|
|
948
|
+
recentActivity: data.recentActivity ??
|
|
949
|
+
{
|
|
950
|
+
items: [],
|
|
951
|
+
pagination: {
|
|
952
|
+
total: 0,
|
|
953
|
+
page: 1,
|
|
954
|
+
limit: 20,
|
|
955
|
+
totalPages: 1,
|
|
956
|
+
},
|
|
957
|
+
},
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
// -------------------------------------------------------------------------
|
|
961
|
+
// Invoice Proof (deprecated — use receipt with period)
|
|
962
|
+
// -------------------------------------------------------------------------
|
|
963
|
+
/**
|
|
964
|
+
* Generate an invoice-ready receipt for a customer's billing period.
|
|
965
|
+
*
|
|
966
|
+
* @deprecated Use `receipt(customerId, { period })` instead.
|
|
967
|
+
* @param customerId - The customer to generate the receipt for.
|
|
968
|
+
* @param options - Period selection and request overrides.
|
|
969
|
+
* @returns Receipt with proof root, verifyUrl, and verification data.
|
|
970
|
+
*/
|
|
971
|
+
async invoiceProof(customerId, options) {
|
|
972
|
+
return this.receiptForPeriod(customerId, options);
|
|
228
973
|
}
|
|
229
974
|
}
|
|
230
975
|
exports.BalanceResource = BalanceResource;
|