@uengage.io/platform-sdk 2.2.0 → 2.3.0

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 CHANGED
@@ -33,6 +33,7 @@ const { balance, balanceMinor, currency } = await wallet.getBalance();
33
33
  // wallet.debit({ referenceId, amountMinor, service: Services.FLASH_DELIVERY, description }) — idempotent on referenceId
34
34
  // wallet.credit({ ..., reversalOf }) refund capped by that debit; ({ ..., isRefund: true }) uncapped
35
35
  // wallet.listTransactions({...}); wallet.getTransaction(id)
36
+ // wallet.getOverview() — wallet balance or credit line? See Wallet client below.
36
37
  // Legacy-ledger passthroughs, written as top-level ledger fields:
37
38
  // taskId, rto (debit), units, serviceBaseCost, paymentId (credit), updatedBy,
38
39
  // occurredAt — IST 'YYYY-MM-DD HH:mm:ss', dates the CHARGE not the write
@@ -229,6 +230,158 @@ const many = await client.business.bulk([123, 124], { groups: ['profile'] });
229
230
  - The `profile` group (just `name`) is public; other groups need
230
231
  matching `business.<group>:read` capability for the calling service id.
231
232
 
233
+ ## Wallet client
234
+
235
+ `getWallet(...)` is a lightweight handle — no I/O. The wallet is resolved
236
+ server-side on the first operation, so a routing miss surfaces from the
237
+ operation, not from `getWallet()`.
238
+
239
+ ### Which billing model? — start here
240
+
241
+ Prepaid wallets and merchant credit lines coexist, and which one a
242
+ merchant is on decides what a dashboard renders and which calls are even
243
+ legal. `getOverview()` settles it with a discriminated union:
244
+
245
+ ```ts
246
+ const o = await wallet.getOverview();
247
+
248
+ if (o.mode === 'credit') {
249
+ o.creditLine.limit; // { amount, amountMinor } — net of GST
250
+ o.creditLine.band; // 'normal' | 'warning' | 'critical' | 'blocked'
251
+ } else {
252
+ o.balance.balanceMinor; // prepaid: the wallet balance
253
+ }
254
+ ```
255
+
256
+ - `balance` is on **both** arms and means the same thing either way: what
257
+ the merchant can still spend. Available credit on the credit arm.
258
+ - One request for a prepaid merchant, two for a credit one, and never a
259
+ 404 on the happy path — it reads `getBalance().source` rather than
260
+ calling `getCreditLine()` and catching its 404, which would make the
261
+ normal state of a prepaid merchant an error on every page load.
262
+ - A wallet service older than the credit line (no `source`) reads as
263
+ prepaid rather than throwing.
264
+ - **The credit arm needs `wallet.credit:read` on top of
265
+ `wallet.balance:read`.** A token with only the latter gets a
266
+ `WalletApiError` with `status === 403` from the second call — not a
267
+ fallback to `prepaid`, which would render the frozen `wallet_balance`
268
+ these merchants no longer spend from.
269
+ - Not a guaranteed 200: `WalletNotFoundError` (no wallet document for the
270
+ resolved identity) and `UnresolvableWalletError` (routing cannot name
271
+ one) both propagate, because both mean there is nothing to render.
272
+
273
+ ### Credit line
274
+
275
+ The ceiling is per **merchant**, not per wallet, so an outlet's id and its
276
+ parent's id return the same line.
277
+
278
+ ```ts
279
+ const line = await wallet.getCreditLine(); // 404 CreditLineNotFoundError if prepaid
280
+ line.consumed; // net, UNPAID — spans months, not a calendar figure
281
+ line.available; // limit − consumed
282
+ line.estimatedInvoice.total; // exact, from recorded GST — not consumed × 1.18
283
+
284
+ await wallet.setCreditLimit({
285
+ referenceId: 'admin:limit:1200:2026-09-02', // idempotency key
286
+ limitMinor: 10_000_000, // ₹1,00,000, NET of GST; 0 blocks
287
+ onBehalfOf: 'user:4471', // required — the trail names the human
288
+ reason: 'Q3 volume increase',
289
+ // enabled: false → take them off the credit line
290
+ });
291
+
292
+ await wallet.settleInvoice({
293
+ invoiceRef: 'invoice:2026-04:88213', // idempotency key
294
+ netMinor: 500_000, // the NET figure — what frees credit
295
+ gstMinor: 90_000, // recorded, not released
296
+ onBehalfOf: 'user:9',
297
+ });
298
+ await wallet.reverseSettlement({ invoiceRef: '…', onBehalfOf: 'user:9' });
299
+ // Correcting a settled amount: reverse, then settle again with the right
300
+ // figures AND a `reason` — different figures on a reversed invoice
301
+ // release against the merchant's whole outstanding consumption, so the
302
+ // service requires the correction to say what it is correcting.
303
+
304
+ await wallet.listCreditEvents(); // limit changes + settlements, newest first
305
+ await wallet.listCreditEvents({ limit: 200 }); // the service defaults to 50
306
+ await client.wallet.getCreditUtilisation({ band: 'warning' }); // cross-merchant
307
+ ```
308
+
309
+ - **Charges on a credit-line merchant must carry `breakup`** — consumption
310
+ is tracked net of GST, so a missing split is
311
+ `CreditBreakupRequiredError` rather than a guessed rate. `allowNegative`
312
+ is refused (`CreditOverrideRefusedError`): it disables the balance guard
313
+ for migration paths, and on a credit line it would disable the limit.
314
+ - **The merchant pays gross; settlement releases net.** A ₹5,900 invoice
315
+ on ₹5,000 of consumption frees ₹5,000. Passing gross hands back 18% too
316
+ much — and it looks right in a test, since both figures sit on the same
317
+ invoice row.
318
+ - **Setting a limit never touches consumption**, so raising one hands back
319
+ exactly the difference. Lowering below what is consumed blocks charges
320
+ immediately.
321
+ - **`enabled: false` is refused while the merchant owes** —
322
+ `CreditLineHasOutstandingError`, carrying `consumedMinor` so you can say
323
+ how much to settle. Disabling moves them back to a wallet balance, which
324
+ with a balance owed abandons it. To _stop_ a merchant trading use
325
+ `limitMinor: 0`; to move them _off_, settle first.
326
+ - Reusing an idempotency key with **different** figures is
327
+ `CreditIdempotencyConflictError`, not a silent replay. To correct a
328
+ settled amount, reverse it and settle again rather than inventing a new
329
+ ref — a new ref leaves the original settlement standing.
330
+ - **A plain `credit()` is refused** — `CreditTopUpRefusedError`. These
331
+ merchants have no balance to top up: `wallet_balance` is the fiction the
332
+ line replaces and is frozen, so the write would move nothing while
333
+ answering 201. Credit comes back through `settleInvoice`. A genuine
334
+ refund is accepted — send `reversalOf` or `isRefund` and it releases
335
+ what the original charge consumed.
336
+ - `getCreditUtilisation` hangs off the **client**, not a wallet handle: it
337
+ is the one wallet call not scoped to a business.
338
+
339
+ ### Errors
340
+
341
+ All extend `WalletApiError` (`.status`, `.body`).
342
+
343
+ `CreditLimitReachedError` carries `limitMinor` / `consumedMinor` /
344
+ `availableMinor` / `requestedMinor`, and that is the point of it — three
345
+ situations share the code and need different merchant copy:
346
+
347
+ ```ts
348
+ if (e instanceof CreditLimitReachedError) {
349
+ if (e.availableMinor === undefined) {
350
+ // No figures in the response (trimmed or proxied body) — generic
351
+ // copy. Not the same as 0, which is the "used up" sentinel below.
352
+ } else if (e.availableMinor > 0) {
353
+ // Limit NOT used up — this one charge is larger than what is left.
354
+ // A smaller order would go through; do not send them to their KAM.
355
+ }
356
+ // Otherwise the ceiling is reached — which can be unpaid invoices
357
+ // rather than this month's spend. getCreditLine() tells you which.
358
+ }
359
+ ```
360
+
361
+ The figures are optional for that reason: coercing an absent
362
+ `availableMinor` to `0` would silently claim the limit is used up.
363
+
364
+ Also: `CreditLineNotFoundError` (404 — a prepaid merchant, not a
365
+ failure), `CreditBreakupRequiredError`, `CreditOverrideRefusedError`,
366
+ `CreditTopUpRefusedError`, `CreditIdempotencyConflictError`,
367
+ `CreditCorrectionReasonRequiredError` (400 — a reversed invoice is being
368
+ re-settled for different figures; pass `reason`),
369
+ `CreditCurrencyConflictError` and `CreditCurrencyMismatchError` (409 —
370
+ neither is caller-retryable; see their docblocks),
371
+ `SettlementNotFoundError`, plus the
372
+ pre-existing `InsufficientBalanceError`, `OverRefundError`,
373
+ `InvalidReversalError`, `IdempotencyConflictError`,
374
+ `WalletIdentityMismatchError`, `UnresolvableWalletError`,
375
+ `WalletNotFoundError`.
376
+
377
+ ### Money
378
+
379
+ Every figure is `{ amount, amountMinor }`. **Compute in `amountMinor`**
380
+ (integer paise); `amount` is for display. On a ledger row `amount` is
381
+ **gross** and `breakup.subTotalMinor` is what consumed the ceiling —
382
+ `creditMerchantId` present means the row's `balanceBefore`/`balanceAfter`
383
+ are available credit rather than a wallet balance.
384
+
232
385
  ## Auth helpers
