@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.
- package/AGENTS.md +29 -0
- package/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +434 -0
- package/dist/_shared/index.d.ts +68 -0
- package/dist/client-sandbox.d.ts +396 -0
- package/dist/client-sandbox.d.ts.map +1 -0
- package/dist/client-sandbox.js +448 -0
- package/dist/client-sandbox.js.map +1 -0
- package/dist/client.d.ts +429 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +588 -0
- package/dist/client.js.map +1 -0
- package/dist/env.d.ts +29 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +44 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +1887 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2107 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/internals/error-ctor-map.d.ts +11 -0
- package/dist/internals/error-ctor-map.d.ts.map +1 -0
- package/dist/internals/error-ctor-map.js +75 -0
- package/dist/internals/error-ctor-map.js.map +1 -0
- package/dist/internals/fetch-with-retry.d.ts +34 -0
- package/dist/internals/fetch-with-retry.d.ts.map +1 -0
- package/dist/internals/fetch-with-retry.js +233 -0
- package/dist/internals/fetch-with-retry.js.map +1 -0
- package/dist/internals/hmac.d.ts +2 -0
- package/dist/internals/hmac.d.ts.map +1 -0
- package/dist/internals/hmac.js +10 -0
- package/dist/internals/hmac.js.map +1 -0
- package/dist/internals/logger.d.ts +9 -0
- package/dist/internals/logger.d.ts.map +1 -0
- package/dist/internals/logger.js +16 -0
- package/dist/internals/logger.js.map +1 -0
- package/dist/internals/parse-problem-details.d.ts +3 -0
- package/dist/internals/parse-problem-details.d.ts.map +1 -0
- package/dist/internals/parse-problem-details.js +76 -0
- package/dist/internals/parse-problem-details.js.map +1 -0
- package/dist/internals/synthetic-details.d.ts +12 -0
- package/dist/internals/synthetic-details.d.ts.map +1 -0
- package/dist/internals/synthetic-details.js +19 -0
- package/dist/internals/synthetic-details.js.map +1 -0
- package/dist/verify/chains/bsc.d.ts +17 -0
- package/dist/verify/chains/bsc.d.ts.map +1 -0
- package/dist/verify/chains/bsc.js +15 -0
- package/dist/verify/chains/bsc.js.map +1 -0
- package/dist/verify/chains/btc.d.ts +22 -0
- package/dist/verify/chains/btc.d.ts.map +1 -0
- package/dist/verify/chains/btc.js +55 -0
- package/dist/verify/chains/btc.js.map +1 -0
- package/dist/verify/chains/cardano.d.ts +73 -0
- package/dist/verify/chains/cardano.d.ts.map +1 -0
- package/dist/verify/chains/cardano.js +175 -0
- package/dist/verify/chains/cardano.js.map +1 -0
- package/dist/verify/chains/evm.d.ts +21 -0
- package/dist/verify/chains/evm.d.ts.map +1 -0
- package/dist/verify/chains/evm.js +46 -0
- package/dist/verify/chains/evm.js.map +1 -0
- package/dist/verify/chains/polygon.d.ts +17 -0
- package/dist/verify/chains/polygon.d.ts.map +1 -0
- package/dist/verify/chains/polygon.js +15 -0
- package/dist/verify/chains/polygon.js.map +1 -0
- package/dist/verify/chains/secp256k1-bip32.d.ts +20 -0
- package/dist/verify/chains/secp256k1-bip32.d.ts.map +1 -0
- package/dist/verify/chains/secp256k1-bip32.js +88 -0
- package/dist/verify/chains/secp256k1-bip32.js.map +1 -0
- package/dist/verify/chains/ton-cell.d.ts +179 -0
- package/dist/verify/chains/ton-cell.d.ts.map +1 -0
- package/dist/verify/chains/ton-cell.js +614 -0
- package/dist/verify/chains/ton-cell.js.map +1 -0
- package/dist/verify/chains/ton.d.ts +84 -0
- package/dist/verify/chains/ton.d.ts.map +1 -0
- package/dist/verify/chains/ton.js +131 -0
- package/dist/verify/chains/ton.js.map +1 -0
- package/dist/verify/chains/tron.d.ts +21 -0
- package/dist/verify/chains/tron.d.ts.map +1 -0
- package/dist/verify/chains/tron.js +42 -0
- package/dist/verify/chains/tron.js.map +1 -0
- package/dist/verify/config.d.ts +41 -0
- package/dist/verify/config.d.ts.map +1 -0
- package/dist/verify/config.js +120 -0
- package/dist/verify/config.js.map +1 -0
- package/dist/verify/errors.d.ts +56 -0
- package/dist/verify/errors.d.ts.map +1 -0
- package/dist/verify/errors.js +58 -0
- package/dist/verify/errors.js.map +1 -0
- package/dist/verify/index.d.ts +119 -0
- package/dist/verify/index.d.ts.map +1 -0
- package/dist/verify/index.js +166 -0
- package/dist/verify/index.js.map +1 -0
- package/dist/verify/xpub-safety.d.ts +33 -0
- package/dist/verify/xpub-safety.d.ts.map +1 -0
- package/dist/verify/xpub-safety.js +54 -0
- package/dist/verify/xpub-safety.js.map +1 -0
- package/dist/verify-webhook-signature.d.ts +30 -0
- package/dist/verify-webhook-signature.d.ts.map +1 -0
- package/dist/verify-webhook-signature.js +84 -0
- package/dist/verify-webhook-signature.js.map +1 -0
- package/docs/00-getting-started.md +135 -0
- package/docs/01-authentication.md +114 -0
- package/docs/02-invoices.md +216 -0
- package/docs/03-rates-and-quotes.md +82 -0
- package/docs/04-webhooks.md +126 -0
- package/docs/05-errors.md +199 -0
- package/docs/05-sandbox.md +159 -0
- package/docs/06-idempotency.md +132 -0
- package/docs/examples/express-webhook-receiver.md +97 -0
- package/docs/examples/nextjs-route-handler.md +206 -0
- package/docs/examples/sandbox-vitest-suite.md +263 -0
- package/docs/index.md +66 -0
- package/docs/reference/client.md +392 -0
- package/docs/reference/errors.md +161 -0
- package/docs/reference/types.md +400 -0
- 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
|