@txnod/sdk 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +33 -0
- package/dist/_shared/index.d.ts +26 -16
- package/dist/client-sandbox.d.ts +181 -6
- package/dist/client-sandbox.d.ts.map +1 -1
- package/dist/client-sandbox.js +216 -5
- package/dist/client-sandbox.js.map +1 -1
- package/dist/client.d.ts +59 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +58 -6
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +187 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +208 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internals/error-ctor-map.d.ts +4 -3
- package/dist/internals/error-ctor-map.d.ts.map +1 -1
- package/dist/internals/error-ctor-map.js +5 -1
- package/dist/internals/error-ctor-map.js.map +1 -1
- package/dist/verify/chains/bsc.d.ts +1 -7
- package/dist/verify/chains/bsc.d.ts.map +1 -1
- package/dist/verify/chains/bsc.js +1 -7
- package/dist/verify/chains/bsc.js.map +1 -1
- package/dist/verify/chains/btc.d.ts +1 -8
- package/dist/verify/chains/btc.d.ts.map +1 -1
- package/dist/verify/chains/btc.js +1 -8
- package/dist/verify/chains/btc.js.map +1 -1
- package/dist/verify/chains/cardano.d.ts +6 -13
- package/dist/verify/chains/cardano.d.ts.map +1 -1
- package/dist/verify/chains/cardano.js +6 -13
- package/dist/verify/chains/cardano.js.map +1 -1
- package/dist/verify/chains/evm.d.ts +1 -6
- package/dist/verify/chains/evm.d.ts.map +1 -1
- package/dist/verify/chains/evm.js +8 -7
- package/dist/verify/chains/evm.js.map +1 -1
- package/dist/verify/chains/polygon.d.ts +1 -7
- package/dist/verify/chains/polygon.d.ts.map +1 -1
- package/dist/verify/chains/polygon.js +1 -7
- package/dist/verify/chains/polygon.js.map +1 -1
- package/dist/verify/chains/secp256k1-bip32.d.ts +2 -8
- package/dist/verify/chains/secp256k1-bip32.d.ts.map +1 -1
- package/dist/verify/chains/secp256k1-bip32.js +5 -13
- package/dist/verify/chains/secp256k1-bip32.js.map +1 -1
- package/dist/verify/chains/ton-cell.d.ts.map +1 -1
- package/dist/verify/chains/ton-cell.js +4 -7
- package/dist/verify/chains/ton-cell.js.map +1 -1
- package/dist/verify/chains/ton.d.ts +3 -7
- package/dist/verify/chains/ton.d.ts.map +1 -1
- package/dist/verify/chains/ton.js +1 -3
- package/dist/verify/chains/ton.js.map +1 -1
- package/dist/verify/chains/tron.d.ts +1 -7
- package/dist/verify/chains/tron.d.ts.map +1 -1
- package/dist/verify/chains/tron.js +1 -7
- package/dist/verify/chains/tron.js.map +1 -1
- package/dist/verify/errors.d.ts +6 -8
- package/dist/verify/errors.d.ts.map +1 -1
- package/dist/verify/errors.js +6 -8
- package/dist/verify/errors.js.map +1 -1
- package/dist/verify/index.d.ts +1 -1
- package/dist/verify/index.js +2 -2
- package/dist/verify/index.js.map +1 -1
- package/docs/02-invoices.md +46 -2
- package/docs/04-webhooks.md +4 -1
- package/docs/05-errors.md +24 -4
- package/docs/05-sandbox.md +13 -5
- package/docs/examples/sandbox-vitest-suite.md +2 -2
- package/docs/reference/client.md +39 -2
- package/docs/reference/errors.md +13 -2
- package/docs/reference/types.md +5 -4
- package/package.json +13 -13
package/docs/reference/client.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "TxnodClient reference"
|
|
3
3
|
description: "Every method of TxnodClient and the verifyWebhookSignature helper: signature, behaviour, and a minimal example."
|
|
4
|
-
sdk_version: 1.0.
|
|
4
|
+
sdk_version: 1.0.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# `TxnodClient` reference
|
|
@@ -242,6 +242,36 @@ attributeOrphanPayment(
|
|
|
242
242
|
|
|
243
243
|
---
|
|
244
244
|
|
|
245
|
+
## `claimInvoiceByTx`
|
|
246
|
+
|
|
247
|
+
Submit a manual tx-hash claim for an open invoice — the "I paid but it's not showing up" recovery path. The server resolves the tx via the chain provider, verifies sender / recipient / amount / timestamp, and either auto-attributes, queues for operator review, defers pending finality, or rejects.
|
|
248
|
+
|
|
249
|
+
**Signature**
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
claimInvoiceByTx(args: {
|
|
253
|
+
invoiceId: string;
|
|
254
|
+
txHash: string;
|
|
255
|
+
chain: Chain;
|
|
256
|
+
}): Promise<ClaimByTxResponse>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Response (`ClaimByTxResponse`)**
|
|
260
|
+
|
|
261
|
+
| Field | Type | Notes |
|
|
262
|
+
|---|---|---|
|
|
263
|
+
| `request_id` | ULID | Request correlation id |
|
|
264
|
+
| `status` | `'auto_attributed' \| 'pending_review' \| 'pending_finality' \| 'rejected'` | Outcome discriminator |
|
|
265
|
+
| `terminal_status` | `'paid' \| 'overpaid' \| 'partial' \| 'expired_paid_late' \| null` | Present when `status === 'auto_attributed'` |
|
|
266
|
+
| `resolved_facts` | `ResolvedFacts \| null` | Sender / recipient / amount / confirmations / timestamp as resolved from the chain provider |
|
|
267
|
+
| `rejection_reason` | `'tx_not_found_or_incomplete' \| 'tx_already_attributed' \| null` | Present when `status === 'rejected'` |
|
|
268
|
+
|
|
269
|
+
**Throws**: generic `TxnodError` with `error_code: 'manual_claim_rate_limit_exceeded'` (HTTP 429, per-user 10/hour throttle). The `tx_not_found_or_incomplete` and `tx_already_attributed` rejection paths are returned in the response body, not thrown.
|
|
270
|
+
|
|
271
|
+
See [`../02-invoices.md#manual-tx-hash-claim`](../02-invoices.md#manual-tx-hash-claim) for the full lifecycle and a worked example.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
245
275
|
## `listWebhookEvents`
|
|
246
276
|
|
|
247
277
|
Paginated audit list of outbound webhook events for the calling project.
|
|
@@ -291,7 +321,7 @@ resendWebhookEvent(eventId: string): Promise<WebhookEventResendResponse>
|
|
|
291
321
|
|
|
292
322
|
## Sandbox surface (`client.sandbox.*`)
|
|
293
323
|
|
|
294
|
-
Lazy accessor (`client.sandbox` is constructed on first use; bundlers tree-shake the entire namespace when never referenced) onto the
|
|
324
|
+
Lazy accessor (`client.sandbox` is constructed on first use; bundlers tree-shake the entire namespace when never referenced) onto the sandbox-mode endpoints. Use it from a sandbox-API-secret-authenticated client (`apiSecret: 'sk_sandbox_...'` + `environment: 'non-production'`) — production secrets cannot reach these routes (the server returns `production_key_against_sandbox_project`). See [`../05-sandbox.md`](../05-sandbox.md) for the lifecycle picture and per-method worked examples.
|
|
295
325
|
|
|
296
326
|
```ts
|
|
297
327
|
const client = new TxnodClient({
|
|
@@ -308,6 +338,12 @@ const r = await client.sandbox.simulatePaid('01HK8MAR2QEXAMPLE000000000');
|
|
|
308
338
|
|
|
309
339
|
| Method | HTTP | Returns | Throws |
|
|
310
340
|
|---|---|---|---|
|
|
341
|
+
| `createInvoice(body)` | `POST /api/v1/sandbox/invoices` | `InvoiceResponse` | `TxnodSandboxActiveInvoiceCapReachedError` (10k active cap), `TxnodCoinNotEnabledError`, `TxnodRateQuoteUnavailableError` |
|
|
342
|
+
| `getInvoice(invoiceId)` | `GET /api/v1/sandbox/invoices/{invoiceId}` | `InvoiceDetailResponse` | `TxnodInvoiceNotFoundError` |
|
|
343
|
+
| `listInvoices(query?)` | `GET /api/v1/sandbox/invoices` | `CursorPaginatedInvoiceResponse` | `TxnodValidationError` |
|
|
344
|
+
| `cancelInvoice(invoiceId)` | `POST /api/v1/sandbox/invoices/{invoiceId}/cancel` | `InvoiceDetailResponse` | `TxnodInvoiceNotFoundError`, `TxnodInvoiceNotCancellableError` |
|
|
345
|
+
| `listWebhookEvents(query?)` | `GET /api/v1/sandbox/webhooks/events` | `WebhookEventListResponse` | `TxnodValidationError` |
|
|
346
|
+
| `resendWebhookEvent(eventId)` | `POST /api/v1/sandbox/webhooks/events/{eventId}/resend` | `WebhookEventResendResponse` | `TxnodEventNotFoundError`, `TxnodEventNotResendableError` (in-flight or dead-lettered) |
|
|
311
347
|
| `simulateDetect(invoiceId, opts?)` | `POST /api/v1/sandbox/invoices/{invoiceId}/simulate-detect` | `{ event_id, status: 'detected' }` | `TxnodSandboxInvoiceTransitionInvalidError` (invoice not in `pending`), `TxnodSandboxInvoiceNotFoundError` |
|
|
312
348
|
| `simulatePaid(invoiceId, opts?)` | `POST .../simulate-paid` | `{ event_id, status: 'paid' }` | `TxnodSandboxInvoiceTransitionInvalidError` (invoice not in `detected`) |
|
|
313
349
|
| `simulateOverpaid(invoiceId, params)` | `POST .../simulate-overpaid` | `{ event_id, status: 'paid' }` | `TxnodSandboxInvoiceTransitionInvalidError` |
|
|
@@ -318,6 +354,7 @@ const r = await client.sandbox.simulatePaid('01HK8MAR2QEXAMPLE000000000');
|
|
|
318
354
|
| `simulateReconfirm(invoiceId)` | `POST .../simulate-reconfirm` | `{ event_id, status: 'paid' }` | `TxnodSandboxInvoiceTransitionInvalidError` (invoice not in `reverted`) |
|
|
319
355
|
| `simulateDuplicateDelivery(invoiceId)` | `POST .../simulate-duplicate-delivery` | `{ event_id }` | `TxnodSandboxInvoiceTerminalError` (no terminal event yet) |
|
|
320
356
|
| `simulateEvent(invoiceId, eventInput)` | `POST .../simulate-event` | `{ event_id, status }` | `TxnodSandboxInvoiceTransitionInvalidError` (current status != `expectedCurrentStatus`) |
|
|
357
|
+
| `simulateClaimByTx(invoiceId, args)` | `POST .../claim-by-tx` | `ClaimByTxResponse` | Generic `TxnodError` with `error_code: 'manual_claim_rate_limit_exceeded'` (per-user 10/hour throttle); rejection paths return in the response body, not thrown |
|
|
321
358
|
| `clockAdvance(projectId, params)` | `POST /api/v1/sandbox/{projectId}/clock/advance` | `{ advanced, remaining }` | `TxnodSandboxRateLimitExceededError` (>10/min/project) |
|
|
322
359
|
| `reset(projectId)` | `POST /api/v1/sandbox/{projectId}/reset` | `{ status: 'reset' }` | `TxnodSandboxResetFailedError` |
|
|
323
360
|
| `destroy(projectId)` | `DELETE /api/v1/sandbox/{projectId}` | `{ status: 'deleted' }` | `TxnodSandboxDeleteFailedError` |
|
package/docs/reference/errors.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Error class catalogue"
|
|
3
3
|
description: "Complete error_code → class lookup and the narrative groups."
|
|
4
|
-
sdk_version: 1.0.
|
|
4
|
+
sdk_version: 1.0.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Error class catalogue
|
|
@@ -56,6 +56,7 @@ The 55-row lookup below covers every server-emitted code in `ERROR_CODES` (58 en
|
|
|
56
56
|
|---|---|---|---|
|
|
57
57
|
| `external_id_conflict` | `TxnodExternalIdConflictError` | 409 | **Idempotent** — fetch existing |
|
|
58
58
|
| `orphan_already_attributed` | `TxnodOrphanAlreadyAttributedError` | 409 | **Idempotent** — treat as success |
|
|
59
|
+
| `overlay_matching_mode_required_exact` | `TxnodOverlayMatchingModeError` | 422 | Pool saturation forced the allocator into `required_exact`; project's `matching_mode` must be flipped or the pool must drain |
|
|
59
60
|
| `wallet_not_bound` | `TxnodWalletNotBoundError` | 422 | Operator must bind a verified wallet of matching kind for the requested chain before invoice creation succeeds |
|
|
60
61
|
| `wallet_not_owned` | `TxnodWalletNotOwnedError` | 403 | **Dashboard-only** — never reaches partner API |
|
|
61
62
|
| `wallet_has_active_bindings` | `TxnodWalletHasActiveBindingsError` | 409 | **Dashboard-only** — never reaches partner API |
|
|
@@ -71,6 +72,15 @@ The 55-row lookup below covers every server-emitted code in `ERROR_CODES` (58 en
|
|
|
71
72
|
| `ton_jetton_resolve_failed` | `TxnodTonJettonResolveFailedError` | 503 | Toncenter/TONAPI hiccup resolving the jetton master/wallet pair — retry with backoff |
|
|
72
73
|
| `ton_comment_parse_failed` | `TxnodTonCommentParseFailedError` | 422 | Inbound TON tx carried a malformed `payment_token` comment |
|
|
73
74
|
|
|
75
|
+
### Manual tx-hash claim flow
|
|
76
|
+
|
|
77
|
+
Returned in the **response body** as `{ status: 'rejected', rejection_reason }` on HTTP 200 — these two codes are not raised by `parseProblemDetails`. The classes below exist as helpers for partners who prefer to throw on the rejection paths themselves.
|
|
78
|
+
|
|
79
|
+
| `error_code` | Class | HTTP status | Notes |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `tx_not_found_or_incomplete` | `TxnodTxNotFoundError` | 200 (body) | Chain provider could not resolve the tx, or facts (recipient / amount / state) do not match the invoice |
|
|
82
|
+
| `tx_already_attributed` | `TxnodTxAlreadyAttributedError` | 200 (body) | The submitted tx was previously credited to an invoice |
|
|
83
|
+
|
|
74
84
|
### TonConnect (operator-onboarding)
|
|
75
85
|
|
|
76
86
|
These never reach partner methods — they fire on the operator's TonConnect signing flow during xpub onboarding. Exported so the dashboard's typed-error catch can branch correctly.
|
|
@@ -87,7 +97,7 @@ These never reach partner methods — they fire on the operator's TonConnect sig
|
|
|
87
97
|
|
|
88
98
|
### Sandbox (lifecycle + simulation)
|
|
89
99
|
|
|
90
|
-
Surfaced by `/api/v1/sandbox/*` REST endpoints, the
|
|
100
|
+
Surfaced by `/api/v1/sandbox/*` REST endpoints, the `client.sandbox.*` SDK methods, and the `sandbox:simulate`-scoped MCP tools.
|
|
91
101
|
|
|
92
102
|
| `error_code` | Class | HTTP status | Notes |
|
|
93
103
|
|---|---|---|---|
|
|
@@ -109,6 +119,7 @@ Surfaced by `/api/v1/sandbox/*` REST endpoints, the 14 `client.sandbox.*` SDK me
|
|
|
109
119
|
| `error_code` | Class | HTTP status | Notes |
|
|
110
120
|
|---|---|---|---|
|
|
111
121
|
| `rate_limit_exceeded` | `TxnodRateLimitError` | 429 | `.retry_after_seconds` |
|
|
122
|
+
| `manual_claim_rate_limit_exceeded` | `TxnodError` (generic) | 429 | Per-user hourly throttle on `client.claimInvoiceByTx` (10/hour/user); falls through to base `TxnodError` — branch on `err.error_code` |
|
|
112
123
|
| `pool_exhausted` | `TxnodPoolExhaustedError` | 503 | `.retry_after_seconds` — hard-cap hit, wait for cooldown |
|
|
113
124
|
| `webhook_capacity_exhausted` | `TxnodWebhookCapacityExhaustedError` | 503 | `.retry_after_seconds` always `0` — partner retry alone won't free capacity, treat as transient outage |
|
|
114
125
|
| `internal_error` | `TxnodServerError` | 5xx | Log `request_id`, retryable |
|
package/docs/reference/types.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Type reference"
|
|
3
3
|
description: "Authoritative type shapes for requests, responses, and shared primitives."
|
|
4
|
-
sdk_version: 1.0.
|
|
4
|
+
sdk_version: 1.0.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Type reference
|
|
@@ -200,7 +200,8 @@ type WebhookEventType =
|
|
|
200
200
|
| 'invoice.partial'
|
|
201
201
|
| 'invoice.expired'
|
|
202
202
|
| 'invoice.expired_paid_late'
|
|
203
|
-
| 'invoice.reverted'
|
|
203
|
+
| 'invoice.reverted'
|
|
204
|
+
| 'invoice.ambiguous';
|
|
204
205
|
|
|
205
206
|
type WebhookEventData = {
|
|
206
207
|
invoice_id: string;
|
|
@@ -212,7 +213,7 @@ type WebhookEventData = {
|
|
|
212
213
|
amount_units: string; // integer string in smallest unit
|
|
213
214
|
confirmations: number;
|
|
214
215
|
block_height: number | null;
|
|
215
|
-
payment_token: string | null; // TON only —
|
|
216
|
+
payment_token: string | null; // TON only — lowercase hex memo token (8 or 16 chars)
|
|
216
217
|
matched_payment_token: string | null;
|
|
217
218
|
chain_specific: { ton?: { tx_lt: string; mc_block_seqno: number; block_ref: { workchain: number; shard: string; seqno: number; }; jetton_master?: string; } } | null;
|
|
218
219
|
reason?: 'reorg' | 'late_arrival'; // present on reverted/expired_paid_late
|
|
@@ -372,7 +373,7 @@ type CursorPaginatedOrphanPaymentResponse = {
|
|
|
372
373
|
};
|
|
373
374
|
```
|
|
374
375
|
|
|
375
|
-
> **TRON activation events never appear here.**
|
|
376
|
+
> **TRON activation events never appear here.** A server-side filter excludes inbound activation transactions (operator-funded TRX/USDT sends that activate a fresh address) from orphan classification — partners do not need to dedupe them client-side.
|
|
376
377
|
|
|
377
378
|
## `ProblemDetails`
|
|
378
379
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@txnod/sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "TypeScript SDK for the txnod non-custodial crypto payment gateway — sign requests, verify webhook signatures, and verify invoice deposit-address derivation across BTC, ETH, TRON, Cardano, Polygon PoS, BNB Smart Chain, and TON. Pure Node >= 20; runs in any server-side framework (Express, Fastify, Hono, Next.js, Nuxt, SvelteKit, etc.).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -20,6 +20,17 @@
|
|
|
20
20
|
"CHANGELOG.md",
|
|
21
21
|
"LICENSE"
|
|
22
22
|
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "pnpm --filter @txnod/shared build && tsc --build && node scripts/bundle-shared-types.mjs",
|
|
25
|
+
"typecheck": "tsc --build",
|
|
26
|
+
"lint": "eslint src",
|
|
27
|
+
"test": "vitest run --config vitest.unit.config.ts",
|
|
28
|
+
"test:contract": "pnpm run build && vitest run --config vitest.contract.config.ts",
|
|
29
|
+
"check:bundle-size": "bash ../../scripts/ci/sdk-bundle-size.sh",
|
|
30
|
+
"check:dep-allowlist": "bash ../../scripts/ci/sdk-dep-allowlist.sh",
|
|
31
|
+
"check:pack-whitelist": "bash ../../scripts/ci/sdk-pack-whitelist.sh",
|
|
32
|
+
"check:dts-self-contained": "bash ../../scripts/ci/sdk-dts-self-contained.sh"
|
|
33
|
+
},
|
|
23
34
|
"publishConfig": {
|
|
24
35
|
"access": "public"
|
|
25
36
|
},
|
|
@@ -38,16 +49,5 @@
|
|
|
38
49
|
"devDependencies": {
|
|
39
50
|
"@testcontainers/postgresql": "11.14.0",
|
|
40
51
|
"@ton/ton": "16.2.4"
|
|
41
|
-
},
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "pnpm --filter @txnod/shared build && tsc --build && node scripts/bundle-shared-types.mjs",
|
|
44
|
-
"typecheck": "tsc --build",
|
|
45
|
-
"lint": "eslint src",
|
|
46
|
-
"test": "vitest run --config vitest.unit.config.ts",
|
|
47
|
-
"test:contract": "pnpm run build && vitest run --config vitest.contract.config.ts",
|
|
48
|
-
"check:bundle-size": "bash ../../scripts/ci/sdk-bundle-size.sh",
|
|
49
|
-
"check:dep-allowlist": "bash ../../scripts/ci/sdk-dep-allowlist.sh",
|
|
50
|
-
"check:pack-whitelist": "bash ../../scripts/ci/sdk-pack-whitelist.sh",
|
|
51
|
-
"check:dts-self-contained": "bash ../../scripts/ci/sdk-dts-self-contained.sh"
|
|
52
52
|
}
|
|
53
|
-
}
|
|
53
|
+
}
|