@atumlabs/payment-gateway-client 1.0.2 → 2.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.
@@ -0,0 +1,62 @@
1
+ # Payment idempotency
2
+
3
+ Submit the same payment twice — a retry, a timeout, a network blip — and you
4
+ should end up with **one** payment, not two, and receive the **same** answer both
5
+ times. The key to both properties is the `request_id` you send with each payment.
6
+
7
+ ## Using the SDK
8
+
9
+ With `@atumlabs/payment-gateway-client` this is automatic. Pass a stable
10
+ `request_id` and reuse it on retry. `request_id` is required on the payment path
11
+ (`preparePaymentRequest`); the SDK derives the on-chain deposit nonce
12
+ deterministically from it, so both guarantees below line up on their own. You
13
+ never manage nonces — `request_id` is the only value you control.
14
+
15
+ Reuse the same `request_id` across attempts of the same logical payment. Use a
16
+ fresh `request_id` only for a genuinely new payment.
17
+
18
+ ## The two guarantees
19
+
20
+ ### 1. Gateway dedup — enforced for every caller
21
+
22
+ The gateway records your `request_id` (scoped to your source account and signing
23
+ identity). If the same `request_id` arrives again, the gateway returns the
24
+ original payment — same `payment_id`, same status and receipt — and never creates
25
+ a second payment or broadcasts a second deposit. This holds whether you use the
26
+ SDK or call the API directly, as long as you send a stable `request_id` and reuse
27
+ it on retry.
28
+
29
+ ### 2. On-chain single-settlement — enforced by the blockchain
30
+
31
+ Each deposit authorization carries a nonce, and the chain guarantees a given
32
+ nonce can settle at most once. This ties your retries together on-chain **only
33
+ if** each retry carries the **same** nonce. The SDK derives that nonce from your
34
+ `request_id`, so retries reuse it automatically. A direct caller sets the nonce
35
+ themselves in the signed permit.
36
+
37
+ The caveat runs in both directions. A changing `request_id` defeats both
38
+ guarantees, because each attempt is then treated as a different payment — keep it
39
+ stable and reuse it on retry. Equally, reusing a `request_id` with different terms
40
+ (a corrected amount, a different token) returns the **original** payment rather
41
+ than an error, so the new terms are silently dropped. A genuinely new payment
42
+ always needs a new id.
43
+
44
+ ## Chain-specific behavior
45
+
46
+ The SDK gives you the same guarantee on every chain; the on-chain half works
47
+ slightly differently underneath:
48
+
49
+ - **EVM / Tron:** the on-chain nonce is spent permanently, so guarantee 2 lasts
50
+ indefinitely.
51
+ - **Solana:** the on-chain guard covers only a short, bounded window (roughly two
52
+ minutes). Beyond that window the durable protection is guarantee 1 (the
53
+ gateway's `request_id` record). The SDK keeps a rebuild inside the window by
54
+ pinning `issued_at` through its Solana clock reader, so you do not have to.
55
+
56
+ Either way, a stable `request_id` keeps you safe on every chain.
57
+
58
+ ## A note on addresses
59
+
60
+ EVM `0x` addresses are case-insensitive, so casing never affects your payment.
61
+ Solana and Tron base58 addresses **are** case-sensitive — pass them exactly as
62
+ issued.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atumlabs/payment-gateway-client",
3
- "version": "1.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "TypeScript client for Atum Payment Gateway API",
5
5
  "author": "Atum Labs, Inc.",
6
6
  "homepage": "https://github.com/Atum-Labs/protocol/tree/main/payment-gateway-client#readme",
@@ -40,12 +40,13 @@
40
40
  "scripts": {
41
41
  "generate": "openapi-ts --input ../schemas/apis/payment-gateway/v1/openapi.yaml --output ./src/generated --client axios --name PaymentGatewayClient --useOptions",
42
42
  "prebuild:deps": "node -e \"if(!require('fs').existsSync('../key-management/common/typescript/tsconfig.json')){console.error('protocol key-management packages not found at ../key-management. Is this checked out inside the protocol monorepo?');process.exit(1)}\"",
43
- "build:deps": "tsc -p ../key-management/common/typescript/tsconfig.json && tsc -p ../key-management/providers/turnkey/typescript/tsconfig.json && tsc -p ../contracts/svm/escrow-encoding/typescript/tsconfig.json && tsc -p ../contracts/evm/escrow-encoding/typescript/tsconfig.json && tsc -p ../contracts/tvm/escrow-encoding/typescript/tsconfig.json",
44
- "build": "pnpm run build:deps && tsup && chmod +x dist/cli/*.js",
43
+ "build:deps": "tsc -p ../key-management/common/typescript/tsconfig.json && tsc -p ../key-management/providers/turnkey/typescript/tsconfig.json && tsc -p ../contracts/svm/escrow-encoding/typescript/tsconfig.json && tsc -p ../contracts/evm/escrow-encoding/typescript/tsconfig.json && tsc -p ../contracts/tvm/escrow-encoding/typescript/tsconfig.json && tsc -p ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/tsconfig.json",
44
+ "build": "pnpm run build:deps && tsup && chmod +x dist/cli/*.js && node scripts/stamp-entry-headers.mjs",
45
45
  "pretest": "pnpm run build:deps",
46
46
  "test": "jest",
47
- "clean": "rm -rf dist ../key-management/common/typescript/dist ../key-management/providers/turnkey/typescript/dist ../contracts/svm/escrow-encoding/typescript/dist ../contracts/evm/escrow-encoding/typescript/dist ../contracts/tvm/escrow-encoding/typescript/dist",
47
+ "clean": "rm -rf dist ../key-management/common/typescript/dist ../key-management/providers/turnkey/typescript/dist ../contracts/svm/escrow-encoding/typescript/dist ../contracts/evm/escrow-encoding/typescript/dist ../contracts/tvm/escrow-encoding/typescript/dist ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist",
48
48
  "check:publishable": "node scripts/check-publishable.mjs",
49
+ "gen:notices": "node scripts/gen-third-party-notices.mjs",
49
50
  "prepare": "pnpm run build",
50
51
  "prepublishOnly": "pnpm run build && pnpm run check:publishable"
51
52
  },
@@ -54,6 +55,7 @@
54
55
  "axios": "1.13.2",
55
56
  "bs58": "^6.0.0",
56
57
  "commander": "^12.0.0",
58
+ "dotenv": "^16.6.1",
57
59
  "ethers": "^6.11.0",
58
60
  "tweetnacl": "^1.0.3",
59
61
  "zod": "^3.25.0"
@@ -61,6 +63,8 @@
61
63
  "devDependencies": {
62
64
  "@atum-labs/evm-escrow-encoding": "workspace:*",
63
65
  "@atum-labs/km-core": "workspace:*",
66
+ "@atum-labs/payment-request-sender-auth": "workspace:*",
67
+ "@atum-labs/publish-guard": "workspace:*",
64
68
  "@atum-labs/solana-escrow-encoding": "workspace:*",
65
69
  "@atum-labs/turnkey-signer": "workspace:*",
66
70
  "@atum-labs/tvm-escrow-encoding": "workspace:*",
@@ -75,7 +79,14 @@
75
79
  },
76
80
  "files": [
77
81
  "dist/**/*",
78
- "CHANGELOG.md"
82
+ "README.md",
83
+ "CHANGELOG.md",
84
+ "docs/**",
85
+ "LICENSE",
86
+ "THIRD-PARTY-NOTICES.txt"
79
87
  ],
80
- "license": "MIT"
88
+ "license": "SEE LICENSE IN LICENSE",
89
+ "publishConfig": {
90
+ "access": "restricted"
91
+ }
81
92
  }
File without changes