@aibtc/tx-schemas 0.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/core/enums.d.ts +161 -0
  4. package/dist/core/enums.d.ts.map +1 -0
  5. package/dist/core/enums.js +98 -0
  6. package/dist/core/enums.js.map +1 -0
  7. package/dist/core/index.d.ts +6 -0
  8. package/dist/core/index.d.ts.map +1 -0
  9. package/dist/core/index.js +6 -0
  10. package/dist/core/index.js.map +1 -0
  11. package/dist/core/payment.d.ts +267 -0
  12. package/dist/core/payment.d.ts.map +1 -0
  13. package/dist/core/payment.js +85 -0
  14. package/dist/core/payment.js.map +1 -0
  15. package/dist/core/primitives.d.ts +11 -0
  16. package/dist/core/primitives.d.ts.map +1 -0
  17. package/dist/core/primitives.js +29 -0
  18. package/dist/core/primitives.js.map +1 -0
  19. package/dist/core/schemas.d.ts +2 -0
  20. package/dist/core/schemas.d.ts.map +1 -0
  21. package/dist/core/schemas.js +2 -0
  22. package/dist/core/schemas.js.map +1 -0
  23. package/dist/core/terminal-reasons.d.ts +154 -0
  24. package/dist/core/terminal-reasons.d.ts.map +1 -0
  25. package/dist/core/terminal-reasons.js +82 -0
  26. package/dist/core/terminal-reasons.js.map +1 -0
  27. package/dist/http/index.d.ts +2 -0
  28. package/dist/http/index.d.ts.map +1 -0
  29. package/dist/http/index.js +2 -0
  30. package/dist/http/index.js.map +1 -0
  31. package/dist/http/schemas.d.ts +424 -0
  32. package/dist/http/schemas.d.ts.map +1 -0
  33. package/dist/http/schemas.js +171 -0
  34. package/dist/http/schemas.js.map +1 -0
  35. package/dist/index.d.ts +4 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +4 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/rpc/index.d.ts +2 -0
  40. package/dist/rpc/index.d.ts.map +1 -0
  41. package/dist/rpc/index.js +2 -0
  42. package/dist/rpc/index.js.map +1 -0
  43. package/dist/rpc/schemas.d.ts +339 -0
  44. package/dist/rpc/schemas.d.ts.map +1 -0
  45. package/dist/rpc/schemas.js +91 -0
  46. package/dist/rpc/schemas.js.map +1 -0
  47. package/docs/package-schemas.md +52 -0
  48. package/docs/x402-approval-spec.md +530 -0
  49. package/docs/x402-state-machines.md +241 -0
  50. package/package.json +101 -0
