@txnod/sdk 1.0.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.
Files changed (121) hide show
  1. package/AGENTS.md +29 -0
  2. package/CHANGELOG.md +22 -0
  3. package/LICENSE +21 -0
  4. package/README.md +434 -0
  5. package/dist/_shared/index.d.ts +68 -0
  6. package/dist/client-sandbox.d.ts +396 -0
  7. package/dist/client-sandbox.d.ts.map +1 -0
  8. package/dist/client-sandbox.js +448 -0
  9. package/dist/client-sandbox.js.map +1 -0
  10. package/dist/client.d.ts +429 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +588 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/env.d.ts +29 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +44 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/errors.d.ts +1887 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +2107 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/index.d.ts +35 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +32 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/internals/error-ctor-map.d.ts +11 -0
  27. package/dist/internals/error-ctor-map.d.ts.map +1 -0
  28. package/dist/internals/error-ctor-map.js +75 -0
  29. package/dist/internals/error-ctor-map.js.map +1 -0
  30. package/dist/internals/fetch-with-retry.d.ts +34 -0
  31. package/dist/internals/fetch-with-retry.d.ts.map +1 -0
  32. package/dist/internals/fetch-with-retry.js +233 -0
  33. package/dist/internals/fetch-with-retry.js.map +1 -0
  34. package/dist/internals/hmac.d.ts +2 -0
  35. package/dist/internals/hmac.d.ts.map +1 -0
  36. package/dist/internals/hmac.js +10 -0
  37. package/dist/internals/hmac.js.map +1 -0
  38. package/dist/internals/logger.d.ts +9 -0
  39. package/dist/internals/logger.d.ts.map +1 -0
  40. package/dist/internals/logger.js +16 -0
  41. package/dist/internals/logger.js.map +1 -0
  42. package/dist/internals/parse-problem-details.d.ts +3 -0
  43. package/dist/internals/parse-problem-details.d.ts.map +1 -0
  44. package/dist/internals/parse-problem-details.js +76 -0
  45. package/dist/internals/parse-problem-details.js.map +1 -0
  46. package/dist/internals/synthetic-details.d.ts +12 -0
  47. package/dist/internals/synthetic-details.d.ts.map +1 -0
  48. package/dist/internals/synthetic-details.js +19 -0
  49. package/dist/internals/synthetic-details.js.map +1 -0
  50. package/dist/verify/chains/bsc.d.ts +17 -0
  51. package/dist/verify/chains/bsc.d.ts.map +1 -0
  52. package/dist/verify/chains/bsc.js +15 -0
  53. package/dist/verify/chains/bsc.js.map +1 -0
  54. package/dist/verify/chains/btc.d.ts +22 -0
  55. package/dist/verify/chains/btc.d.ts.map +1 -0
  56. package/dist/verify/chains/btc.js +55 -0
  57. package/dist/verify/chains/btc.js.map +1 -0
  58. package/dist/verify/chains/cardano.d.ts +73 -0
  59. package/dist/verify/chains/cardano.d.ts.map +1 -0
  60. package/dist/verify/chains/cardano.js +175 -0
  61. package/dist/verify/chains/cardano.js.map +1 -0
  62. package/dist/verify/chains/evm.d.ts +21 -0
  63. package/dist/verify/chains/evm.d.ts.map +1 -0
  64. package/dist/verify/chains/evm.js +46 -0
  65. package/dist/verify/chains/evm.js.map +1 -0
  66. package/dist/verify/chains/polygon.d.ts +17 -0
  67. package/dist/verify/chains/polygon.d.ts.map +1 -0
  68. package/dist/verify/chains/polygon.js +15 -0
  69. package/dist/verify/chains/polygon.js.map +1 -0
  70. package/dist/verify/chains/secp256k1-bip32.d.ts +20 -0
  71. package/dist/verify/chains/secp256k1-bip32.d.ts.map +1 -0
  72. package/dist/verify/chains/secp256k1-bip32.js +88 -0
  73. package/dist/verify/chains/secp256k1-bip32.js.map +1 -0
  74. package/dist/verify/chains/ton-cell.d.ts +179 -0
  75. package/dist/verify/chains/ton-cell.d.ts.map +1 -0
  76. package/dist/verify/chains/ton-cell.js +614 -0
  77. package/dist/verify/chains/ton-cell.js.map +1 -0
  78. package/dist/verify/chains/ton.d.ts +84 -0
  79. package/dist/verify/chains/ton.d.ts.map +1 -0
  80. package/dist/verify/chains/ton.js +131 -0
  81. package/dist/verify/chains/ton.js.map +1 -0
  82. package/dist/verify/chains/tron.d.ts +21 -0
  83. package/dist/verify/chains/tron.d.ts.map +1 -0
  84. package/dist/verify/chains/tron.js +42 -0
  85. package/dist/verify/chains/tron.js.map +1 -0
  86. package/dist/verify/config.d.ts +41 -0
  87. package/dist/verify/config.d.ts.map +1 -0
  88. package/dist/verify/config.js +120 -0
  89. package/dist/verify/config.js.map +1 -0
  90. package/dist/verify/errors.d.ts +56 -0
  91. package/dist/verify/errors.d.ts.map +1 -0
  92. package/dist/verify/errors.js +58 -0
  93. package/dist/verify/errors.js.map +1 -0
  94. package/dist/verify/index.d.ts +119 -0
  95. package/dist/verify/index.d.ts.map +1 -0
  96. package/dist/verify/index.js +166 -0
  97. package/dist/verify/index.js.map +1 -0
  98. package/dist/verify/xpub-safety.d.ts +33 -0
  99. package/dist/verify/xpub-safety.d.ts.map +1 -0
  100. package/dist/verify/xpub-safety.js +54 -0
  101. package/dist/verify/xpub-safety.js.map +1 -0
  102. package/dist/verify-webhook-signature.d.ts +30 -0
  103. package/dist/verify-webhook-signature.d.ts.map +1 -0
  104. package/dist/verify-webhook-signature.js +84 -0
  105. package/dist/verify-webhook-signature.js.map +1 -0
  106. package/docs/00-getting-started.md +135 -0
  107. package/docs/01-authentication.md +114 -0
  108. package/docs/02-invoices.md +216 -0
  109. package/docs/03-rates-and-quotes.md +82 -0
  110. package/docs/04-webhooks.md +126 -0
  111. package/docs/05-errors.md +199 -0
  112. package/docs/05-sandbox.md +159 -0
  113. package/docs/06-idempotency.md +132 -0
  114. package/docs/examples/express-webhook-receiver.md +97 -0
  115. package/docs/examples/nextjs-route-handler.md +206 -0
  116. package/docs/examples/sandbox-vitest-suite.md +263 -0
  117. package/docs/index.md +66 -0
  118. package/docs/reference/client.md +392 -0
  119. package/docs/reference/errors.md +161 -0
  120. package/docs/reference/types.md +400 -0
  121. package/package.json +53 -0