233
386
 
234
387
  ```ts
package/dist/version.d.ts CHANGED
@@ -13,4 +13,4 @@
13
13
  * namespace suite, so a later split or trim of one namespace cannot take
14
14
  * the release guard with it.
15
15
  */
16
- export declare const SDK_VERSION = "2.2.0";
16
+ export declare const SDK_VERSION = "2.3.0";
package/dist/version.js CHANGED
@@ -16,5 +16,5 @@ exports.SDK_VERSION = void 0;
16
16
  * namespace suite, so a later split or trim of one namespace cannot take
17
17
  * the release guard with it.
18
18
  */
19
- exports.SDK_VERSION = '2.2.0';
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ1UsUUFBQSxXQUFXLEdBQUcsT0FBTyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNYW51YWxseS1tYWludGFpbmVkIHZlcnNpb24gc3RyaW5nIHN1cmZhY2VkIHZpYSB0aGUgYFVzZXItQWdlbnRgXG4gKiBoZWFkZXIuIEtlcHQgaW4gc3luYyB3aXRoIGBwYWNrYWdlLmpzb25gIGJ5IGhhbmQgYmVjYXVzZSBwdWxsaW5nIHRoZVxuICogdmFsdWUgZnJvbSBwYWNrYWdlLmpzb24gYXQgcnVudGltZSB3b3VsZCByZXF1aXJlIGVpdGhlciBhIEpTT04gaW1wb3J0XG4gKiAoVFMgbGliIHNldHRpbmdzIGRlcGVuZGVudCkgb3IgYSBidWlsZC10aW1lIHJlcGxhY2VtZW50LCBhbmQgdGhlXG4gKiBjb3N0IG9mIG9uZSBidW1wLWluLXR3by1wbGFjZXMgcGVyIHJlbGVhc2UgaXMgc21hbGwuXG4gKlxuICogVGhhdCBjb3N0IHdhcyB1bmRlcmVzdGltYXRlZCBvbmNlOiB0aGUgcHVibGlzaCBqb2IgdmVyaWZpZXNcbiAqIHBhY2thZ2UuanNvbiBhZ2FpbnN0IHRoZSByZWxlYXNlIHRhZyBidXQgbmV2ZXIgcmVhZHMgdGhpcyBmaWxlLCBzbyB0aGVcbiAqIHR3byBkcmlmdGVkIGFuZCAxLjAuMCBzaGlwcGVkIHJlcG9ydGluZyAwLjkuMS4gQSB0ZXN0IG5vdyBwaW5zIHRoZW1cbiAqIHRvZ2V0aGVyIChgdGVzdC92ZXJzaW9uLnRlc3QudHNgKSwgc28gZm9yZ2V0dGluZyB0aGlzIGJ1bXAgZmFpbHMgdGhlXG4gKiBidWlsZCBpbnN0ZWFkIG9mIHRoZSBVc2VyLUFnZW50LiBJdCBsaXZlcyBhdCB0aGUgdG9wIGxldmVsLCBub3QgdW5kZXIgYVxuICogbmFtZXNwYWNlIHN1aXRlLCBzbyBhIGxhdGVyIHNwbGl0IG9yIHRyaW0gb2Ygb25lIG5hbWVzcGFjZSBjYW5ub3QgdGFrZVxuICogdGhlIHJlbGVhc2UgZ3VhcmQgd2l0aCBpdC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNES19WRVJTSU9OID0gJzIuMi4wJztcbiJdfQ==
19
+ exports.SDK_VERSION = '2.3.0';
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ1UsUUFBQSxXQUFXLEdBQUcsT0FBTyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNYW51YWxseS1tYWludGFpbmVkIHZlcnNpb24gc3RyaW5nIHN1cmZhY2VkIHZpYSB0aGUgYFVzZXItQWdlbnRgXG4gKiBoZWFkZXIuIEtlcHQgaW4gc3luYyB3aXRoIGBwYWNrYWdlLmpzb25gIGJ5IGhhbmQgYmVjYXVzZSBwdWxsaW5nIHRoZVxuICogdmFsdWUgZnJvbSBwYWNrYWdlLmpzb24gYXQgcnVudGltZSB3b3VsZCByZXF1aXJlIGVpdGhlciBhIEpTT04gaW1wb3J0XG4gKiAoVFMgbGliIHNldHRpbmdzIGRlcGVuZGVudCkgb3IgYSBidWlsZC10aW1lIHJlcGxhY2VtZW50LCBhbmQgdGhlXG4gKiBjb3N0IG9mIG9uZSBidW1wLWluLXR3by1wbGFjZXMgcGVyIHJlbGVhc2UgaXMgc21hbGwuXG4gKlxuICogVGhhdCBjb3N0IHdhcyB1bmRlcmVzdGltYXRlZCBvbmNlOiB0aGUgcHVibGlzaCBqb2IgdmVyaWZpZXNcbiAqIHBhY2thZ2UuanNvbiBhZ2FpbnN0IHRoZSByZWxlYXNlIHRhZyBidXQgbmV2ZXIgcmVhZHMgdGhpcyBmaWxlLCBzbyB0aGVcbiAqIHR3byBkcmlmdGVkIGFuZCAxLjAuMCBzaGlwcGVkIHJlcG9ydGluZyAwLjkuMS4gQSB0ZXN0IG5vdyBwaW5zIHRoZW1cbiAqIHRvZ2V0aGVyIChgdGVzdC92ZXJzaW9uLnRlc3QudHNgKSwgc28gZm9yZ2V0dGluZyB0aGlzIGJ1bXAgZmFpbHMgdGhlXG4gKiBidWlsZCBpbnN0ZWFkIG9mIHRoZSBVc2VyLUFnZW50LiBJdCBsaXZlcyBhdCB0aGUgdG9wIGxldmVsLCBub3QgdW5kZXIgYVxuICogbmFtZXNwYWNlIHN1aXRlLCBzbyBhIGxhdGVyIHNwbGl0IG9yIHRyaW0gb2Ygb25lIG5hbWVzcGFjZSBjYW5ub3QgdGFrZVxuICogdGhlIHJlbGVhc2UgZ3VhcmQgd2l0aCBpdC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNES19WRVJTSU9OID0gJzIuMy4wJztcbiJdfQ==
@@ -1,5 +1,5 @@
1
1
  import { type PlatformAuth, type PlatformAuthInput, type PlatformConfigInput } from '../config';
2
- import type { CreditInput, Currency, DebitInput, GetWalletOptions, ListTransactionsFilter, TransactionPage, TransactionResult, WalletBalance, WalletInstance, WalletTransaction } from './schema';
2
+ import type { CreditEvent, CreditInput, CreditLine, CreditUtilisationFilter, CreditUtilisationPage, Currency, DebitInput, GetWalletOptions, ListCreditEventsFilter, ListTransactionsFilter, ReverseSettlementInput, SetCreditLimitInput, SetCreditLimitResult, SettleInvoiceInput, SettleInvoiceResult, TransactionPage, TransactionResult, WalletBalance, WalletInstance, WalletOverview, WalletTransaction } from './schema';
3
3
  /**
4
4
  * A handle to one business wallet. Cheap to create — `getWallet(...)`
5
5
  * does no I/O. The wallet is resolved server-side on the first
@@ -7,6 +7,23 @@ import type { CreditInput, Currency, DebitInput, GetWalletOptions, ListTransacti
7
7
  * surface from the operation, not from `getWallet()`.
8
8
  */
9
9
  export interface Wallet {
10
+ /**
11
+ * WHICH MODEL IS THIS MERCHANT ON — call this first.
12
+ *
13
+ * Returns a discriminated union on `mode`, so a dashboard settles
14
+ * "wallet balance or credit line?" from a value rather than by
15
+ * catching a 404, and TypeScript narrows the rest for you:
16
+ *
17
+ * ```ts
18
+ * const o = await wallet.getOverview();
19
+ * if (o.mode === 'credit') renderCreditWidget(o.creditLine);
20
+ * else renderWalletPanel(o.balance);
21
+ * ```
22
+ *
23
+ * One request for a prepaid merchant, two for a credit one, and never
24
+ * a 404 on the happy path — see the implementation for why that order.
25
+ */
26
+ getOverview(): Promise<WalletOverview>;
10
27
  /** GET /v1/wallet/balance — resolves the wallet and returns its balance + currency. */
11
28
  getBalance(): Promise<WalletBalance>;
12
29
  /** GET /v1/wallet/instance — wallet identity + currency, without the balance. */
@@ -29,6 +46,39 @@ export interface Wallet {
29
46
  listTransactions(filter?: ListTransactionsFilter): Promise<TransactionPage>;
30
47
  /** GET /v1/wallet/transactions/:id — scoped to this wallet. */
31
48
  getTransaction(id: string): Promise<WalletTransaction>;
49
+ /**
50
+ * GET /v1/wallet/credit — everything the merchant widget renders.
51
+ * Throws `CreditLineNotFoundError` (404) when the merchant is not on
52
+ * the credit line, which is the normal state for a prepaid merchant.
53
+ * Requires `wallet.credit:read`.
54
+ */
55
+ getCreditLine(): Promise<CreditLine>;
56
+ /**
57
+ * GET /v1/wallet/credit/events — the limit-change and settlement
58
+ * trail, newest first. Requires `wallet.credit:read`.
59
+ *
60
+ * Pass a `limit` to widen the page: the service defaults to 50, which
61
+ * a merchant on the line for a year will have outgrown.
62
+ */
63
+ listCreditEvents(filter?: ListCreditEventsFilter): Promise<CreditEvent[]>;
64
+ /**
65
+ * PUT /v1/wallet/credit/limit — set the limit, creating the credit
66
+ * line on first use. Consumption is never touched, so raising a limit
67
+ * hands back exactly the difference. Requires `wallet.credit:write`.
68
+ */
69
+ setCreditLimit(input: SetCreditLimitInput): Promise<SetCreditLimitResult>;
70
+ /**
71
+ * POST /v1/wallet/credit/settlements — release the credit an invoice
72
+ * was holding, on payment IN FULL. Releases the invoice's net figure;
73
+ * see `SettleInvoiceInput.netMinor`. Requires `wallet.credit:settle`.
74
+ */
75
+ settleInvoice(input: SettleInvoiceInput): Promise<SettleInvoiceResult>;
76
+ /**
77
+ * POST /v1/wallet/credit/settlements/reversal — undo a settlement
78
+ * recorded in error, re-holding exactly what it released. Requires
79
+ * `wallet.credit:settle`.
80
+ */
81
+ reverseSettlement(input: ReverseSettlementInput): Promise<SettleInvoiceResult>;
32
82
  }
33
83
  export interface WalletClient {
34
84
  config(input: PlatformConfigInput): WalletClient;
@@ -39,6 +89,16 @@ export interface WalletClient {
39
89
  * `wallet.*` scope for the operations on the returned handle.
40
90
  */
41
91
  getWallet(opts: GetWalletOptions): Wallet;
92
+ /**
93
+ * GET /v1/wallet/credit/utilisation — every merchant on the credit
94
+ * line, most-utilised first.
95
+ *
96
+ * On the client rather than on a wallet handle because it is the one
97
+ * wallet operation that is not scoped to a business, and it carries
98
+ * its own capability (`wallet.credit:list`) for the same reason: it is
99
+ * a materially broader grant than reading one merchant's line.
100
+ */
101
+ getCreditUtilisation(filter?: CreditUtilisationFilter): Promise<CreditUtilisationPage>;
42
102
  }
43
103
  export declare class WalletApiError extends Error {
44
104
  readonly status: number;
@@ -79,4 +139,148 @@ export declare class UnresolvableWalletError extends WalletApiError {
79
139
  export declare class WalletNotFoundError extends WalletApiError {
80
140
  constructor(body: string);
81
141
  }
142
+ /**
143
+ * The charge would exceed the merchant's credit limit; nothing was moved
144
+ * (HTTP 409).
145
+ *
146
+ * Distinct from `InsufficientBalanceError` because the merchant's next
147
+ * step is different — settle an invoice or talk to their account
148
+ * manager, not top up. The figures also separate two cases that share
149
+ * this error and need different copy:
150
+ *
151
+ * - `availableMinor === 0` — the limit is used up.
152
+ * - `availableMinor > 0` — this one charge is larger than what is
153
+ * left, which can happen at any utilisation. Telling that merchant
154
+ * their "credit limit is reached" would be wrong.
155
+ * - `availableMinor === undefined` — the response carried no figures
156
+ * (a trimmed or proxied body). Fall back to generic copy; do not
157
+ * read it as zero, which is the sentinel above.
158
+ *
159
+ * And a third the fields cannot distinguish on their own: consumption
160
+ * spans months, so a merchant can be at their ceiling purely because
161
+ * older invoices are unpaid. `getCreditLine()` tells you which.
162
+ */
163
+ export declare class CreditLimitReachedError extends WalletApiError {
164
+ readonly limitMinor?: number;
165
+ readonly consumedMinor?: number;
166
+ readonly availableMinor?: number;
167
+ readonly requestedMinor?: number;
168
+ constructor(figures: {
169
+ limitMinor?: number;
170
+ consumedMinor?: number;
171
+ availableMinor?: number;
172
+ requestedMinor?: number;
173
+ }, body: string);
174
+ }
175
+ /**
176
+ * A charge on a credit-line merchant arrived without its GST split
177
+ * (HTTP 400).
178
+ *
179
+ * Consumption is tracked net of GST, so `breakup` is required rather
180
+ * than a rate being inferred. If you hit this, the caller is sending
181
+ * gross-only amounts and needs to send `breakup` — the same split it
182
+ * almost certainly already computes.
183
+ */
184
+ export declare class CreditBreakupRequiredError extends WalletApiError {
185
+ constructor(body: string);
186
+ }
187
+ /** `allowNegative` was passed for a credit-line merchant (HTTP 400). */
188
+ export declare class CreditOverrideRefusedError extends WalletApiError {
189
+ constructor(body: string);
190
+ }
191
+ /**
192
+ * A re-settlement changed an invoice's figures without saying why
193
+ * (HTTP 400).
194
+ *
195
+ * Re-settling a REVERSED invoice with different figures is how a settled
196
+ * amount is corrected, so the service does not refuse it the way it
197
+ * refuses a conflicting first settlement. But it releases against the
198
+ * merchant's whole outstanding consumption rather than the invoice's own
199
+ * amount, so a mistyped figure can hand back far more than the invoice
200
+ * held — and a deliberate correction can say what it is correcting where
201
+ * a replayed webhook cannot. Pass `reason` and retry. Re-settling with
202
+ * the SAME figures needs none.
203
+ */
204
+ export declare class CreditCorrectionReasonRequiredError extends WalletApiError {
205
+ /** What the invoice was previously settled for, in minor units. */
206
+ readonly previousNetMinor: number | undefined;
207
+ constructor(
208
+ /** What the invoice was previously settled for, in minor units. */
209
+ previousNetMinor: number | undefined, body: string);
210
+ }
211
+ /**
212
+ * A limit change named a currency the credit line is not denominated in
213
+ * (HTTP 409).
214
+ *
215
+ * The line's currency is fixed when it is created, because it sets the
216
+ * exponent every stored figure is already scaled by — changing it would
217
+ * re-denominate the limit and the consumption without touching either
218
+ * number. Re-denominating a live line is a migration, not a field
219
+ * update, so this is not something a caller can retry past: send the
220
+ * currency the line already carries.
221
+ */
222
+ export declare class CreditCurrencyConflictError extends WalletApiError {
223
+ readonly storedCurrency: string | undefined;
224
+ readonly requestedCurrency: string | undefined;
225
+ constructor(storedCurrency: string | undefined, requestedCurrency: string | undefined, body: string);
226
+ }
227
+ /**
228
+ * The merchant's credit line and the wallet the charge routed to are in
229
+ * different currencies (HTTP 409).
230
+ *
231
+ * `amountMinor` and `breakup` carry no currency of their own — they are
232
+ * read with the exponent of the resolved wallet — so when the two
233
+ * disagree there is no reading of them that is right for both, and the
234
+ * service refuses rather than mis-scaling by a factor of ten or a
235
+ * hundred. Not caller-fixable: it means the merchant's routing and their
236
+ * credit line disagree, which is an ops/data problem.
237
+ */
238
+ export declare class CreditCurrencyMismatchError extends WalletApiError {
239
+ constructor(body: string);
240
+ }
241
+ /**
242
+ * A plain top-up was sent for a credit-line merchant (HTTP 400).
243
+ *
244
+ * These merchants have no balance to top up: `wallet_balance` is the
245
+ * fiction the credit line replaces and is deliberately frozen, so the
246
+ * write would move nothing while appearing to succeed. Credit is handed
247
+ * back by settling an invoice (`settleInvoice`), never by crediting the
248
+ * wallet. A genuine refund is accepted — send it as `reversalOf` or
249
+ * `isRefund` and it releases the credit the original charge consumed.
250
+ */
251
+ export declare class CreditTopUpRefusedError extends WalletApiError {
252
+ constructor(body: string);
253
+ }
254
+ /**
255
+ * The merchant is not on the credit line (HTTP 404).
256
+ *
257
+ * The normal state for a prepaid merchant, so a widget should treat it
258
+ * as "show the wallet balance instead", not as an error.
259
+ */
260
+ export declare class CreditLineNotFoundError extends WalletApiError {
261
+ constructor(body: string);
262
+ }
263
+ /**
264
+ * `enabled: false` was refused because the merchant still owes for the
265
+ * credit line (HTTP 409).
266
+ *
267
+ * Disabling moves a merchant back to a wallet balance, and doing that
268
+ * with consumption outstanding abandons it. Show `consumedMinor` and
269
+ * tell the operator to settle first — or, if the intent was to stop the
270
+ * merchant trading rather than to move them off the model, set
271
+ * `limitMinor: 0`, which blocks every charge and keeps the balance.
272
+ */
273
+ export declare class CreditLineHasOutstandingError extends WalletApiError {
274
+ readonly consumedMinor: number;
275
+ readonly gstAccruedMinor: number;
276
+ constructor(consumedMinor: number, gstAccruedMinor: number, body: string);
277
+ }
278
+ /** A limit `referenceId` or an invoice was reused for different figures (HTTP 409). */
279
+ export declare class CreditIdempotencyConflictError extends WalletApiError {
280
+ constructor(body: string);
281
+ }
282
+ /** No settlement to reverse for that invoice (HTTP 404). */
283
+ export declare class SettlementNotFoundError extends WalletApiError {
284
+ constructor(body: string);
285
+ }
82
286
  export declare function createWalletClient(input?: PlatformConfigInput): WalletClient;