@@ -0,0 +1,241 @@
1
+ # x402 and Sponsored Transaction State Machines
2
+
3
+ Related review document:
4
+
5
+ - `x402-approval-spec.md` defines the target approval bar, transport boundaries, and reduction-first architecture expectations for this flow.
6
+
7
+ These diagrams reflect the implemented flow across:
8
+
9
+ - `aibtcdev/skills`
10
+ - `aibtcdev/aibtc-mcp-server`
11
+ - `aibtcdev/landing-page` (`aibtc.com`)
12
+ - `aibtcdev/agent-news` (`aibtc.news`)
13
+ - `aibtcdev/x402-sponsor-relay`
14
+ - Hiro API
15
+
16
+ ## 1. Client State Machine: `skills` and `aibtc-mcp-server`
17
+
18
+ This is the client-side control flow used when an x402-protected endpoint returns `402 Payment Required`.
19
+
20
+ ```mermaid
21
+ stateDiagram-v2
22
+ [*] --> Requesting
23
+
24
+ Requesting --> CompletedFree: 2xx free response
25
+ Requesting --> PaymentRequired: HTTP 402 + payment-required
26
+ Requesting --> Failed: non-402/non-retryable error
27
+
28
+ PaymentRequired --> ValidateOffer
29
+ ValidateOffer --> Failed: invalid header or no Stacks option
30
+ ValidateOffer --> EnsureWallet
31
+
32
+ EnsureWallet --> Failed: wallet/network/balance problem
33
+ EnsureWallet --> BuildSponsoredTx
34
+
35
+ BuildSponsoredTx --> SignPaymentPayload
36
+ SignPaymentPayload --> SubmitPaidRequest
37
+
38
+ SubmitPaidRequest --> CompletedPaid: 200/201 + payment-response txid
39
+ SubmitPaidRequest --> CompletedPending: 200/201 + paymentStatus=pending + paymentId
40
+ SubmitPaidRequest --> RetrySameTx: 409 NONCE_CONFLICT or relay-side duplicate
41
+ SubmitPaidRequest --> RebuildTx: 409 SENDER_NONCE_STALE or SENDER_NONCE_GAP
42
+ SubmitPaidRequest --> BackoffRetry: 502/503 or retryable relay error
43
+ SubmitPaidRequest --> RecoveryCheck: retries exhausted with seen relay txids
44
+ SubmitPaidRequest --> Failed: non-retryable failure
45
+
46
+ RetrySameTx --> SubmitPaidRequest: reuse cached txHex + paymentId for relay dedup
47
+ RebuildTx --> BuildSponsoredTx: fetch fresh nonce and re-sign
48
+ BackoffRetry --> SubmitPaidRequest
49
+
50
+ RecoveryCheck --> AutoRecover: Hiro shows seen txid confirmed
51
+ RecoveryCheck --> Failed: no confirmed txid found
52
+ AutoRecover --> CompletedPaid: resubmit using paymentTxid proof
53
+
54
+ CompletedFree --> [*]
55
+ CompletedPaid --> [*]
56
+ CompletedPending --> [*]
57
+ Failed --> [*]
58
+ ```
59
+
60
+ Notes:
61
+
62
+ - `aibtc-mcp-server/src/services/x402.service.ts` does the generic `402 -> sign -> retry once` flow.
63
+ - `skills/src/lib/utils/x402-retry.ts` and `aibtc-mcp-server/src/tools/inbox.tools.ts` add inbox-specific nonce recovery, same-tx dedup retries, and txid auto-recovery.
64
+
65
+ ## 2. Service State Machine: `aibtc.com` and `aibtc.news`
66
+
67
+ This is how the service workers behave after receiving a paid request.
68
+
69
+ ```mermaid
70
+ stateDiagram-v2
71
+ [*] --> UnpaidRequest
72
+
73
+ UnpaidRequest --> Return402: no payment-signature/payment proof
74
+ Return402 --> [*]
75
+
76
+ UnpaidRequest --> VerifyPayment: payment-signature or paymentTxid present
77
+
78
+ VerifyPayment --> RpcSubmit: X402_RELAY service binding available
79
+ VerifyPayment --> HttpSettle: fallback HTTP /settle path
80
+
81
+ RpcSubmit --> RelayRejected: submitPayment accepted=false
82
+ RpcSubmit --> PollPaymentId: submitPayment accepted=true + paymentId
83
+
84
+ PollPaymentId --> DeliverConfirmed: checkPayment=confirmed
85
+ PollPaymentId --> DeliverConfirmed: checkPayment=mempool
86
+ PollPaymentId --> DeliverPending: poll exhausted with queued/submitted/broadcasting/mempool
87
+ PollPaymentId --> RelayRejected: checkPayment=failed
88
+ PollPaymentId --> RelayRejected: checkPayment=replaced
89
+ PollPaymentId --> RelayRejected: checkPayment=not_found
90
+ PollPaymentId --> RelayUnavailable: RPC error / circuit breaker
91
+
92
+ HttpSettle --> DeliverConfirmed: relay returns confirmed
93
+ HttpSettle --> DeliverPending: relay returns pending
94
+ HttpSettle --> RelayRejected: 4xx settle rejection
95
+ HttpSettle --> RelayUnavailable: 5xx / timeout
96
+
97
+ DeliverConfirmed --> StoreResource
98
+ DeliverPending --> StoreResource
99
+
100
+ StoreResource --> SuccessResponse
101
+ SuccessResponse --> [*]
102
+
103
+ RelayRejected --> ErrorResponse
104
+ RelayUnavailable --> ErrorResponse
105
+ ErrorResponse --> [*]
106
+ ```
107
+
108
+ What the service returns:
109
+
110
+ - `confirmed` or `mempool`: resource is delivered normally.
111
+ - `pending`: resource is still delivered, but response includes `paymentStatus: "pending"` and `paymentId`.
112
+ - `failed`, `replaced`, `not_found`, or relay unavailability: request fails.
113
+
114
+ ## 3. Relay Queue Payment State Machine: `x402-sponsor-relay` RPC path
115
+
116
+ This is the async `paymentId` lifecycle behind `submitPayment()` and `checkPayment()`.
117
+
118
+ ```mermaid
119
+ stateDiagram-v2
120
+ [*] --> Submitted
121
+
122
+ Submitted --> Failed: invalid tx / not sponsored / stale nonce / duplicate nonce
123
+ Submitted --> Queued: paymentId created + KV record written + queue send ok
124
+
125
+ Queued --> Broadcasting: queue consumer starts work
126
+ Queued --> Queued: held sender nonce gap
127
+ Queued --> Queued: sponsor contention retry
128
+ Queued --> Failed: queue unavailable / terminal sponsor failure
129
+
130
+ Broadcasting --> Queued: nonce conflict or TooMuchChaining retry
131
+ Broadcasting --> Failed: terminal broadcast failure
132
+ Broadcasting --> Mempool: broadcastOnly() returns txid
133
+
134
+ Mempool --> Confirmed: chainhook marks success
135
+ Mempool --> Failed: chainhook sees on-chain abort
136
+ Mempool --> Replaced: NonceDO replacement notification
137
+ Mempool --> Mempool: waiting for chainhook/finalization
138
+
139
+ Failed --> [*]
140
+ Confirmed --> [*]
141
+ Replaced --> [*]
142
+ ```
143
+
144
+ Stored `paymentId` statuses exposed by `checkPayment()`:
145
+
146
+ - Pending/in-flight: `queued`, `submitted`, `broadcasting`, `mempool`
147
+ - Terminal: `confirmed`, `failed`, `replaced`
148
+ - Missing/expired: `not_found`
149
+
150
+ ## 4. Direct Relay Settlement State Machine: `/settle` to Hiro final status
151
+
152
+ This is the synchronous/native settlement flow used by the relay itself when handling direct `/settle` or `/relay` style settlement logic.
153
+
154
+ ```mermaid
155
+ stateDiagram-v2
156
+ [*] --> ValidatePayment
157
+
158
+ ValidatePayment --> Failed: tx deserialize or payment requirements invalid
159
+ ValidatePayment --> Broadcasting
160
+
161
+ Broadcasting --> BroadcastRetry: Hiro/node 5xx or retryable transport failure
162
+ Broadcasting --> Failed: client rejection or terminal broadcast failure
163
+ Broadcasting --> PendingReturn: caller requested broadcast-only mode
164
+ Broadcasting --> PollingHiro: txid accepted
165
+
166
+ BroadcastRetry --> Broadcasting
167
+ BroadcastRetry --> Failed: retries exhausted
168
+
169
+ PollingHiro --> Confirmed: Hiro tx_status=success + block_height
170
+ PollingHiro --> Failed: Hiro tx_status=abort_*
171
+ PollingHiro --> PollingHiro: tx_status=pending
172
+ PollingHiro --> PollingHiro: tx_status=dropped_* treated as transient
173
+ PollingHiro --> PollingHiro: 404 not yet indexed
174
+ PollingHiro --> PollingHiro: degraded Hiro polling with backoff
175
+ PollingHiro --> PendingReturn: poll budget exhausted
176
+
177
+ PendingReturn --> BackgroundStatusTracking
178
+ BackgroundStatusTracking --> Confirmed: later Hiro/chainhook confirmation
179
+ BackgroundStatusTracking --> Failed: later on-chain abort
180
+
181
+ Confirmed --> [*]
182
+ Failed --> [*]
183
+ ```
184
+
185
+ Important Hiro-specific behavior:
186
+
187
+ - `success` is only terminal when `block_height` is present.
188
+ - `abort_*` is terminal failure.
189
+ - `dropped_*` is treated as transient and the relay keeps polling.
190
+ - If polling budget expires, relay returns `pending` and status is updated later via KV + background/chainhook updates.
191
+
192
+ ## 5. End-to-End View
193
+
194
+ ```mermaid
195
+ stateDiagram-v2
196
+ [*] --> ClientCallsService
197
+ ClientCallsService --> NeedsPayment: service returns 402
198
+ NeedsPayment --> ClientSignsSponsoredTx
199
+ ClientSignsSponsoredTx --> ServiceVerifies
200
+
201
+ ServiceVerifies --> RelayQueueFlow: landing-page / agent-news RPC submitPayment
202
+ ServiceVerifies --> RelaySettleFlow: fallback HTTP /settle
203
+
204
+ RelayQueueFlow --> HiroObserved
205
+ RelaySettleFlow --> HiroObserved
206
+
207
+ HiroObserved --> FinalConfirmed
208
+ HiroObserved --> FinalFailed
209
+ HiroObserved --> ServicePending
210
+
211
+ ServicePending --> ClientPollsPaymentId
212
+ ClientPollsPaymentId --> FinalConfirmed
213
+ ClientPollsPaymentId --> FinalFailed
214
+ ClientPollsPaymentId --> ServicePending
215
+
216
+ FinalConfirmed --> [*]
217
+ FinalFailed --> [*]
218
+ ```
219
+
220
+ ## Code Anchors
221
+
222
+ - Client payment interceptor:
223
+ - `aibtc-mcp-server/src/services/x402.service.ts`
224
+ - `skills/src/lib/services/x402.service.ts`
225
+ - Client inbox retry and recovery:
226
+ - `skills/src/lib/utils/x402-retry.ts`
227
+ - `skills/src/lib/utils/x402-recovery.ts`
228
+ - `aibtc-mcp-server/src/tools/inbox.tools.ts`
229
+ - Service verification and pending-success behavior:
230
+ - `landing-page/app/api/inbox/[address]/route.ts`
231
+ - `landing-page/app/api/payment-status/[paymentId]/route.ts`
232
+ - `agent-news/src/services/x402.ts`
233
+ - `agent-news/src/routes/payment-status.ts`
234
+ - Relay async payment status:
235
+ - `x402-sponsor-relay/src/rpc.ts`
236
+ - `x402-sponsor-relay/src/services/payment-status.ts`
237
+ - `x402-sponsor-relay/src/queue-consumer.ts`
238
+ - `x402-sponsor-relay/src/endpoints/chainhook.ts`
239
+ - `x402-sponsor-relay/src/durable-objects/nonce-do.ts`
240
+ - Relay Hiro settlement polling:
241
+ - `x402-sponsor-relay/src/services/settlement.ts`
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "@aibtc/tx-schemas",
3
+ "version": "0.1.0",
4
+ "description": "Shared zod schemas for AIBTC transaction states, internal relay schemas, and external x402 payment schemas.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./core": {
15
+ "types": "./dist/core/index.d.ts",
16
+ "import": "./dist/core/index.js"
17
+ },
18
+ "./core/enums": {
19
+ "types": "./dist/core/enums.d.ts",
20
+ "import": "./dist/core/enums.js"
21
+ },
22
+ "./terminal-reasons": {
23
+ "types": "./dist/core/terminal-reasons.d.ts",
24
+ "import": "./dist/core/terminal-reasons.js"
25
+ },
26
+ "./core/terminal-reasons": {
27
+ "types": "./dist/core/terminal-reasons.d.ts",
28
+ "import": "./dist/core/terminal-reasons.js"
29
+ },
30
+ "./core/primitives": {
31
+ "types": "./dist/core/primitives.d.ts",
32
+ "import": "./dist/core/primitives.js"
33
+ },
34
+ "./core/schemas": {
35
+ "types": "./dist/core/schemas.d.ts",
36
+ "import": "./dist/core/schemas.js"
37
+ },
38
+ "./rpc": {
39
+ "types": "./dist/rpc/index.d.ts",
40
+ "import": "./dist/rpc/index.js"
41
+ },
42
+ "./rpc/schemas": {
43
+ "types": "./dist/rpc/schemas.d.ts",
44
+ "import": "./dist/rpc/schemas.js"
45
+ },
46
+ "./http": {
47
+ "types": "./dist/http/index.d.ts",
48
+ "import": "./dist/http/index.js"
49
+ },
50
+ "./http/schemas": {
51
+ "types": "./dist/http/schemas.d.ts",
52
+ "import": "./dist/http/schemas.js"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "files": [
57
+ "dist",
58
+ "README.md",
59
+ "docs/package-schemas.md",
60
+ "docs/x402-approval-spec.md",
61
+ "docs/x402-state-machines.md",
62
+ "LICENSE"
63
+ ],
64
+ "scripts": {
65
+ "build": "tsc -p tsconfig.build.json",
66
+ "typecheck": "tsc -p tsconfig.json --noEmit",
67
+ "test": "vitest run",
68
+ "test:watch": "vitest",
69
+ "prepublishOnly": "npm run build && npm run typecheck && npm test",
70
+ "pack:dry-run": "npm pack --dry-run"
71
+ },
72
+ "keywords": [
73
+ "aibtc",
74
+ "x402",
75
+ "schemas",
76
+ "zod",
77
+ "stacks",
78
+ "payments",
79
+ "rpc",
80
+ "http"
81
+ ],
82
+ "author": "aibtcdev",
83
+ "repository": {
84
+ "type": "git",
85
+ "url": "git+https://github.com/aibtcdev/tx-schemas.git"
86
+ },
87
+ "homepage": "https://github.com/aibtcdev/tx-schemas#readme",
88
+ "license": "MIT",
89
+ "publishConfig": {
90
+ "access": "public",
91
+ "registry": "https://registry.npmjs.org"
92
+ },
93
+ "dependencies": {
94
+ "zod": "^4.3.6"
95
+ },
96
+ "devDependencies": {
97
+ "@types/node": "^22.19.13",
98
+ "typescript": "^5.9.3",
99
+ "vitest": "^4.0.18"
100
+ }
101
+ }