package/dist/errors.js ADDED
@@ -0,0 +1,2107 @@
1
+ import { syntheticDetails } from './internals/synthetic-details.js';
2
+ /**
3
+ * Base error thrown by every `TxnodClient` method when the server returns a
4
+ * non-2xx response. Carries the RFC 7807 problem-details envelope so partners
5
+ * can branch on `error_code` or log `request_id` for support.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { TxnodClient, TxnodError } from '@txnod/sdk';
10
+ *
11
+ * const client = new TxnodClient({
12
+ * projectId: process.env.TXNOD_PROJECT_ID!,
13
+ * apiSecret: process.env.TXNOD_API_SECRET!,
14
+ * });
15
+ *
16
+ * try {
17
+ * const invoice = await client.createInvoice({
18
+ * amount_usd: 10.0,
19
+ * coin: 'btc',
20
+ * external_id: 'order-123',
21
+ * callback_url: 'https://my-site.com/webhooks/txnod',
22
+ * });
23
+ * console.log(invoice.id);
24
+ * } catch (err) {
25
+ * if (err instanceof TxnodError) {
26
+ * console.error(err.error_code, err.status, err.request_id);
27
+ * } else {
28
+ * throw err;
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export class TxnodError extends Error {
34
+ kind = 'txnod';
35
+ error_code;
36
+ status;
37
+ request_id;
38
+ raw;
39
+ constructor(details) {
40
+ super(details.title);
41
+ this.name = 'TxnodError';
42
+ this.error_code = details.error_code;
43
+ this.status = details.status;
44
+ this.request_id = details.request_id;
45
+ this.raw = details;
46
+ }
47
+ }
48
+ /**
49
+ * Thrown by `verifyWebhookSignature` when the `X-Txnod-Signature` header is
50
+ * missing or does not match the expected `t=<unix>,v1=<hex>` shape.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { verifyWebhookSignature, TxnodSignatureFormatError } from '@txnod/sdk';
55
+ *
56
+ * try {
57
+ * verifyWebhookSignature(req.headers, rawBody, process.env.TXNOD_WEBHOOK_SECRET!);
58
+ * } catch (err) {
59
+ * if (err instanceof TxnodSignatureFormatError) {
60
+ * return new Response('bad header', { status: 401 });
61
+ * }
62
+ * throw err;
63
+ * }
64
+ * ```
65
+ */
66
+ export class TxnodSignatureFormatError extends TxnodError {
67
+ kind = 'signature_format';
68
+ constructor() {
69
+ super(syntheticDetails('auth_invalid', 401, 'Webhook signature header is missing or malformed.'));
70
+ this.name = 'TxnodSignatureFormatError';
71
+ }
72
+ }
73
+ /**
74
+ * Thrown by `verifyWebhookSignature` when the computed HMAC-SHA256 does not
75
+ * match the signature carried in the `X-Txnod-Signature` header.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { verifyWebhookSignature, TxnodHmacError } from '@txnod/sdk';
80
+ *
81
+ * try {
82
+ * verifyWebhookSignature(req.headers, rawBody, process.env.TXNOD_WEBHOOK_SECRET!);
83
+ * } catch (err) {
84
+ * if (err instanceof TxnodHmacError) {
85
+ * return new Response('bad sig', { status: 401 });
86
+ * }
87
+ * throw err;
88
+ * }
89
+ * ```
90
+ */
91
+ export class TxnodHmacError extends TxnodError {
92
+ kind = 'hmac';
93
+ constructor() {
94
+ super(syntheticDetails('signature_invalid', 401, 'Webhook signature does not match.'));
95
+ this.name = 'TxnodHmacError';
96
+ }
97
+ }
98
+ /**
99
+ * Thrown by `verifyWebhookSignature` when the timestamp in the
100
+ * `X-Txnod-Signature` header is outside the ±300-second window. The signed
101
+ * `skew_seconds` field reports `now - timestamp` so callers can alert on
102
+ * clock drift.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * import { verifyWebhookSignature, TxnodTimestampError } from '@txnod/sdk';
107
+ *
108
+ * try {
109
+ * verifyWebhookSignature(req.headers, rawBody, process.env.TXNOD_WEBHOOK_SECRET!);
110
+ * } catch (err) {
111
+ * if (err instanceof TxnodTimestampError) {
112
+ * console.warn('clock skew', err.skew_seconds);
113
+ * return new Response('stale', { status: 401 });
114
+ * }
115
+ * throw err;
116
+ * }
117
+ * ```
118
+ */
119
+ export class TxnodTimestampError extends TxnodError {
120
+ kind = 'timestamp';
121
+ skew_seconds;
122
+ constructor(skewSeconds) {
123
+ super(syntheticDetails('timestamp_out_of_window', 401, 'Webhook timestamp is outside the ±300-second window.'));
124
+ this.name = 'TxnodTimestampError';
125
+ this.skew_seconds = skewSeconds;
126
+ }
127
+ }
128
+ /**
129
+ * Thrown by `verifyWebhookSignature` when the body bytes pass HMAC verification
130
+ * but cannot be parsed as JSON. In a non-compromised setup this never fires;
131
+ * a real occurrence indicates a misbehaving server release that emitted a
132
+ * non-JSON body alongside a valid signature. The `cause` field carries the
133
+ * underlying `SyntaxError` so the partner can log it. Treat it as a 401-class
134
+ * failure (do not parse, do not act) — same handling as `TxnodHmacError`.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * import { verifyWebhookSignature, TxnodWebhookPayloadParseError } from '@txnod/sdk';
139
+ *
140
+ * try {
141
+ * verifyWebhookSignature(req.headers, rawBody, secret);
142
+ * } catch (err) {
143
+ * if (err instanceof TxnodWebhookPayloadParseError) {
144
+ * return new Response('bad payload', { status: 401 });
145
+ * }
146
+ * throw err;
147
+ * }
148
+ * ```
149
+ */
150
+ export class TxnodWebhookPayloadParseError extends TxnodError {
151
+ kind = 'webhook_payload_parse';
152
+ cause;
153
+ constructor(cause) {
154
+ super(syntheticDetails('internal_error', 401, 'Webhook body passed HMAC but is not valid JSON.'));
155
+ this.name = 'TxnodWebhookPayloadParseError';
156
+ this.cause = cause;
157
+ }
158
+ }
159
+ /**
160
+ * Thrown when the server responds with `error_code: 'validation_error'` —
161
+ * request payload failed validation (Zod on the server). Inspect
162
+ * `err.raw.errors` for the structured per-field issues.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * import { TxnodClient, TxnodValidationError } from '@txnod/sdk';
167
+ *
168
+ * const client = new TxnodClient({
169
+ * projectId: process.env.TXNOD_PROJECT_ID!,
170
+ * apiSecret: process.env.TXNOD_API_SECRET!,
171
+ * });
172
+ *
173
+ * try {
174
+ * const invoice = await client.createInvoice({
175
+ * amount_usd: 10,
176
+ * coin: 'btc',
177
+ * external_id: 'order-1',
178
+ * });
179
+ * console.log(invoice.id);
180
+ * } catch (err) {
181
+ * if (err instanceof TxnodValidationError) {
182
+ * console.error('validation failed:', err.raw.errors);
183
+ * return;
184
+ * }
185
+ * throw err;
186
+ * }
187
+ * ```
188
+ */
189
+ export class TxnodValidationError extends TxnodError {
190
+ kind = 'validation_error';
191
+ constructor(details) {
192
+ super(details);
193
+ this.name = 'TxnodValidationError';
194
+ }
195
+ }
196
+ /**
197
+ * Thrown when the server responds with `error_code: 'invalid_coin'` — the
198
+ * requested `coin` is not in the supported coins enum.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * import { TxnodClient, TxnodInvalidCoinError } from '@txnod/sdk';
203
+ *
204
+ * const client = new TxnodClient({
205
+ * projectId: process.env.TXNOD_PROJECT_ID!,
206
+ * apiSecret: process.env.TXNOD_API_SECRET!,
207
+ * });
208
+ *
209
+ * try {
210
+ * const invoice = await client.createInvoice({
211
+ * amount_usd: 10,
212
+ * coin: 'btc',
213
+ * external_id: 'order-1',
214
+ * });
215
+ * console.log(invoice.id);
216
+ * } catch (err) {
217
+ * if (err instanceof TxnodInvalidCoinError) {
218
+ * console.error(err.error_code, err.request_id);
219
+ * return;
220
+ * }
221
+ * throw err;
222
+ * }
223
+ * ```
224
+ */
225
+ export class TxnodInvalidCoinError extends TxnodError {
226
+ kind = 'invalid_coin';
227
+ constructor(details) {
228
+ super(details);
229
+ this.name = 'TxnodInvalidCoinError';
230
+ }
231
+ }
232
+ /**
233
+ * Thrown when the server responds with `error_code: 'invalid_xpub_format'` —
234
+ * the supplied xpub string is structurally invalid for the chain.
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * import { TxnodClient, TxnodInvalidXpubFormatError } from '@txnod/sdk';
239
+ *
240
+ * const client = new TxnodClient({
241
+ * projectId: process.env.TXNOD_PROJECT_ID!,
242
+ * apiSecret: process.env.TXNOD_API_SECRET!,
243
+ * });
244
+ *
245
+ * try {
246
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
247
+ * console.log(invoice.status);
248
+ * } catch (err) {
249
+ * if (err instanceof TxnodInvalidXpubFormatError) {
250
+ * console.error(err.error_code, err.request_id);
251
+ * return;
252
+ * }
253
+ * throw err;
254
+ * }
255
+ * ```
256
+ */
257
+ export class TxnodInvalidXpubFormatError extends TxnodError {
258
+ kind = 'invalid_xpub_format';
259
+ constructor(details) {
260
+ super(details);
261
+ this.name = 'TxnodInvalidXpubFormatError';
262
+ }
263
+ }
264
+ /**
265
+ * Thrown when the server responds with `error_code: 'invalid_webhook_url'` —
266
+ * the configured webhook URL is not a valid https URL.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * import { TxnodClient, TxnodInvalidWebhookUrlError } from '@txnod/sdk';
271
+ *
272
+ * const client = new TxnodClient({
273
+ * projectId: process.env.TXNOD_PROJECT_ID!,
274
+ * apiSecret: process.env.TXNOD_API_SECRET!,
275
+ * });
276
+ *
277
+ * try {
278
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
279
+ * console.log(invoice.status);
280
+ * } catch (err) {
281
+ * if (err instanceof TxnodInvalidWebhookUrlError) {
282
+ * console.error(err.error_code, err.request_id);
283
+ * return;
284
+ * }
285
+ * throw err;
286
+ * }
287
+ * ```
288
+ */
289
+ export class TxnodInvalidWebhookUrlError extends TxnodError {
290
+ kind = 'invalid_webhook_url';
291
+ constructor(details) {
292
+ super(details);
293
+ this.name = 'TxnodInvalidWebhookUrlError';
294
+ }
295
+ }
296
+ /**
297
+ * Thrown when the server responds with `error_code: 'auth_invalid'` on an API
298
+ * call — the `X-Project-Id` / `X-Signature` headers are missing, malformed,
299
+ * or do not identify a known project. Distinct from the webhook-local
300
+ * `TxnodSignatureFormatError`: this one is thrown by `TxnodClient` methods
301
+ * on an API 401 response.
302
+ *
303
+ * @example
304
+ * ```ts
305
+ * import { TxnodClient, TxnodAuthInvalidError } from '@txnod/sdk';
306
+ *
307
+ * const client = new TxnodClient({
308
+ * projectId: process.env.TXNOD_PROJECT_ID!,
309
+ * apiSecret: process.env.TXNOD_API_SECRET!,
310
+ * });
311
+ *
312
+ * try {
313
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
314
+ * console.log(invoice.status);
315
+ * } catch (err) {
316
+ * if (err instanceof TxnodAuthInvalidError) {
317
+ * console.error(err.error_code, err.request_id);
318
+ * return;
319
+ * }
320
+ * throw err;
321
+ * }
322
+ * ```
323
+ */
324
+ export class TxnodAuthInvalidError extends TxnodError {
325
+ kind = 'auth_invalid';
326
+ constructor(details) {
327
+ super(details);
328
+ this.name = 'TxnodAuthInvalidError';
329
+ }
330
+ }
331
+ /**
332
+ * Thrown when the server responds with `error_code: 'signature_invalid'` on
333
+ * an API call — the computed HMAC for the outbound request did not match.
334
+ * Distinct from the webhook-local `TxnodHmacError`.
335
+ *
336
+ * @example
337
+ * ```ts
338
+ * import { TxnodClient, TxnodSignatureInvalidError } from '@txnod/sdk';
339
+ *
340
+ * const client = new TxnodClient({
341
+ * projectId: process.env.TXNOD_PROJECT_ID!,
342
+ * apiSecret: process.env.TXNOD_API_SECRET!,
343
+ * });
344
+ *
345
+ * try {
346
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
347
+ * console.log(invoice.status);
348
+ * } catch (err) {
349
+ * if (err instanceof TxnodSignatureInvalidError) {
350
+ * console.error(err.error_code, err.request_id);
351
+ * return;
352
+ * }
353
+ * throw err;
354
+ * }
355
+ * ```
356
+ */
357
+ export class TxnodSignatureInvalidError extends TxnodError {
358
+ kind = 'signature_invalid';
359
+ constructor(details) {
360
+ super(details);
361
+ this.name = 'TxnodSignatureInvalidError';
362
+ }
363
+ }
364
+ /**
365
+ * Thrown when the server responds with `error_code: 'signature_replayed'` —
366
+ * the same signed `(timestamp, signature)` triple has already been processed
367
+ * within the freshness window. Re-sign the request (fresh timestamp) and try
368
+ * again. Persistent occurrence indicates a stuck retry loop on the caller
369
+ * side or, rarer, replay of a captured request.
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * import { TxnodClient, TxnodSignatureReplayedError } from '@txnod/sdk';
374
+ *
375
+ * const client = new TxnodClient({
376
+ * projectId: process.env.TXNOD_PROJECT_ID!,
377
+ * apiSecret: process.env.TXNOD_API_SECRET!,
378
+ * });
379
+ *
380
+ * try {
381
+ * const invoice = await client.createInvoice({
382
+ * amount_usd: 10,
383
+ * coin: 'btc',
384
+ * external_id: 'order-1',
385
+ * });
386
+ * console.log(invoice.id);
387
+ * } catch (err) {
388
+ * if (err instanceof TxnodSignatureReplayedError) {
389
+ * // The previous attempt's signature was already accepted. The SDK
390
+ * // signs every request with a fresh timestamp, so this normally only
391
+ * // surfaces when something else (a proxy, a retry loop) sends the
392
+ * // exact same signed bytes a second time.
393
+ * console.error('signed request already processed', err.request_id);
394
+ * return;
395
+ * }
396
+ * throw err;
397
+ * }
398
+ * ```
399
+ */
400
+ export class TxnodSignatureReplayedError extends TxnodError {
401
+ kind = 'signature_replayed';
402
+ constructor(details) {
403
+ super(details);
404
+ this.name = 'TxnodSignatureReplayedError';
405
+ }
406
+ }
407
+ /**
408
+ * Thrown when the server responds with `error_code: 'timestamp_out_of_window'`
409
+ * on an API call — the `X-Timestamp` header is outside the ±300-second
410
+ * window. Distinct from the webhook-local `TxnodTimestampError`, which
411
+ * exposes a `skew_seconds` field.
412
+ *
413
+ * @example
414
+ * ```ts
415
+ * import { TxnodClient, TxnodTimestampOutOfWindowError } from '@txnod/sdk';
416
+ *
417
+ * const client = new TxnodClient({
418
+ * projectId: process.env.TXNOD_PROJECT_ID!,
419
+ * apiSecret: process.env.TXNOD_API_SECRET!,
420
+ * });
421
+ *
422
+ * try {
423
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
424
+ * console.log(invoice.status);
425
+ * } catch (err) {
426
+ * if (err instanceof TxnodTimestampOutOfWindowError) {
427
+ * console.error(err.error_code, err.request_id);
428
+ * return;
429
+ * }
430
+ * throw err;
431
+ * }
432
+ * ```
433
+ */
434
+ export class TxnodTimestampOutOfWindowError extends TxnodError {
435
+ kind = 'timestamp_out_of_window';
436
+ constructor(details) {
437
+ super(details);
438
+ this.name = 'TxnodTimestampOutOfWindowError';
439
+ }
440
+ }
441
+ /**
442
+ * Thrown when the server responds with `error_code: 'key_suspended'` — the
443
+ * owner of the API key has been suspended.
444
+ *
445
+ * @example
446
+ * ```ts
447
+ * import { TxnodClient, TxnodKeySuspendedError } from '@txnod/sdk';
448
+ *
449
+ * const client = new TxnodClient({
450
+ * projectId: process.env.TXNOD_PROJECT_ID!,
451
+ * apiSecret: process.env.TXNOD_API_SECRET!,
452
+ * });
453
+ *
454
+ * try {
455
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
456
+ * console.log(invoice.status);
457
+ * } catch (err) {
458
+ * if (err instanceof TxnodKeySuspendedError) {
459
+ * console.error(err.error_code, err.request_id);
460
+ * return;
461
+ * }
462
+ * throw err;
463
+ * }
464
+ * ```
465
+ */
466
+ export class TxnodKeySuspendedError extends TxnodError {
467
+ kind = 'key_suspended';
468
+ constructor(details) {
469
+ super(details);
470
+ this.name = 'TxnodKeySuspendedError';
471
+ }
472
+ }
473
+ /**
474
+ * Thrown when the server responds with `error_code: 'project_suspended'` —
475
+ * the target project has been suspended.
476
+ *
477
+ * @example
478
+ * ```ts
479
+ * import { TxnodClient, TxnodProjectSuspendedError } from '@txnod/sdk';
480
+ *
481
+ * const client = new TxnodClient({
482
+ * projectId: process.env.TXNOD_PROJECT_ID!,
483
+ * apiSecret: process.env.TXNOD_API_SECRET!,
484
+ * });
485
+ *
486
+ * try {
487
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
488
+ * console.log(invoice.status);
489
+ * } catch (err) {
490
+ * if (err instanceof TxnodProjectSuspendedError) {
491
+ * console.error(err.error_code, err.request_id);
492
+ * return;
493
+ * }
494
+ * throw err;
495
+ * }
496
+ * ```
497
+ */
498
+ export class TxnodProjectSuspendedError extends TxnodError {
499
+ kind = 'project_suspended';
500
+ constructor(details) {
501
+ super(details);
502
+ this.name = 'TxnodProjectSuspendedError';
503
+ }
504
+ }
505
+ /**
506
+ * Thrown when the server responds with `error_code: 'permission_denied'` —
507
+ * the authenticated key does not hold the capability required by the route.
508
+ *
509
+ * @example
510
+ * ```ts
511
+ * import { TxnodClient, TxnodPermissionDeniedError } from '@txnod/sdk';
512
+ *
513
+ * const client = new TxnodClient({
514
+ * projectId: process.env.TXNOD_PROJECT_ID!,
515
+ * apiSecret: process.env.TXNOD_API_SECRET!,
516
+ * });
517
+ *
518
+ * try {
519
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
520
+ * console.log(invoice.status);
521
+ * } catch (err) {
522
+ * if (err instanceof TxnodPermissionDeniedError) {
523
+ * console.error(err.error_code, err.request_id);
524
+ * return;
525
+ * }
526
+ * throw err;
527
+ * }
528
+ * ```
529
+ */
530
+ export class TxnodPermissionDeniedError extends TxnodError {
531
+ kind = 'permission_denied';
532
+ constructor(details) {
533
+ super(details);
534
+ this.name = 'TxnodPermissionDeniedError';
535
+ }
536
+ }
537
+ /**
538
+ * Thrown when the server responds with `error_code: 'key_revoked'` — the
539
+ * API key has been rotated or revoked and is no longer valid.
540
+ *
541
+ * @example
542
+ * ```ts
543
+ * import { TxnodClient, TxnodKeyRevokedError } from '@txnod/sdk';
544
+ *
545
+ * const client = new TxnodClient({
546
+ * projectId: process.env.TXNOD_PROJECT_ID!,
547
+ * apiSecret: process.env.TXNOD_API_SECRET!,
548
+ * });
549
+ *
550
+ * try {
551
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
552
+ * console.log(invoice.status);
553
+ * } catch (err) {
554
+ * if (err instanceof TxnodKeyRevokedError) {
555
+ * console.error(err.error_code, err.request_id);
556
+ * return;
557
+ * }
558
+ * throw err;
559
+ * }
560
+ * ```
561
+ */
562
+ export class TxnodKeyRevokedError extends TxnodError {
563
+ kind = 'key_revoked';
564
+ constructor(details) {
565
+ super(details);
566
+ this.name = 'TxnodKeyRevokedError';
567
+ }
568
+ }
569
+ /**
570
+ * Thrown when the server responds with `error_code: 'invoice_not_found'` —
571
+ * no invoice exists with the given id for this project.
572
+ *
573
+ * @example
574
+ * ```ts
575
+ * import { TxnodClient, TxnodInvoiceNotFoundError } from '@txnod/sdk';
576
+ *
577
+ * const client = new TxnodClient({
578
+ * projectId: process.env.TXNOD_PROJECT_ID!,
579
+ * apiSecret: process.env.TXNOD_API_SECRET!,
580
+ * });
581
+ *
582
+ * try {
583
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
584
+ * return Response.json(invoice);
585
+ * } catch (err) {
586
+ * if (err instanceof TxnodInvoiceNotFoundError) {
587
+ * return new Response('Not found', { status: 404 });
588
+ * }
589
+ * throw err;
590
+ * }
591
+ * ```
592
+ */
593
+ export class TxnodInvoiceNotFoundError extends TxnodError {
594
+ kind = 'invoice_not_found';
595
+ constructor(details) {
596
+ super(details);
597
+ this.name = 'TxnodInvoiceNotFoundError';
598
+ }
599
+ }
600
+ /**
601
+ * Thrown when the server responds with `error_code: 'project_not_found'` —
602
+ * no project exists with the given id (or the key does not have access).
603
+ *
604
+ * @example
605
+ * ```ts
606
+ * import { TxnodClient, TxnodProjectNotFoundError } from '@txnod/sdk';
607
+ *
608
+ * const client = new TxnodClient({
609
+ * projectId: process.env.TXNOD_PROJECT_ID!,
610
+ * apiSecret: process.env.TXNOD_API_SECRET!,
611
+ * });
612
+ *
613
+ * try {
614
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
615
+ * console.log(invoice.status);
616
+ * } catch (err) {
617
+ * if (err instanceof TxnodProjectNotFoundError) {
618
+ * console.error(err.error_code, err.request_id);
619
+ * return;
620
+ * }
621
+ * throw err;
622
+ * }
623
+ * ```
624
+ */
625
+ export class TxnodProjectNotFoundError extends TxnodError {
626
+ kind = 'project_not_found';
627
+ constructor(details) {
628
+ super(details);
629
+ this.name = 'TxnodProjectNotFoundError';
630
+ }
631
+ }
632
+ /**
633
+ * Thrown when the server responds with `error_code: 'wallet_not_found'` —
634
+ * no wallet record exists for the requested chain + project.
635
+ *
636
+ * @example
637
+ * ```ts
638
+ * import { TxnodClient, TxnodWalletNotFoundError } from '@txnod/sdk';
639
+ *
640
+ * const client = new TxnodClient({
641
+ * projectId: process.env.TXNOD_PROJECT_ID!,
642
+ * apiSecret: process.env.TXNOD_API_SECRET!,
643
+ * });
644
+ *
645
+ * try {
646
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
647
+ * console.log(invoice.status);
648
+ * } catch (err) {
649
+ * if (err instanceof TxnodWalletNotFoundError) {
650
+ * console.error(err.error_code, err.request_id);
651
+ * return;
652
+ * }
653
+ * throw err;
654
+ * }
655
+ * ```
656
+ */
657
+ export class TxnodWalletNotFoundError extends TxnodError {
658
+ kind = 'wallet_not_found';
659
+ constructor(details) {
660
+ super(details);
661
+ this.name = 'TxnodWalletNotFoundError';
662
+ }
663
+ }
664
+ /**
665
+ * Thrown when the server responds with `error_code: 'external_id_conflict'` —
666
+ * an invoice with the requested `external_id` already exists for this
667
+ * project. Treat as idempotent success and fetch the existing invoice.
668
+ *
669
+ * @example
670
+ * ```ts
671
+ * import { TxnodClient, TxnodExternalIdConflictError } from '@txnod/sdk';
672
+ *
673
+ * const client = new TxnodClient({
674
+ * projectId: process.env.TXNOD_PROJECT_ID!,
675
+ * apiSecret: process.env.TXNOD_API_SECRET!,
676
+ * });
677
+ *
678
+ * try {
679
+ * const invoice = await client.createInvoice({
680
+ * amount_usd: 10,
681
+ * coin: 'btc',
682
+ * external_id: 'order-1',
683
+ * });
684
+ * console.log(invoice.id);
685
+ * } catch (err) {
686
+ * if (err instanceof TxnodExternalIdConflictError) {
687
+ * const page = await client.searchInvoices({ external_id: 'order-1', limit: 1 });
688
+ * const existing = page.items[0];
689
+ * if (existing !== undefined) console.log(existing.status);
690
+ * return;
691
+ * }
692
+ * throw err;
693
+ * }
694
+ * ```
695
+ */
696
+ export class TxnodExternalIdConflictError extends TxnodError {
697
+ kind = 'external_id_conflict';
698
+ constructor(details) {
699
+ super(details);
700
+ this.name = 'TxnodExternalIdConflictError';
701
+ }
702
+ }
703
+ /**
704
+ * Thrown when the server responds with `error_code: 'xpub_not_verified'` —
705
+ * the xpub for the chain has not completed its verification challenge yet.
706
+ *
707
+ * @example
708
+ * ```ts
709
+ * import { TxnodClient, TxnodXpubNotVerifiedError } from '@txnod/sdk';
710
+ *
711
+ * const client = new TxnodClient({
712
+ * projectId: process.env.TXNOD_PROJECT_ID!,
713
+ * apiSecret: process.env.TXNOD_API_SECRET!,
714
+ * });
715
+ *
716
+ * try {
717
+ * const invoice = await client.createInvoice({
718
+ * amount_usd: 10,
719
+ * coin: 'btc',
720
+ * external_id: 'order-1',
721
+ * });
722
+ * console.log(invoice.id);
723
+ * } catch (err) {
724
+ * if (err instanceof TxnodXpubNotVerifiedError) {
725
+ * console.error(err.error_code, err.request_id);
726
+ * return;
727
+ * }
728
+ * throw err;
729
+ * }
730
+ * ```
731
+ */
732
+ export class TxnodXpubNotVerifiedError extends TxnodError {
733
+ kind = 'xpub_not_verified';
734
+ constructor(details) {
735
+ super(details);
736
+ this.name = 'TxnodXpubNotVerifiedError';
737
+ }
738
+ }
739
+ /**
740
+ * Thrown when the server responds with `error_code: 'coin_not_enabled'` —
741
+ * the requested coin is not enabled for this project. Point the user at a
742
+ * coin from `client.getRates()`.
743
+ *
744
+ * @example
745
+ * ```ts
746
+ * import { TxnodClient, TxnodCoinNotEnabledError } from '@txnod/sdk';
747
+ *
748
+ * const client = new TxnodClient({
749
+ * projectId: process.env.TXNOD_PROJECT_ID!,
750
+ * apiSecret: process.env.TXNOD_API_SECRET!,
751
+ * });
752
+ *
753
+ * try {
754
+ * const invoice = await client.createInvoice({
755
+ * amount_usd: 10,
756
+ * coin: 'btc',
757
+ * external_id: 'order-1',
758
+ * });
759
+ * console.log(invoice.id);
760
+ * } catch (err) {
761
+ * if (err instanceof TxnodCoinNotEnabledError) {
762
+ * const rates = await client.getRates({});
763
+ * console.log('enabled coins:', Object.keys(rates.rates));
764
+ * return;
765
+ * }
766
+ * throw err;
767
+ * }
768
+ * ```
769
+ */
770
+ export class TxnodCoinNotEnabledError extends TxnodError {
771
+ kind = 'coin_not_enabled';
772
+ constructor(details) {
773
+ super(details);
774
+ this.name = 'TxnodCoinNotEnabledError';
775
+ }
776
+ }
777
+ /**
778
+ * Thrown when the server responds with `error_code: 'amount_out_of_range'` —
779
+ * the requested amount is outside the project's accepted range.
780
+ *
781
+ * @example
782
+ * ```ts
783
+ * import { TxnodClient, TxnodAmountOutOfRangeError } from '@txnod/sdk';
784
+ *
785
+ * const client = new TxnodClient({
786
+ * projectId: process.env.TXNOD_PROJECT_ID!,
787
+ * apiSecret: process.env.TXNOD_API_SECRET!,
788
+ * });
789
+ *
790
+ * try {
791
+ * const invoice = await client.createInvoice({
792
+ * amount_usd: 10,
793
+ * coin: 'btc',
794
+ * external_id: 'order-1',
795
+ * });
796
+ * console.log(invoice.id);
797
+ * } catch (err) {
798
+ * if (err instanceof TxnodAmountOutOfRangeError) {
799
+ * console.error(err.error_code, err.request_id);
800
+ * return;
801
+ * }
802
+ * throw err;
803
+ * }
804
+ * ```
805
+ */
806
+ export class TxnodAmountOutOfRangeError extends TxnodError {
807
+ kind = 'amount_out_of_range';
808
+ constructor(details) {
809
+ super(details);
810
+ this.name = 'TxnodAmountOutOfRangeError';
811
+ }
812
+ }
813
+ /**
814
+ * Thrown when the server responds with `error_code: 'rate_limit_exceeded'` —
815
+ * the per-key rate limit has been exceeded. The `retry_after_seconds` field
816
+ * carries the value of the HTTP `Retry-After` header (0 when absent).
817
+ *
818
+ * @example
819
+ * ```ts
820
+ * import { TxnodClient, TxnodRateLimitError } from '@txnod/sdk';
821
+ *
822
+ * const client = new TxnodClient({
823
+ * projectId: process.env.TXNOD_PROJECT_ID!,
824
+ * apiSecret: process.env.TXNOD_API_SECRET!,
825
+ * });
826
+ *
827
+ * try {
828
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
829
+ * console.log(invoice.status);
830
+ * } catch (err) {
831
+ * if (err instanceof TxnodRateLimitError) {
832
+ * await new Promise((r) => setTimeout(r, err.retry_after_seconds * 1000));
833
+ * const retry = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
834
+ * console.log(retry.status);
835
+ * return;
836
+ * }
837
+ * throw err;
838
+ * }
839
+ * ```
840
+ */
841
+ export class TxnodRateLimitError extends TxnodError {
842
+ kind = 'rate_limit_exceeded';
843
+ retry_after_seconds;
844
+ constructor(details, retryAfterSeconds) {
845
+ super(details);
846
+ this.name = 'TxnodRateLimitError';
847
+ this.retry_after_seconds = retryAfterSeconds;
848
+ }
849
+ }
850
+ /**
851
+ * Thrown when the server responds with `error_code: 'pool_exhausted'` — the
852
+ * per-chain derivation-address pool has hit its hard cap
853
+ * (`poolSizePerChain[chain]`) and no slot is currently `available`. The
854
+ * `retry_after_seconds` field carries the value of the HTTP `Retry-After`
855
+ * header (0 when absent) — the server derives it from the soonest
856
+ * `locked_until` across locked rows, falling back to the project's
857
+ * `cooldownSeconds`. Wait the indicated interval before retrying, or raise
858
+ * the per-chain pool cap if this fires under normal load.
859
+ *
860
+ * @example
861
+ * ```ts
862
+ * import { TxnodClient, TxnodPoolExhaustedError } from '@txnod/sdk';
863
+ *
864
+ * const client = new TxnodClient({
865
+ * projectId: process.env.TXNOD_PROJECT_ID!,
866
+ * apiSecret: process.env.TXNOD_API_SECRET!,
867
+ * });
868
+ *
869
+ * try {
870
+ * const invoice = await client.createInvoice({
871
+ * amount_usd: 10,
872
+ * coin: 'btc',
873
+ * external_id: 'order-1',
874
+ * });
875
+ * console.log(invoice.id);
876
+ * } catch (err) {
877
+ * if (err instanceof TxnodPoolExhaustedError) {
878
+ * await new Promise((r) => setTimeout(r, err.retry_after_seconds * 1000));
879
+ * const retry = await client.createInvoice({
880
+ * amount_usd: 10,
881
+ * coin: 'btc',
882
+ * external_id: 'order-1',
883
+ * });
884
+ * console.log(retry.id);
885
+ * return;
886
+ * }
887
+ * throw err;
888
+ * }
889
+ * ```
890
+ */
891
+ export class TxnodPoolExhaustedError extends TxnodError {
892
+ kind = 'pool_exhausted';
893
+ retry_after_seconds;
894
+ constructor(details, retryAfterSeconds) {
895
+ super(details);
896
+ this.name = 'TxnodPoolExhaustedError';
897
+ this.retry_after_seconds = retryAfterSeconds;
898
+ }
899
+ }
900
+ /**
901
+ * Thrown when the server responds with `error_code: 'webhook_capacity_exhausted'`
902
+ * — the chain's webhook fleet has no spare slots, so the server can't bind a
903
+ * new pool address to a webhook. `retry_after_seconds` is `0` because partner
904
+ * retry alone will not free capacity. Treat as a transient outage; queue the
905
+ * invoice and retry later.
906
+ *
907
+ * @example
908
+ * ```ts
909
+ * import { TxnodClient, TxnodWebhookCapacityExhaustedError } from '@txnod/sdk';
910
+ *
911
+ * const client = new TxnodClient({
912
+ * projectId: process.env.TXNOD_PROJECT_ID!,
913
+ * apiSecret: process.env.TXNOD_API_SECRET!,
914
+ * });
915
+ *
916
+ * try {
917
+ * await client.createInvoice({
918
+ * external_id: 'order-1',
919
+ * amount_usd: 100,
920
+ * coin: 'eth',
921
+ * });
922
+ * } catch (err) {
923
+ * if (err instanceof TxnodWebhookCapacityExhaustedError) {
924
+ * console.error('webhook fleet at capacity for chain:', err.kind);
925
+ * // Transient outage — queue invoice and retry later.
926
+ * return;
927
+ * }
928
+ * throw err;
929
+ * }
930
+ * ```
931
+ */
932
+ export class TxnodWebhookCapacityExhaustedError extends TxnodError {
933
+ kind = 'webhook_capacity_exhausted';
934
+ retry_after_seconds;
935
+ constructor(details, retryAfterSeconds) {
936
+ super(details);
937
+ this.name = 'TxnodWebhookCapacityExhaustedError';
938
+ this.retry_after_seconds = retryAfterSeconds;
939
+ }
940
+ }
941
+ /**
942
+ * Thrown when the server responds with `error_code: 'internal_error'` — the
943
+ * server failed for a reason it could not categorize. Log `err.request_id`
944
+ * for support and treat as a retryable 5xx.
945
+ *
946
+ * @example
947
+ * ```ts
948
+ * import { TxnodClient, TxnodServerError } from '@txnod/sdk';
949
+ *
950
+ * const client = new TxnodClient({
951
+ * projectId: process.env.TXNOD_PROJECT_ID!,
952
+ * apiSecret: process.env.TXNOD_API_SECRET!,
953
+ * });
954
+ *
955
+ * try {
956
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
957
+ * console.log(invoice.status);
958
+ * } catch (err) {
959
+ * if (err instanceof TxnodServerError) {
960
+ * console.error('TxNod server error — report request_id to support:', err.request_id);
961
+ * return;
962
+ * }
963
+ * throw err;
964
+ * }
965
+ * ```
966
+ */
967
+ export class TxnodServerError extends TxnodError {
968
+ kind = 'internal_error';
969
+ constructor(details) {
970
+ super(details);
971
+ this.name = 'TxnodServerError';
972
+ }
973
+ }
974
+ /**
975
+ * Thrown when the server responds with `error_code: 'invoice_not_cancellable'`
976
+ * — the invoice is in a state that does not permit cancellation.
977
+ *
978
+ * @example
979
+ * ```ts
980
+ * import { TxnodClient, TxnodInvoiceNotCancellableError } from '@txnod/sdk';
981
+ *
982
+ * const client = new TxnodClient({
983
+ * projectId: process.env.TXNOD_PROJECT_ID!,
984
+ * apiSecret: process.env.TXNOD_API_SECRET!,
985
+ * });
986
+ *
987
+ * try {
988
+ * const invoice = await client.cancelInvoice('01HK8MAR2QEXAMPLE000000000');
989
+ * console.log(invoice.status);
990
+ * } catch (err) {
991
+ * if (err instanceof TxnodInvoiceNotCancellableError) {
992
+ * console.error(err.error_code, err.request_id);
993
+ * return;
994
+ * }
995
+ * throw err;
996
+ * }
997
+ * ```
998
+ */
999
+ export class TxnodInvoiceNotCancellableError extends TxnodError {
1000
+ kind = 'invoice_not_cancellable';
1001
+ constructor(details) {
1002
+ super(details);
1003
+ this.name = 'TxnodInvoiceNotCancellableError';
1004
+ }
1005
+ }
1006
+ /**
1007
+ * Thrown when the server responds with `error_code: 'invalid_state_transition'`
1008
+ * — the requested operation would produce an illegal invoice state
1009
+ * transition.
1010
+ *
1011
+ * @example
1012
+ * ```ts
1013
+ * import { TxnodClient, TxnodInvalidStateTransitionError } from '@txnod/sdk';
1014
+ *
1015
+ * const client = new TxnodClient({
1016
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1017
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1018
+ * });
1019
+ *
1020
+ * try {
1021
+ * const invoice = await client.cancelInvoice('01HK8MAR2QEXAMPLE000000000');
1022
+ * console.log(invoice.status);
1023
+ * } catch (err) {
1024
+ * if (err instanceof TxnodInvalidStateTransitionError) {
1025
+ * console.error(err.error_code, err.request_id);
1026
+ * return;
1027
+ * }
1028
+ * throw err;
1029
+ * }
1030
+ * ```
1031
+ */
1032
+ export class TxnodInvalidStateTransitionError extends TxnodError {
1033
+ kind = 'invalid_state_transition';
1034
+ constructor(details) {
1035
+ super(details);
1036
+ this.name = 'TxnodInvalidStateTransitionError';
1037
+ }
1038
+ }
1039
+ /**
1040
+ * Thrown when the server responds with `error_code: 'orphan_not_found'` —
1041
+ * no orphan payment exists with the given tx hash.
1042
+ *
1043
+ * @example
1044
+ * ```ts
1045
+ * import { TxnodClient, TxnodOrphanNotFoundError } from '@txnod/sdk';
1046
+ *
1047
+ * const client = new TxnodClient({
1048
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1049
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1050
+ * });
1051
+ *
1052
+ * try {
1053
+ * await client.attributeOrphanPayment('0xabc', { external_id: 'order-1' });
1054
+ * } catch (err) {
1055
+ * if (err instanceof TxnodOrphanNotFoundError) {
1056
+ * console.error(err.error_code, err.request_id);
1057
+ * return;
1058
+ * }
1059
+ * throw err;
1060
+ * }
1061
+ * ```
1062
+ */
1063
+ export class TxnodOrphanNotFoundError extends TxnodError {
1064
+ kind = 'orphan_not_found';
1065
+ constructor(details) {
1066
+ super(details);
1067
+ this.name = 'TxnodOrphanNotFoundError';
1068
+ }
1069
+ }
1070
+ /**
1071
+ * Thrown when the server responds with `error_code: 'orphan_already_attributed'`
1072
+ * — the orphan payment has already been attributed to an invoice.
1073
+ *
1074
+ * @example
1075
+ * ```ts
1076
+ * import { TxnodClient, TxnodOrphanAlreadyAttributedError } from '@txnod/sdk';
1077
+ *
1078
+ * const client = new TxnodClient({
1079
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1080
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1081
+ * });
1082
+ *
1083
+ * try {
1084
+ * await client.attributeOrphanPayment('0xabc', { external_id: 'order-1' });
1085
+ * } catch (err) {
1086
+ * if (err instanceof TxnodOrphanAlreadyAttributedError) {
1087
+ * console.error(err.error_code, err.request_id);
1088
+ * return;
1089
+ * }
1090
+ * throw err;
1091
+ * }
1092
+ * ```
1093
+ */
1094
+ export class TxnodOrphanAlreadyAttributedError extends TxnodError {
1095
+ kind = 'orphan_already_attributed';
1096
+ constructor(details) {
1097
+ super(details);
1098
+ this.name = 'TxnodOrphanAlreadyAttributedError';
1099
+ }
1100
+ }
1101
+ /**
1102
+ * Thrown when the server responds with `error_code: 'event_not_found'` — no
1103
+ * webhook event exists with the given id for this project.
1104
+ *
1105
+ * @example
1106
+ * ```ts
1107
+ * import { TxnodClient, TxnodEventNotFoundError } from '@txnod/sdk';
1108
+ *
1109
+ * const client = new TxnodClient({
1110
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1111
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1112
+ * });
1113
+ *
1114
+ * try {
1115
+ * await client.resendWebhookEvent('01HK8MAR2QEXAMPLE000000000');
1116
+ * } catch (err) {
1117
+ * if (err instanceof TxnodEventNotFoundError) {
1118
+ * console.error(err.error_code, err.request_id);
1119
+ * return;
1120
+ * }
1121
+ * throw err;
1122
+ * }
1123
+ * ```
1124
+ */
1125
+ export class TxnodEventNotFoundError extends TxnodError {
1126
+ kind = 'event_not_found';
1127
+ constructor(details) {
1128
+ super(details);
1129
+ this.name = 'TxnodEventNotFoundError';
1130
+ }
1131
+ }
1132
+ /**
1133
+ * Thrown when the server responds with `error_code: 'wallet_not_bound'` —
1134
+ * the target project has no verified wallet bound for the requested chain.
1135
+ * The chain is implied by the invoice's `coin` and the project's `kind`
1136
+ * (production / testnet) is fixed at project create time. Bind a wallet of
1137
+ * matching kind via the dashboard or the binding API before retrying invoice
1138
+ * creation.
1139
+ *
1140
+ * Status: 422 (was 409 in pre-`testnet`-kind builds).
1141
+ *
1142
+ * @example
1143
+ * ```ts
1144
+ * import { TxnodClient, TxnodWalletNotBoundError } from '@txnod/sdk';
1145
+ *
1146
+ * const client = new TxnodClient({
1147
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1148
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1149
+ * });
1150
+ *
1151
+ * try {
1152
+ * const invoice = await client.createInvoice({
1153
+ * amount_usd: 10,
1154
+ * coin: 'btc',
1155
+ * external_id: 'order-1',
1156
+ * });
1157
+ * console.log(invoice.id);
1158
+ * } catch (err) {
1159
+ * if (err instanceof TxnodWalletNotBoundError) {
1160
+ * console.error('bind a wallet before retrying', err.request_id);
1161
+ * return;
1162
+ * }
1163
+ * throw err;
1164
+ * }
1165
+ * ```
1166
+ */
1167
+ export class TxnodWalletNotBoundError extends TxnodError {
1168
+ kind = 'wallet_not_bound';
1169
+ constructor(details) {
1170
+ super(details);
1171
+ this.name = 'TxnodWalletNotBoundError';
1172
+ }
1173
+ }
1174
+ /**
1175
+ * Thrown when the server responds with `error_code: 'wallet_kind_mismatch'`
1176
+ * (HTTP 422) — the operator attempted to bind an `operator_wallet` of one
1177
+ * `kind` (e.g. `'testnet'`) to a project of a different `kind` (e.g.
1178
+ * `'production'`). Project kind is fixed at create time and cross-kind
1179
+ * binding is forbidden — production projects accept only production wallets,
1180
+ * testnet projects accept only testnet wallets, sandbox projects auto-derive
1181
+ * their own simulated wallets and never reach the operator-binding surface.
1182
+ *
1183
+ * Recover by either creating a wallet of the matching kind, or creating a
1184
+ * fresh project of the wallet's kind.
1185
+ *
1186
+ * @example
1187
+ * ```ts
1188
+ * import { TxnodWalletKindMismatchError } from '@txnod/sdk';
1189
+ *
1190
+ * try {
1191
+ * // ...attempt a cross-kind wallet binding via a server action / internal API...
1192
+ * } catch (err) {
1193
+ * if (err instanceof TxnodWalletKindMismatchError) {
1194
+ * console.error('cannot bind across kinds', err.request_id);
1195
+ * return;
1196
+ * }
1197
+ * throw err;
1198
+ * }
1199
+ * ```
1200
+ */
1201
+ export class TxnodWalletKindMismatchError extends TxnodError {
1202
+ kind = 'wallet_kind_mismatch';
1203
+ constructor(details) {
1204
+ super(details);
1205
+ this.name = 'TxnodWalletKindMismatchError';
1206
+ }
1207
+ }
1208
+ /**
1209
+ * Thrown when the server responds with `error_code: 'wallet_not_owned'` — the
1210
+ * authenticated operator does not own the wallet targeted by the request.
1211
+ * Dashboard-only: the partner HMAC surface never exposes other-operator wallets,
1212
+ * so this error is limited to internal Server Actions.
1213
+ *
1214
+ * @example
1215
+ * ```ts
1216
+ * import { TxnodClient, TxnodWalletNotOwnedError } from '@txnod/sdk';
1217
+ *
1218
+ * const client = new TxnodClient({
1219
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1220
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1221
+ * });
1222
+ *
1223
+ * try {
1224
+ * const invoice = await client.getInvoice('01HK8MAR2QEXAMPLE000000000');
1225
+ * console.log(invoice.status);
1226
+ * } catch (err) {
1227
+ * if (err instanceof TxnodWalletNotOwnedError) {
1228
+ * console.error(err.error_code, err.request_id);
1229
+ * return;
1230
+ * }
1231
+ * throw err;
1232
+ * }
1233
+ * ```
1234
+ */
1235
+ export class TxnodWalletNotOwnedError extends TxnodError {
1236
+ kind = 'wallet_not_owned';
1237
+ constructor(details) {
1238
+ super(details);
1239
+ this.name = 'TxnodWalletNotOwnedError';
1240
+ }
1241
+ }
1242
+ /**
1243
+ * Thrown when the server responds with `error_code: 'wallet_has_active_bindings'`
1244
+ * — the authenticated operator attempted to archive an `operator_wallet` while
1245
+ * at least one `project_chain_wallet_bindings` row still references it. The
1246
+ * RFC-7807 response carries an `extensions.affected_projects` list of
1247
+ * `(project_id, project_name, chain)` tuples; future SDK methods will expose
1248
+ * them via a dedicated field on this class.
1249
+ *
1250
+ * @example
1251
+ * ```ts
1252
+ * import { TxnodWalletHasActiveBindingsError } from '@txnod/sdk';
1253
+ *
1254
+ * try {
1255
+ * // ...attempt to archive an operator wallet that still has active bindings...
1256
+ * } catch (err) {
1257
+ * if (err instanceof TxnodWalletHasActiveBindingsError) {
1258
+ * console.error('rebind affected projects first', err.request_id);
1259
+ * return;
1260
+ * }
1261
+ * throw err;
1262
+ * }
1263
+ * ```
1264
+ */
1265
+ export class TxnodWalletHasActiveBindingsError extends TxnodError {
1266
+ kind = 'wallet_has_active_bindings';
1267
+ constructor(details) {
1268
+ super(details);
1269
+ this.name = 'TxnodWalletHasActiveBindingsError';
1270
+ }
1271
+ }
1272
+ /**
1273
+ * Thrown when the server responds with `error_code: 'subscription_expired'`
1274
+ * (HTTP 402) — the authenticated operator's subscription is not `active`
1275
+ * and write operations are blocked. Reads remain available. The operator
1276
+ * must renew via `/billing` before writes will succeed again.
1277
+ *
1278
+ * @example
1279
+ * ```ts
1280
+ * import { TxnodClient, TxnodSubscriptionExpiredError } from '@txnod/sdk';
1281
+ *
1282
+ * const client = new TxnodClient({
1283
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1284
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1285
+ * });
1286
+ *
1287
+ * try {
1288
+ * await client.createInvoice({ external_id: 'o-1', amount_usd: 50, coin: 'btc' });
1289
+ * } catch (err) {
1290
+ * if (err instanceof TxnodSubscriptionExpiredError) {
1291
+ * console.error('renew subscription at /billing', err.request_id);
1292
+ * return;
1293
+ * }
1294
+ * throw err;
1295
+ * }
1296
+ * ```
1297
+ */
1298
+ export class TxnodSubscriptionExpiredError extends TxnodError {
1299
+ kind = 'subscription_expired';
1300
+ constructor(details) {
1301
+ super(details);
1302
+ this.name = 'TxnodSubscriptionExpiredError';
1303
+ }
1304
+ }
1305
+ /**
1306
+ * Thrown when the server responds with `error_code: 'tron_no_activated_addresses_available'`
1307
+ * (HTTP 422) — the operator's TRON pool has zero activated addresses and the
1308
+ * invoice cannot be issued. The `wallet_id` field carries the operator wallet
1309
+ * id; deep-link the operator into `/wallets/{wallet_id}` where they can
1310
+ * activate addresses via a third-party multisend service or an in-dashboard
1311
+ * Ledger tool.
1312
+ *
1313
+ * @example
1314
+ * ```ts
1315
+ * import { TxnodClient, TxnodTronNoActivatedAddressesError } from '@txnod/sdk';
1316
+ *
1317
+ * const client = new TxnodClient({
1318
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1319
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1320
+ * });
1321
+ *
1322
+ * try {
1323
+ * const invoice = await client.createInvoice({
1324
+ * amount_usd: 10,
1325
+ * coin: 'usdt_trc20',
1326
+ * external_id: 'order-1',
1327
+ * });
1328
+ * console.log(invoice.id);
1329
+ * } catch (err) {
1330
+ * if (err instanceof TxnodTronNoActivatedAddressesError) {
1331
+ * console.error('activate addresses for wallet', err.walletId);
1332
+ * return;
1333
+ * }
1334
+ * throw err;
1335
+ * }
1336
+ * ```
1337
+ */
1338
+ export class TxnodTronNoActivatedAddressesError extends TxnodError {
1339
+ kind = 'tron_no_activated_addresses_available';
1340
+ walletId;
1341
+ constructor(details) {
1342
+ super(details);
1343
+ this.name = 'TxnodTronNoActivatedAddressesError';
1344
+ if (typeof details.wallet_id !== 'string' || details.wallet_id.length === 0) {
1345
+ throw new Error('TxnodTronNoActivatedAddressesError: wallet_id is required on the problem-details body');
1346
+ }
1347
+ this.walletId = details.wallet_id;
1348
+ }
1349
+ }
1350
+ /**
1351
+ * Thrown when the server responds with `error_code: 'ton_operator_wallet_not_deployed'`
1352
+ * (HTTP 422) — the operator's TON wallet has not yet been deployed on-chain,
1353
+ * so a deposit cannot be issued. Trigger the wallet's first outbound message
1354
+ * (or send a no-op transaction) to deploy the contract, then retry.
1355
+ *
1356
+ * @example
1357
+ * ```ts
1358
+ * import { TxnodClient, TxnodTonOperatorWalletNotDeployedError } from '@txnod/sdk';
1359
+ *
1360
+ * const client = new TxnodClient({
1361
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1362
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1363
+ * });
1364
+ *
1365
+ * try {
1366
+ * const invoice = await client.createInvoice({
1367
+ * amount_usd: 10,
1368
+ * coin: 'ton',
1369
+ * external_id: 'order-1',
1370
+ * });
1371
+ * console.log(invoice.id);
1372
+ * } catch (err) {
1373
+ * if (err instanceof TxnodTonOperatorWalletNotDeployedError) {
1374
+ * console.error('deploy operator wallet before issuing TON invoices', err.request_id);
1375
+ * return;
1376
+ * }
1377
+ * throw err;
1378
+ * }
1379
+ * ```
1380
+ */
1381
+ export class TxnodTonOperatorWalletNotDeployedError extends TxnodError {
1382
+ kind = 'ton_operator_wallet_not_deployed';
1383
+ constructor(details) {
1384
+ super(details);
1385
+ this.name = 'TxnodTonOperatorWalletNotDeployedError';
1386
+ }
1387
+ }
1388
+ /**
1389
+ * Thrown when the server responds with `error_code: 'ton_invalid_wallet_version'`
1390
+ * (HTTP 422) — the TON wallet version supplied is not one of the supported
1391
+ * versions (`v3R2`, `v4R2`, `v5R1`).
1392
+ *
1393
+ * @example
1394
+ * ```ts
1395
+ * import { TxnodClient, TxnodTonInvalidWalletVersionError } from '@txnod/sdk';
1396
+ *
1397
+ * const client = new TxnodClient({
1398
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1399
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1400
+ * });
1401
+ *
1402
+ * try {
1403
+ * const invoice = await client.createInvoice({
1404
+ * amount_usd: 10,
1405
+ * coin: 'ton',
1406
+ * external_id: 'order-1',
1407
+ * });
1408
+ * console.log(invoice.id);
1409
+ * } catch (err) {
1410
+ * if (err instanceof TxnodTonInvalidWalletVersionError) {
1411
+ * console.error('register a v3R2/v4R2/v5R1 wallet', err.request_id);
1412
+ * return;
1413
+ * }
1414
+ * throw err;
1415
+ * }
1416
+ * ```
1417
+ */
1418
+ export class TxnodTonInvalidWalletVersionError extends TxnodError {
1419
+ kind = 'ton_invalid_wallet_version';
1420
+ constructor(details) {
1421
+ super(details);
1422
+ this.name = 'TxnodTonInvalidWalletVersionError';
1423
+ }
1424
+ }
1425
+ /**
1426
+ * Thrown when the server responds with `error_code: 'ton_jetton_resolve_failed'`
1427
+ * (HTTP 503) — the TON jetton-wallet address could not be resolved because
1428
+ * the upstream provider is temporarily unavailable. The error is retryable.
1429
+ *
1430
+ * @example
1431
+ * ```ts
1432
+ * import { TxnodClient, TxnodTonJettonResolveFailedError } from '@txnod/sdk';
1433
+ *
1434
+ * const client = new TxnodClient({
1435
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1436
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1437
+ * });
1438
+ *
1439
+ * try {
1440
+ * const invoice = await client.createInvoice({
1441
+ * amount_usd: 10,
1442
+ * coin: 'usdt_ton',
1443
+ * external_id: 'order-1',
1444
+ * });
1445
+ * console.log(invoice.id);
1446
+ * } catch (err) {
1447
+ * if (err instanceof TxnodTonJettonResolveFailedError) {
1448
+ * console.error('jetton resolver unavailable; retrying soon', err.request_id);
1449
+ * return;
1450
+ * }
1451
+ * throw err;
1452
+ * }
1453
+ * ```
1454
+ */
1455
+ export class TxnodTonJettonResolveFailedError extends TxnodError {
1456
+ kind = 'ton_jetton_resolve_failed';
1457
+ constructor(details) {
1458
+ super(details);
1459
+ this.name = 'TxnodTonJettonResolveFailedError';
1460
+ }
1461
+ }
1462
+ /**
1463
+ * Thrown when the server responds with `error_code: 'ton_comment_parse_failed'`
1464
+ * (HTTP 422) — a TON deposit comment could not be parsed as a payment token.
1465
+ * Surfaces through the orphan / unattributed-deposit flow rather than the
1466
+ * partner integration API, but is included here for SDK error mapping
1467
+ * completeness.
1468
+ *
1469
+ * @example
1470
+ * ```ts
1471
+ * import { TxnodClient, TxnodTonCommentParseFailedError } from '@txnod/sdk';
1472
+ *
1473
+ * const client = new TxnodClient({
1474
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1475
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1476
+ * });
1477
+ *
1478
+ * try {
1479
+ * await client.attributeOrphanPayment('0xabc', { external_id: 'order-1' });
1480
+ * } catch (err) {
1481
+ * if (err instanceof TxnodTonCommentParseFailedError) {
1482
+ * console.error('TON deposit comment was unparseable', err.request_id);
1483
+ * return;
1484
+ * }
1485
+ * throw err;
1486
+ * }
1487
+ * ```
1488
+ */
1489
+ export class TxnodTonCommentParseFailedError extends TxnodError {
1490
+ kind = 'ton_comment_parse_failed';
1491
+ constructor(details) {
1492
+ super(details);
1493
+ this.name = 'TxnodTonCommentParseFailedError';
1494
+ }
1495
+ }
1496
+ // TON Connect /payload + /verify error classes — produced by
1497
+ // `/api/internal/wallets/tonconnect/*` and flowed through the generic
1498
+ // `parseProblemDetails` mapper.
1499
+ /**
1500
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_payload_expired'`.
1501
+ * The TON Connect handshake nonce expired (5-minute TTL); restart the wizard.
1502
+ *
1503
+ * @example
1504
+ * ```ts
1505
+ * import { TxnodTonConnectPayloadExpiredError } from '@txnod/sdk';
1506
+ *
1507
+ * try {
1508
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1509
+ * } catch (err) {
1510
+ * if (err instanceof TxnodTonConnectPayloadExpiredError) {
1511
+ * console.error('TON Connect nonce expired', err.request_id);
1512
+ * }
1513
+ * }
1514
+ * ```
1515
+ */
1516
+ export class TxnodTonConnectPayloadExpiredError extends TxnodError {
1517
+ kind = 'tonconnect_payload_expired';
1518
+ constructor(details) {
1519
+ super(details);
1520
+ this.name = 'TxnodTonConnectPayloadExpiredError';
1521
+ }
1522
+ }
1523
+ /**
1524
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_payload_unknown'`.
1525
+ * The proof's payload field does not match any nonce on file for this operator.
1526
+ *
1527
+ * @example
1528
+ * ```ts
1529
+ * import { TxnodTonConnectPayloadUnknownError } from '@txnod/sdk';
1530
+ *
1531
+ * try {
1532
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1533
+ * } catch (err) {
1534
+ * if (err instanceof TxnodTonConnectPayloadUnknownError) {
1535
+ * console.error('TON Connect nonce unknown', err.request_id);
1536
+ * }
1537
+ * }
1538
+ * ```
1539
+ */
1540
+ export class TxnodTonConnectPayloadUnknownError extends TxnodError {
1541
+ kind = 'tonconnect_payload_unknown';
1542
+ constructor(details) {
1543
+ super(details);
1544
+ this.name = 'TxnodTonConnectPayloadUnknownError';
1545
+ }
1546
+ }
1547
+ /**
1548
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_domain_mismatch'`.
1549
+ * The wallet attested to a different domain than the server's TXNOD_TONCONNECT_DOMAIN.
1550
+ *
1551
+ * @example
1552
+ * ```ts
1553
+ * import { TxnodTonConnectDomainMismatchError } from '@txnod/sdk';
1554
+ *
1555
+ * try {
1556
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1557
+ * } catch (err) {
1558
+ * if (err instanceof TxnodTonConnectDomainMismatchError) {
1559
+ * console.error('TON Connect domain mismatch', err.request_id);
1560
+ * }
1561
+ * }
1562
+ * ```
1563
+ */
1564
+ export class TxnodTonConnectDomainMismatchError extends TxnodError {
1565
+ kind = 'tonconnect_domain_mismatch';
1566
+ constructor(details) {
1567
+ super(details);
1568
+ this.name = 'TxnodTonConnectDomainMismatchError';
1569
+ }
1570
+ }
1571
+ /**
1572
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_timestamp_skew'`.
1573
+ * The proof timestamp is outside the 5-minute / +60s acceptance window.
1574
+ *
1575
+ * @example
1576
+ * ```ts
1577
+ * import { TxnodTonConnectTimestampSkewError } from '@txnod/sdk';
1578
+ *
1579
+ * try {
1580
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1581
+ * } catch (err) {
1582
+ * if (err instanceof TxnodTonConnectTimestampSkewError) {
1583
+ * console.error('TON Connect timestamp skew', err.request_id);
1584
+ * }
1585
+ * }
1586
+ * ```
1587
+ */
1588
+ export class TxnodTonConnectTimestampSkewError extends TxnodError {
1589
+ kind = 'tonconnect_timestamp_skew';
1590
+ constructor(details) {
1591
+ super(details);
1592
+ this.name = 'TxnodTonConnectTimestampSkewError';
1593
+ }
1594
+ }
1595
+ /**
1596
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_unknown_wallet_version'`.
1597
+ * The wallet's `walletStateInit` does not match any known TON wallet version.
1598
+ *
1599
+ * @example
1600
+ * ```ts
1601
+ * import { TxnodTonConnectUnknownWalletVersionError } from '@txnod/sdk';
1602
+ *
1603
+ * try {
1604
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1605
+ * } catch (err) {
1606
+ * if (err instanceof TxnodTonConnectUnknownWalletVersionError) {
1607
+ * console.error('TON Connect unknown wallet version', err.request_id);
1608
+ * }
1609
+ * }
1610
+ * ```
1611
+ */
1612
+ export class TxnodTonConnectUnknownWalletVersionError extends TxnodError {
1613
+ kind = 'tonconnect_unknown_wallet_version';
1614
+ constructor(details) {
1615
+ super(details);
1616
+ this.name = 'TxnodTonConnectUnknownWalletVersionError';
1617
+ }
1618
+ }
1619
+ /**
1620
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_signature_invalid'`.
1621
+ * The Ed25519 verification of the ton_proof signature failed.
1622
+ *
1623
+ * @example
1624
+ * ```ts
1625
+ * import { TxnodTonConnectSignatureInvalidError } from '@txnod/sdk';
1626
+ *
1627
+ * try {
1628
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1629
+ * } catch (err) {
1630
+ * if (err instanceof TxnodTonConnectSignatureInvalidError) {
1631
+ * console.error('TON Connect proof rejected', err.request_id);
1632
+ * }
1633
+ * }
1634
+ * ```
1635
+ */
1636
+ export class TxnodTonConnectSignatureInvalidError extends TxnodError {
1637
+ kind = 'tonconnect_signature_invalid';
1638
+ constructor(details) {
1639
+ super(details);
1640
+ this.name = 'TxnodTonConnectSignatureInvalidError';
1641
+ }
1642
+ }
1643
+ /**
1644
+ * Thrown when the dashboard responds with `error_code: 'tonconnect_network_mismatch'`.
1645
+ * The wallet reported a chain id (`-239`/`-3`) that disagrees with the wizard's network.
1646
+ *
1647
+ * @example
1648
+ * ```ts
1649
+ * import { TxnodTonConnectNetworkMismatchError } from '@txnod/sdk';
1650
+ *
1651
+ * try {
1652
+ * // SDK call that bubbles a /tonconnect/verify problem+json
1653
+ * } catch (err) {
1654
+ * if (err instanceof TxnodTonConnectNetworkMismatchError) {
1655
+ * console.error('TON Connect network mismatch', err.request_id);
1656
+ * }
1657
+ * }
1658
+ * ```
1659
+ */
1660
+ export class TxnodTonConnectNetworkMismatchError extends TxnodError {
1661
+ kind = 'tonconnect_network_mismatch';
1662
+ constructor(details) {
1663
+ super(details);
1664
+ this.name = 'TxnodTonConnectNetworkMismatchError';
1665
+ }
1666
+ }
1667
+ /**
1668
+ * Thrown when the server responds with `error_code: 'sandbox_project_required'`.
1669
+ * The endpoint accepts only sandbox projects and the targeted project's `kind`
1670
+ * is `production`. Story 37.3 will surface a richer SDK surface.
1671
+ *
1672
+ * @example
1673
+ * ```ts
1674
+ * import { TxnodSandboxProjectRequiredError } from '@txnod/sdk';
1675
+ *
1676
+ * try {
1677
+ * // SDK call that targets a sandbox-only endpoint
1678
+ * } catch (err) {
1679
+ * if (err instanceof TxnodSandboxProjectRequiredError) {
1680
+ * console.error('Sandbox-only endpoint', err.request_id);
1681
+ * }
1682
+ * }
1683
+ * ```
1684
+ */
1685
+ export class TxnodSandboxProjectRequiredError extends TxnodError {
1686
+ kind = 'sandbox_project_required';
1687
+ constructor(details) {
1688
+ super(details);
1689
+ this.name = 'TxnodSandboxProjectRequiredError';
1690
+ }
1691
+ }
1692
+ /**
1693
+ * Thrown when the server responds with `error_code: 'production_project_required'`.
1694
+ * The endpoint accepts only production projects and the targeted project's
1695
+ * `kind` is `sandbox` or `testnet`.
1696
+ *
1697
+ * @example
1698
+ * ```ts
1699
+ * import { TxnodProductionProjectRequiredError } from '@txnod/sdk';
1700
+ *
1701
+ * try {
1702
+ * // SDK call that targets a production-only endpoint
1703
+ * } catch (err) {
1704
+ * if (err instanceof TxnodProductionProjectRequiredError) {
1705
+ * console.error('Production-only endpoint', err.request_id);
1706
+ * }
1707
+ * }
1708
+ * ```
1709
+ */
1710
+ export class TxnodProductionProjectRequiredError extends TxnodError {
1711
+ kind = 'production_project_required';
1712
+ constructor(details) {
1713
+ super(details);
1714
+ this.name = 'TxnodProductionProjectRequiredError';
1715
+ }
1716
+ }
1717
+ /**
1718
+ * Thrown when the server responds with `error_code: 'sandbox_per_operator_cap_reached'`.
1719
+ * The operator already has the maximum number of active sandbox projects.
1720
+ *
1721
+ * @example
1722
+ * ```ts
1723
+ * import { TxnodSandboxPerOperatorCapReachedError } from '@txnod/sdk';
1724
+ *
1725
+ * try {
1726
+ * // SDK call that creates a new sandbox project
1727
+ * } catch (err) {
1728
+ * if (err instanceof TxnodSandboxPerOperatorCapReachedError) {
1729
+ * console.error('sandbox cap reached', err.request_id);
1730
+ * }
1731
+ * }
1732
+ * ```
1733
+ */
1734
+ export class TxnodSandboxPerOperatorCapReachedError extends TxnodError {
1735
+ kind = 'sandbox_per_operator_cap_reached';
1736
+ constructor(details) {
1737
+ super(details);
1738
+ this.name = 'TxnodSandboxPerOperatorCapReachedError';
1739
+ }
1740
+ }
1741
+ /**
1742
+ * Thrown when the server responds with `error_code: 'sandbox_key_against_production_project'`.
1743
+ * A sandbox API key (prefix `sk_sandbox_`) was used against a production project.
1744
+ *
1745
+ * @example
1746
+ * ```ts
1747
+ * import { TxnodSandboxKeyAgainstProductionProjectError } from '@txnod/sdk';
1748
+ *
1749
+ * try {
1750
+ * // SDK call with mixed-mode credentials
1751
+ * } catch (err) {
1752
+ * if (err instanceof TxnodSandboxKeyAgainstProductionProjectError) {
1753
+ * console.error('cross-mode rejected', err.request_id);
1754
+ * }
1755
+ * }
1756
+ * ```
1757
+ */
1758
+ export class TxnodSandboxKeyAgainstProductionProjectError extends TxnodError {
1759
+ kind = 'sandbox_key_against_production_project';
1760
+ constructor(details) {
1761
+ super(details);
1762
+ this.name = 'TxnodSandboxKeyAgainstProductionProjectError';
1763
+ }
1764
+ }
1765
+ /**
1766
+ * Thrown when the server responds with `error_code: 'production_key_against_sandbox_project'`.
1767
+ * A production API key was used against a sandbox project.
1768
+ *
1769
+ * @example
1770
+ * ```ts
1771
+ * import { TxnodProductionKeyAgainstSandboxProjectError } from '@txnod/sdk';
1772
+ *
1773
+ * try {
1774
+ * // SDK call with mixed-mode credentials
1775
+ * } catch (err) {
1776
+ * if (err instanceof TxnodProductionKeyAgainstSandboxProjectError) {
1777
+ * console.error('cross-mode rejected', err.request_id);
1778
+ * }
1779
+ * }
1780
+ * ```
1781
+ */
1782
+ export class TxnodProductionKeyAgainstSandboxProjectError extends TxnodError {
1783
+ kind = 'production_key_against_sandbox_project';
1784
+ constructor(details) {
1785
+ super(details);
1786
+ this.name = 'TxnodProductionKeyAgainstSandboxProjectError';
1787
+ }
1788
+ }
1789
+ /**
1790
+ * Thrown when the server responds with `error_code: 'sandbox_provisioning_failed'`.
1791
+ * The sandbox project could not be provisioned (transient or internal error).
1792
+ *
1793
+ * @example
1794
+ * ```ts
1795
+ * import { TxnodSandboxProvisioningFailedError } from '@txnod/sdk';
1796
+ *
1797
+ * try {
1798
+ * // SDK call that creates a new sandbox project
1799
+ * } catch (err) {
1800
+ * if (err instanceof TxnodSandboxProvisioningFailedError) {
1801
+ * console.error('sandbox provisioning failed', err.request_id);
1802
+ * }
1803
+ * }
1804
+ * ```
1805
+ */
1806
+ export class TxnodSandboxProvisioningFailedError extends TxnodError {
1807
+ kind = 'sandbox_provisioning_failed';
1808
+ constructor(details) {
1809
+ super(details);
1810
+ this.name = 'TxnodSandboxProvisioningFailedError';
1811
+ }
1812
+ }
1813
+ /**
1814
+ * Thrown when the server responds with `error_code: 'sandbox_invoice_transition_invalid'`.
1815
+ * A simulate-* call requested a state-machine transition forbidden by the
1816
+ * invoice's current status. Story 37.3 will surface a richer SDK surface.
1817
+ *
1818
+ * @example
1819
+ * ```ts
1820
+ * import { TxnodSandboxInvoiceTransitionInvalidError } from '@txnod/sdk';
1821
+ *
1822
+ * try {
1823
+ * // SDK call into a sandbox simulate-* endpoint
1824
+ * } catch (err) {
1825
+ * if (err instanceof TxnodSandboxInvoiceTransitionInvalidError) {
1826
+ * console.error('forbidden transition', err.request_id);
1827
+ * }
1828
+ * }
1829
+ * ```
1830
+ */
1831
+ export class TxnodSandboxInvoiceTransitionInvalidError extends TxnodError {
1832
+ kind = 'sandbox_invoice_transition_invalid';
1833
+ constructor(details) {
1834
+ super(details);
1835
+ this.name = 'TxnodSandboxInvoiceTransitionInvalidError';
1836
+ }
1837
+ }
1838
+ /**
1839
+ * Thrown when the server responds with `error_code: 'sandbox_invoice_not_found'`.
1840
+ *
1841
+ * @example
1842
+ * ```ts
1843
+ * import { TxnodSandboxInvoiceNotFoundError } from '@txnod/sdk';
1844
+ *
1845
+ * try {
1846
+ * // SDK call into a sandbox simulate-* endpoint
1847
+ * } catch (err) {
1848
+ * if (err instanceof TxnodSandboxInvoiceNotFoundError) {
1849
+ * console.error('sandbox invoice missing', err.request_id);
1850
+ * }
1851
+ * }
1852
+ * ```
1853
+ */
1854
+ export class TxnodSandboxInvoiceNotFoundError extends TxnodError {
1855
+ kind = 'sandbox_invoice_not_found';
1856
+ constructor(details) {
1857
+ super(details);
1858
+ this.name = 'TxnodSandboxInvoiceNotFoundError';
1859
+ }
1860
+ }
1861
+ /**
1862
+ * Thrown when the server responds with `error_code: 'sandbox_invoice_terminal'`.
1863
+ *
1864
+ * @example
1865
+ * ```ts
1866
+ * import { TxnodSandboxInvoiceTerminalError } from '@txnod/sdk';
1867
+ *
1868
+ * try {
1869
+ * // SDK call into a sandbox simulate-* endpoint
1870
+ * } catch (err) {
1871
+ * if (err instanceof TxnodSandboxInvoiceTerminalError) {
1872
+ * console.error('invoice already terminal', err.request_id);
1873
+ * }
1874
+ * }
1875
+ * ```
1876
+ */
1877
+ export class TxnodSandboxInvoiceTerminalError extends TxnodError {
1878
+ kind = 'sandbox_invoice_terminal';
1879
+ constructor(details) {
1880
+ super(details);
1881
+ this.name = 'TxnodSandboxInvoiceTerminalError';
1882
+ }
1883
+ }
1884
+ /**
1885
+ * Thrown when the server responds with `error_code: 'sandbox_rate_limit_exceeded'`.
1886
+ *
1887
+ * @example
1888
+ * ```ts
1889
+ * import { TxnodSandboxRateLimitExceededError } from '@txnod/sdk';
1890
+ *
1891
+ * try {
1892
+ * // SDK call into a sandbox simulate-* endpoint
1893
+ * } catch (err) {
1894
+ * if (err instanceof TxnodSandboxRateLimitExceededError) {
1895
+ * console.error('sandbox rate limited', err.request_id);
1896
+ * }
1897
+ * }
1898
+ * ```
1899
+ */
1900
+ export class TxnodSandboxRateLimitExceededError extends TxnodError {
1901
+ kind = 'sandbox_rate_limit_exceeded';
1902
+ constructor(details) {
1903
+ super(details);
1904
+ this.name = 'TxnodSandboxRateLimitExceededError';
1905
+ }
1906
+ }
1907
+ /**
1908
+ * Thrown when the server responds with `error_code: 'sandbox_reset_failed'`.
1909
+ *
1910
+ * @example
1911
+ * ```ts
1912
+ * import { TxnodSandboxResetFailedError } from '@txnod/sdk';
1913
+ *
1914
+ * try {
1915
+ * // SDK call to /api/v1/sandbox/{projectId}/reset
1916
+ * } catch (err) {
1917
+ * if (err instanceof TxnodSandboxResetFailedError) {
1918
+ * console.error('sandbox reset failed', err.request_id);
1919
+ * }
1920
+ * }
1921
+ * ```
1922
+ */
1923
+ export class TxnodSandboxResetFailedError extends TxnodError {
1924
+ kind = 'sandbox_reset_failed';
1925
+ constructor(details) {
1926
+ super(details);
1927
+ this.name = 'TxnodSandboxResetFailedError';
1928
+ }
1929
+ }
1930
+ /**
1931
+ * Thrown when the server responds with `error_code: 'sandbox_delete_failed'`.
1932
+ *
1933
+ * @example
1934
+ * ```ts
1935
+ * import { TxnodSandboxDeleteFailedError } from '@txnod/sdk';
1936
+ *
1937
+ * try {
1938
+ * // SDK call to DELETE /api/v1/sandbox/{projectId}
1939
+ * } catch (err) {
1940
+ * if (err instanceof TxnodSandboxDeleteFailedError) {
1941
+ * console.error('sandbox delete failed', err.request_id);
1942
+ * }
1943
+ * }
1944
+ * ```
1945
+ */
1946
+ export class TxnodSandboxDeleteFailedError extends TxnodError {
1947
+ kind = 'sandbox_delete_failed';
1948
+ constructor(details) {
1949
+ super(details);
1950
+ this.name = 'TxnodSandboxDeleteFailedError';
1951
+ }
1952
+ }
1953
+ /**
1954
+ * Thrown when the server responds with `error_code: 'sandbox_active_invoice_cap_reached'`.
1955
+ *
1956
+ * @example
1957
+ * ```ts
1958
+ * import { TxnodSandboxActiveInvoiceCapReachedError } from '@txnod/sdk';
1959
+ *
1960
+ * try {
1961
+ * // SDK call into POST /api/v1/invoices for a sandbox project
1962
+ * } catch (err) {
1963
+ * if (err instanceof TxnodSandboxActiveInvoiceCapReachedError) {
1964
+ * console.error('sandbox active-invoice cap reached', err.request_id);
1965
+ * }
1966
+ * }
1967
+ * ```
1968
+ */
1969
+ export class TxnodSandboxActiveInvoiceCapReachedError extends TxnodError {
1970
+ kind = 'sandbox_active_invoice_cap_reached';
1971
+ constructor(details) {
1972
+ super(details);
1973
+ this.name = 'TxnodSandboxActiveInvoiceCapReachedError';
1974
+ }
1975
+ }
1976
+ /**
1977
+ * Thrown synchronously by the `TxnodClient` constructor when the configured
1978
+ * `apiSecret` carries the `sk_sandbox_` prefix AND `getSdkEnv()` resolves to
1979
+ * `'production'` AND the `iAcknowledgeRoutingRealCustomerFundsToSandboxAddresses`
1980
+ * override is not set or `false`.
1981
+ *
1982
+ * The error names which signal triggered the production detection so the
1983
+ * operator can fix the configuration source. Boot fails — no client instance
1984
+ * is returned.
1985
+ *
1986
+ * @example
1987
+ * ```ts
1988
+ * import { TxnodClient, TxnodSandboxKeyInProductionError } from '@txnod/sdk';
1989
+ *
1990
+ * try {
1991
+ * const client = new TxnodClient({
1992
+ * projectId: process.env.TXNOD_PROJECT_ID!,
1993
+ * apiSecret: process.env.TXNOD_API_SECRET!,
1994
+ * });
1995
+ * void client;
1996
+ * } catch (err) {
1997
+ * if (err instanceof TxnodSandboxKeyInProductionError) {
1998
+ * console.error(
1999
+ * 'sandbox secret in production environment',
2000
+ * err.signal,
2001
+ * err.secretPrefix,
2002
+ * );
2003
+ * process.exit(1);
2004
+ * }
2005
+ * throw err;
2006
+ * }
2007
+ * ```
2008
+ */
2009
+ export class TxnodSandboxKeyInProductionError extends TxnodError {
2010
+ kind = 'sandbox_key_in_production';
2011
+ secretPrefix;
2012
+ detectedEnvironment;
2013
+ signal;
2014
+ constructor(signal) {
2015
+ super(syntheticDetails('auth_invalid', 401, `Sandbox API secret (sk_sandbox_*) detected in production environment via ${signal}. Refusing to construct TxnodClient. Set iAcknowledgeRoutingRealCustomerFundsToSandboxAddresses: true to override.`));
2016
+ this.name = 'TxnodSandboxKeyInProductionError';
2017
+ this.secretPrefix = 'sk_sandbox_';
2018
+ this.detectedEnvironment = 'production';
2019
+ this.signal = signal;
2020
+ }
2021
+ }
2022
+ /**
2023
+ * Thrown synchronously by the `TxnodClient` constructor when the configured
2024
+ * `apiSecret` carries the `sk_sandbox_` prefix AND `getSdkEnv()` returns
2025
+ * `'unknown'` (no signal indicates whether the runtime is production).
2026
+ *
2027
+ * The fix: set the `environment` constructor option, the
2028
+ * `TXNOD_ENVIRONMENT` env var, or `NODE_ENV` to a recognised value.
2029
+ *
2030
+ * @example
2031
+ * ```ts
2032
+ * import { TxnodClient, TxnodEnvironmentUnknownError } from '@txnod/sdk';
2033
+ *
2034
+ * try {
2035
+ * const client = new TxnodClient({
2036
+ * projectId: process.env.TXNOD_PROJECT_ID!,
2037
+ * apiSecret: process.env.TXNOD_API_SECRET!,
2038
+ * environment: 'non-production',
2039
+ * });
2040
+ * void client;
2041
+ * } catch (err) {
2042
+ * if (err instanceof TxnodEnvironmentUnknownError) {
2043
+ * console.error('environment unknown for sandbox secret', err.message);
2044
+ * process.exit(1);
2045
+ * }
2046
+ * throw err;
2047
+ * }
2048
+ * ```
2049
+ */
2050
+ export class TxnodEnvironmentUnknownError extends TxnodError {
2051
+ kind = 'environment_unknown';
2052
+ constructor() {
2053
+ super(syntheticDetails('auth_invalid', 401, 'Sandbox API secret (sk_sandbox_*) detected but environment is unknown. Set the `environment` constructor option, TXNOD_ENVIRONMENT, or NODE_ENV.'));
2054
+ this.name = 'TxnodEnvironmentUnknownError';
2055
+ }
2056
+ }
2057
+ /**
2058
+ * Thrown synchronously by the `TxnodClient` constructor (and at
2059
+ * `refreshXpubConfig()` time) when one of the configured xpubs has a
2060
+ * testnet-shape prefix (`tpub`/`vpub`/`upub`) AND `getSdkEnv()` returns
2061
+ * `'production'`.
2062
+ *
2063
+ * Carve-outs documented on `assertNoTestnetXpubsInProduction`:
2064
+ * - Cardano (CIP-5 hrp does not distinguish testnet at account-pubkey level —
2065
+ * safety lives at the address-level NetworkId byte; guard is a no-op).
2066
+ * - TON (no xpub concept; guard is a no-op).
2067
+ * - EVM mainnet/testnet `xpub` ambiguity — testnet differentiation lives in
2068
+ * the address checksum, not the xpub itself; only `tpub`/`vpub`/`upub`
2069
+ * prefixes are reliably classified as testnet.
2070
+ *
2071
+ * @example
2072
+ * ```ts
2073
+ * import { TxnodClient, TxnodSandboxXpubInProductionError } from '@txnod/sdk';
2074
+ *
2075
+ * try {
2076
+ * const client = new TxnodClient({
2077
+ * projectId: process.env.TXNOD_PROJECT_ID!,
2078
+ * apiSecret: process.env.TXNOD_API_SECRET!,
2079
+ * });
2080
+ * void client;
2081
+ * } catch (err) {
2082
+ * if (err instanceof TxnodSandboxXpubInProductionError) {
2083
+ * console.error(
2084
+ * 'testnet xpub in production',
2085
+ * err.chain,
2086
+ * err.xpubPrefix,
2087
+ * );
2088
+ * process.exit(1);
2089
+ * }
2090
+ * throw err;
2091
+ * }
2092
+ * ```
2093
+ */
2094
+ export class TxnodSandboxXpubInProductionError extends TxnodError {
2095
+ kind = 'sandbox_xpub_in_production';
2096
+ chain;
2097
+ xpubPrefix;
2098
+ detectedEnvironment;
2099
+ constructor(chain, xpubPrefix) {
2100
+ super(syntheticDetails('auth_invalid', 401, `Testnet-shape xpub prefix '${xpubPrefix}' configured for chain '${chain}' in production environment. Refusing to construct TxnodClient.`));
2101
+ this.name = 'TxnodSandboxXpubInProductionError';
2102
+ this.chain = chain;
2103
+ this.xpubPrefix = xpubPrefix;
2104
+ this.detectedEnvironment = 'production';
2105
+ }
2106
+ }
2107
+ //# sourceMappingURL=errors.js.map