@cmdoss/suipay-mcp 0.2.1 → 0.2.2-dev.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/README.md +61 -8
- package/dist/bin/suipay.js +2 -3
- package/dist/chunk-K6WM4Z7H.js +46 -0
- package/dist/{chunk-XZQOOY66.js → chunk-NVTYOOMY.js} +3743 -1623
- package/dist/http-B4YTVw0k.d.ts +392 -0
- package/dist/http.d.ts +7 -2
- package/dist/http.js +1 -2
- package/dist/index.d.ts +109 -35
- package/dist/index.js +14 -3
- package/package.json +9 -7
- package/dist/chunk-A3JIIDYT.js +0 -161
- package/dist/chunk-TPW6S2K4.js +0 -39
- package/dist/http-BnIjiwcR.d.ts +0 -1149
- package/dist/personal-message-5PF4KVLF.js +0 -284
package/dist/http-BnIjiwcR.d.ts
DELETED
|
@@ -1,1149 +0,0 @@
|
|
|
1
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
-
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolve which grant policy target may pay a seller offer's targetHash (WS7.6).
|
|
6
|
-
*
|
|
7
|
-
* SINGLE SOURCE — consent validation and MCP pay MUST use this helper.
|
|
8
|
-
* Never inline "find policy by hash" in tools or consent UI.
|
|
9
|
-
*
|
|
10
|
-
* Seller offer carries targetHash only (no buyer policyId). Buyer authority
|
|
11
|
-
* is the OAuth grant snapshot of policies/targets at consent time.
|
|
12
|
-
*/
|
|
13
|
-
type GrantLifecycleStatus = 'pending' | 'active' | 'paused' | 'revoked' | 'expired';
|
|
14
|
-
type PolicyLifecycleStatus = 'draft' | 'active' | 'paused' | 'revoked';
|
|
15
|
-
interface GrantTargetBinding {
|
|
16
|
-
/** 32-byte hex target hash. */
|
|
17
|
-
targetHash: string;
|
|
18
|
-
/** Optional per-target ceiling (atomic units). */
|
|
19
|
-
maxPerPayment?: string;
|
|
20
|
-
/**
|
|
21
|
-
* The address this target pays, when the authority source records one.
|
|
22
|
-
* Carried for callers that want to pin the payee before signing; target
|
|
23
|
-
* resolution itself matches on {@link targetHash} alone, because the offer's
|
|
24
|
-
* `payTo` is what the settlement actually pays.
|
|
25
|
-
*/
|
|
26
|
-
recipient?: string;
|
|
27
|
-
}
|
|
28
|
-
interface GrantPolicyBinding {
|
|
29
|
-
/** Off-chain policy id (for audit). */
|
|
30
|
-
policyId: string;
|
|
31
|
-
/** On-chain policy id (u64) inside SpendAccount. */
|
|
32
|
-
onChainPolicyId: number | string;
|
|
33
|
-
status: PolicyLifecycleStatus;
|
|
34
|
-
targets: readonly GrantTargetBinding[];
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Immutable snapshot of buyer authority for one OAuth grant.
|
|
38
|
-
* Pool/grant object ids come from finalized on-chain objects (or fake in WS6B).
|
|
39
|
-
*/
|
|
40
|
-
interface GrantSnapshot {
|
|
41
|
-
grantId: string;
|
|
42
|
-
status: GrantLifecycleStatus;
|
|
43
|
-
grantObjectId: string | null;
|
|
44
|
-
poolObjectId: string;
|
|
45
|
-
coinType: string;
|
|
46
|
-
delegateAddress: string;
|
|
47
|
-
policies: readonly GrantPolicyBinding[];
|
|
48
|
-
/**
|
|
49
|
-
* `open` = open-recipient (no allowlist, caps required); `scoped` / omit = policy-bound.
|
|
50
|
-
*/
|
|
51
|
-
accessMode?: 'scoped' | 'open';
|
|
52
|
-
/** Grant-level max per payment (atomic); used for open and as a grant ceiling. */
|
|
53
|
-
maxPerPayment?: string | null;
|
|
54
|
-
/** Grant-level session cap (atomic); open requires a positive value. */
|
|
55
|
-
sessionCap?: string | null;
|
|
56
|
-
}
|
|
57
|
-
type ResolveGrantTargetResult = {
|
|
58
|
-
ok: true;
|
|
59
|
-
policyId: string;
|
|
60
|
-
onChainPolicyId: number | string;
|
|
61
|
-
targetHash: string;
|
|
62
|
-
maxPerPayment?: string;
|
|
63
|
-
poolObjectId: string;
|
|
64
|
-
grantObjectId: string;
|
|
65
|
-
coinType: string;
|
|
66
|
-
delegateAddress: string;
|
|
67
|
-
} | {
|
|
68
|
-
ok: false;
|
|
69
|
-
reason: string;
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* Pick the policy target that matches offer.targetHash under an active grant.
|
|
73
|
-
* Pause/revoke of grant or policy fails closed without decrypting the delegate.
|
|
74
|
-
*/
|
|
75
|
-
declare function resolveGrantTarget(snapshot: GrantSnapshot, offerTargetHash: string): ResolveGrantTargetResult;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Public authorization facts exposed to authenticated MCP clients.
|
|
79
|
-
*
|
|
80
|
-
* This shape is descriptive only. Payment authorization continues to use the
|
|
81
|
-
* immutable on-chain GrantSnapshot; callers must never derive spend authority
|
|
82
|
-
* from this object.
|
|
83
|
-
*/
|
|
84
|
-
interface McpAccessProfile {
|
|
85
|
-
id: string;
|
|
86
|
-
name: string;
|
|
87
|
-
status: 'active' | 'disabled';
|
|
88
|
-
}
|
|
89
|
-
interface McpAccessTarget {
|
|
90
|
-
serviceId: string;
|
|
91
|
-
/** Friendly seller service name (live catalog), or serviceId if unresolved. */
|
|
92
|
-
name: string;
|
|
93
|
-
endpointId: string;
|
|
94
|
-
method: string;
|
|
95
|
-
path: string;
|
|
96
|
-
targetHash: string;
|
|
97
|
-
maxPerPayment: string;
|
|
98
|
-
}
|
|
99
|
-
interface McpAccessPolicy {
|
|
100
|
-
id: string;
|
|
101
|
-
name: string;
|
|
102
|
-
status: 'draft' | 'active' | 'paused' | 'revoked';
|
|
103
|
-
asset: string;
|
|
104
|
-
coinType: string;
|
|
105
|
-
totalCap: string;
|
|
106
|
-
spent: string;
|
|
107
|
-
maxPerPayment: string;
|
|
108
|
-
expiresAt: string | null;
|
|
109
|
-
targets: McpAccessTarget[];
|
|
110
|
-
}
|
|
111
|
-
interface McpAccessContext {
|
|
112
|
-
accessMode: 'scoped' | 'open';
|
|
113
|
-
grant: {
|
|
114
|
-
id: string;
|
|
115
|
-
status: 'pending' | 'active' | 'paused' | 'revoked' | 'expired';
|
|
116
|
-
sessionCap: string | null;
|
|
117
|
-
sessionSpent: string;
|
|
118
|
-
expiresAt: string | null;
|
|
119
|
-
};
|
|
120
|
-
profiles: McpAccessProfile[];
|
|
121
|
-
policies: McpAccessPolicy[];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Shared vocabulary for both 402 dialects.
|
|
126
|
-
*
|
|
127
|
-
* The central claim of this PoC is that MPP and x402 are two encodings of one
|
|
128
|
-
* payment offer, not two payment systems. Everything below the dialect codecs
|
|
129
|
-
* therefore speaks in these types; only `mpp.ts` and `x402.ts` know about
|
|
130
|
-
* headers and JSON bodies.
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
/** Payment intent on a signed offer. Default / omitted = one-shot charge. */
|
|
134
|
-
type PaymentIntent = 'charge' | 'subscription';
|
|
135
|
-
/** Proof of settlement, returned alongside the resource. */
|
|
136
|
-
interface Receipt {
|
|
137
|
-
challengeId: string;
|
|
138
|
-
/** On-chain transaction digest. */
|
|
139
|
-
txDigest: string;
|
|
140
|
-
network: string;
|
|
141
|
-
payer: string;
|
|
142
|
-
/** Gross amount settled (atomic units). */
|
|
143
|
-
amount: string;
|
|
144
|
-
asset: string;
|
|
145
|
-
status: 'settled';
|
|
146
|
-
/**
|
|
147
|
-
* Canonical requestDigest this settlement paid for. Bound to `txDigest` so
|
|
148
|
-
* a receipt proves one specific HTTP request was settled on chain.
|
|
149
|
-
*/
|
|
150
|
-
requestDigest?: string;
|
|
151
|
-
/** Seller net proceeds (atomic units). Explicit fee semantics; PoC equals amount. */
|
|
152
|
-
netAmount?: string;
|
|
153
|
-
/** Facilitator platform fee (atomic units). PoC is `"0"`. */
|
|
154
|
-
platformFee?: string;
|
|
155
|
-
/** Payment intent when settled via a non-charge flow (e.g. subscription). */
|
|
156
|
-
intent?: PaymentIntent;
|
|
157
|
-
/** Subscription mandate object id when intent=subscription. */
|
|
158
|
-
mandateId?: string;
|
|
159
|
-
/** Clock-derived period index that was charged (subscription). */
|
|
160
|
-
periodIndex?: string;
|
|
161
|
-
/**
|
|
162
|
-
* Canonical payment_key hex when settlement opened a RefundVault (refundable).
|
|
163
|
-
* Used as the durable delivery-success key and operator-refund identity.
|
|
164
|
-
*/
|
|
165
|
-
paymentKey?: string;
|
|
166
|
-
/** Shared vault object id when refundable. */
|
|
167
|
-
vaultId?: string;
|
|
168
|
-
/** Pinned refund beneficiary from VaultOpened when refundable. */
|
|
169
|
-
refundTo?: string;
|
|
170
|
-
/**
|
|
171
|
-
* Canonical `GrantCap` object id this settlement drew against (shared_pool
|
|
172
|
-
* rail only). `padObjectId` form — the SAME identity the session receipt
|
|
173
|
-
* ledger keys by (`sessionIdForGrant`), so the durable projection and the
|
|
174
|
-
* session ledger converge on one grant id. Absent for non-shared_pool rails
|
|
175
|
-
* and refundable-vault settlements, which carry no PaymentMade grant.
|
|
176
|
-
*/
|
|
177
|
-
grantId?: string;
|
|
178
|
-
/**
|
|
179
|
-
* Canonical `SpendAccount` object id the grant draws from (shared_pool rail
|
|
180
|
-
* only). Absent wherever `grantId` is.
|
|
181
|
-
*/
|
|
182
|
-
poolId?: string;
|
|
183
|
-
}
|
|
184
|
-
/** Which encoding a message used. Recorded so the provider can answer in kind. */
|
|
185
|
-
type Dialect = 'mpp' | 'x402';
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Canonical settlement and payment-list rows.
|
|
189
|
-
*
|
|
190
|
-
* The gateway HTTP handlers project into these shapes; they do not own them.
|
|
191
|
-
* Wire codecs stay in `src/protocol`. Owner/control-plane rows live here so
|
|
192
|
-
* `buyer-control` never imports types from `gateway/app`.
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* The canonical `/v1/settlements` wire row. Both settlement sources — the live
|
|
197
|
-
* in-memory feed and the durable read model — normalize to this shape so the
|
|
198
|
-
* response is byte-stable regardless of whether a read model (DATABASE_URL) is
|
|
199
|
-
* configured. Consumers (MCP `receipts` tool, buyer/seller console) read
|
|
200
|
-
* `receipt.txDigest`; a source that returns its own native shape breaks them.
|
|
201
|
-
*/
|
|
202
|
-
interface SettlementDTO {
|
|
203
|
-
at: string;
|
|
204
|
-
resourceId?: string;
|
|
205
|
-
recipient: string;
|
|
206
|
-
dialect?: Dialect;
|
|
207
|
-
receipt: {
|
|
208
|
-
challengeId: string;
|
|
209
|
-
txDigest: string;
|
|
210
|
-
network: string;
|
|
211
|
-
payer: string;
|
|
212
|
-
amount: string;
|
|
213
|
-
asset: string;
|
|
214
|
-
status: 'settled';
|
|
215
|
-
};
|
|
216
|
-
/**
|
|
217
|
-
* Present only on the live in-memory feed. The read model dedups on
|
|
218
|
-
* (network, digest), so a durable row is never a replay — the field is
|
|
219
|
-
* omitted there rather than asserted false. Consumers must treat absent as
|
|
220
|
-
* not-replayed.
|
|
221
|
-
*/
|
|
222
|
-
replayed?: boolean;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Authenticated MCP request context (remote Streamable HTTP).
|
|
227
|
-
* Bearer is required on /mcp; tools enforce scope from the resolved grant.
|
|
228
|
-
*/
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Read/prepare-only shared-pool context for an authenticated MCP bearer.
|
|
232
|
-
*
|
|
233
|
-
* Non-custodial: the gateway holds NO key that can spend. There is deliberately
|
|
234
|
-
* no `decryptDelegateSeed` and no forwarded `sponsorAuthorization` here — the
|
|
235
|
-
* `pay` tool only PREPARES an unsigned `spend_account::settle_policy_payment` transaction from the
|
|
236
|
-
* immutable grant snapshot (`prepareSpendAccountPayment`), and the client that
|
|
237
|
-
* holds the delegate key signs locally and submits. Only signatures ever reach
|
|
238
|
-
* the gateway. See docs/design/mcp-non-custodial-signing.md and ADR-0013 §3.
|
|
239
|
-
*/
|
|
240
|
-
interface McpSpendAccountPayAuth {
|
|
241
|
-
snapshot: GrantSnapshot;
|
|
242
|
-
packageId: string;
|
|
243
|
-
/**
|
|
244
|
-
* Re-verify the paying authority against a FRESH graph + injected clock at
|
|
245
|
-
* prepare time. Throws on drift/expiry so the pay tool refuses to hand back a
|
|
246
|
-
* signing request for a grant that just went paused/revoked/expired. Optional:
|
|
247
|
-
* absent for legacy/local paths.
|
|
248
|
-
*/
|
|
249
|
-
assertLive?: () => Promise<void>;
|
|
250
|
-
}
|
|
251
|
-
interface McpAuthContext {
|
|
252
|
-
grantId: string;
|
|
253
|
-
buyerAccountId: string;
|
|
254
|
-
/** Space-separated scopes from the access token. */
|
|
255
|
-
scope: string;
|
|
256
|
-
/** Public, descriptive policy context. Never used as payment authority. */
|
|
257
|
-
access?: McpAccessContext;
|
|
258
|
-
/**
|
|
259
|
-
* When present, `pay` prepares unsigned spend_account::settle_policy_payment bytes for the
|
|
260
|
-
* client-held delegate key to sign locally — no server-side decrypt or
|
|
261
|
-
* signing. Stdio local V1 profile path remains when absent.
|
|
262
|
-
*/
|
|
263
|
-
spendAccountPay?: McpSpendAccountPayAuth;
|
|
264
|
-
/**
|
|
265
|
-
* Server-scoped receipts reader, built by the /mcp route from the verified
|
|
266
|
-
* bearer's connection. The `receipts` tool calls this instead of hitting the
|
|
267
|
-
* global settlement feed with a forwarded credential — the bearer never
|
|
268
|
-
* enters the tool surface, and scoping is enforced server-side. Absent for
|
|
269
|
-
* local stdio (no connection, no settlement source).
|
|
270
|
-
*/
|
|
271
|
-
listReceipts?: (challengeId?: string) => Promise<SettlementDTO[]>;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
interface McpConfig {
|
|
275
|
-
consoleUrl: string;
|
|
276
|
-
gatewayUrl: string;
|
|
277
|
-
rpcUrl: string;
|
|
278
|
-
network: 'testnet' | 'mainnet' | 'devnet' | 'localnet';
|
|
279
|
-
packageId: string;
|
|
280
|
-
recipient: string;
|
|
281
|
-
coinType: string;
|
|
282
|
-
sponsorUrl: string;
|
|
283
|
-
minFunded: bigint;
|
|
284
|
-
minMaxPerPayment: bigint;
|
|
285
|
-
label: string;
|
|
286
|
-
}
|
|
287
|
-
declare function loadMcpConfig(env?: NodeJS.ProcessEnv): McpConfig;
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Grant-scoped read ergonomics for a delegate agent.
|
|
291
|
-
*
|
|
292
|
-
* Two kinds of read, mirroring the epic's public/private split:
|
|
293
|
-
*
|
|
294
|
-
* 1. Enriched-context reads ({@link createReader}) — the private,
|
|
295
|
-
* off-chain-enriched projections behind P2's signed routes
|
|
296
|
-
* (`GET /v1/delegate/{balance,policies,receipts}`). Each request is signed
|
|
297
|
-
* with the four `x-suipay-*` headers (via the P0-backed signing helper),
|
|
298
|
-
* so the gateway resolves the caller's grant and returns ONLY that grant's
|
|
299
|
-
* state. Non-2xx responses are classified, never swallowed.
|
|
300
|
-
*
|
|
301
|
-
* 2. Direct on-chain reads ({@link readPublicGrantState} /
|
|
302
|
-
* {@link readPublicSpendAccountState}) — the PUBLIC on-chain facts (delegate, caps,
|
|
303
|
-
* spend, policy ids, pause/revoke, pool balance) read straight from a
|
|
304
|
-
* `getObject` projection with no signature. Public data stays public.
|
|
305
|
-
*
|
|
306
|
-
* The read client never spends and never holds the private key: money still
|
|
307
|
-
* moves only through the delegate's own on-chain `spend_account::settle_policy_payment`.
|
|
308
|
-
*/
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Fetch the Move JSON contents of an object. Wire this to
|
|
312
|
-
* `client.core.getObject({ objectId, include: { json: true } })` and return its
|
|
313
|
-
* `object.json`. `null` for a missing object. Injected so the reader is pure and
|
|
314
|
-
* testable with fakes and depends on no Sui client at load time.
|
|
315
|
-
*/
|
|
316
|
-
type GetObjectJson = (objectId: string) => Promise<Record<string, unknown> | null | undefined>;
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Non-MCP SDK/REST delegated-signer payer (Phase C1).
|
|
320
|
-
*
|
|
321
|
-
* MPP pay-then-prove over `spend_account::settle_policy_payment` with a bring-your-own
|
|
322
|
-
* delegated key. Mirrors packages/mcp/src/spend-account-pay.ts but:
|
|
323
|
-
* - gas: agent-provided coins (default when configured) OR sponsored gas
|
|
324
|
-
* gated by sponsor personal-message challenge (Phase C2 / ADR-0008)
|
|
325
|
-
* - never enables x402 transaction-submit for shared_pool (stays gated)
|
|
326
|
-
*
|
|
327
|
-
* Order is load-bearing on the money path (no step may run before the prior):
|
|
328
|
-
* 1. Bound the offer FIRST — the gateway secret's HMAC over it, the agent's
|
|
329
|
-
* own SpendIntent, or both; at least one is required. Nothing else
|
|
330
|
-
* (ledger, capability, hashing) runs before this.
|
|
331
|
-
* 2. Request-binding + offer-expiry checks.
|
|
332
|
-
* 3. ATOMIC reserve on the REQUIRED payment-attempt ledger (payment_id).
|
|
333
|
-
* - reserved -> this attempt owns the id; may proceed to build/sign
|
|
334
|
-
* - done -> return validated prior ok/ambiguous (no re-sign)
|
|
335
|
-
* - in_flight -> another attempt is mid-flight; return ambiguous (no sign)
|
|
336
|
-
* Reserve failure fails closed: never sign without a durable claim.
|
|
337
|
-
* 4. Execution-capability check (submitter present). After reserve so a
|
|
338
|
-
* prior done result is never lost when capability is unavailable.
|
|
339
|
-
* 5. Derive payment_id_hash / terms_hash.
|
|
340
|
-
* 6. Build the full executable pay transaction (real shared-object versions).
|
|
341
|
-
* 7. Validate-before-sign (built tx encodes exactly the intended pay; gas may differ).
|
|
342
|
-
* 8. Sign, 9. execute, 10. complete(ledger) with terminal ok/ambiguous, settle.
|
|
343
|
-
*
|
|
344
|
-
* Exactly-once for concurrent pay() on the same payment_id is the ledger
|
|
345
|
-
* reserve CAS (memory: sync check-and-insert; Postgres: INSERT ON CONFLICT).
|
|
346
|
-
* Settlement single-use on chain is the pool-scoped payment_id_hash replay
|
|
347
|
-
* marker inside pay. The durable ChallengeStore is a delivery/proof CAS
|
|
348
|
-
* (prevents a second proof/delivery for the same challenge), not the money
|
|
349
|
-
* CAS (see ADR-0002).
|
|
350
|
-
*/
|
|
351
|
-
|
|
352
|
-
type DelegatedPayStatus = 'ok' | 'failed' | 'ambiguous';
|
|
353
|
-
/**
|
|
354
|
-
* Closed set of caller-visible error codes. Never surface a gateway-controlled
|
|
355
|
-
* header, token, or body string as `code`.
|
|
356
|
-
*/
|
|
357
|
-
declare const DELEGATED_PAY_ERROR_CODES: {
|
|
358
|
-
readonly OFFER_SECRET_REQUIRED: "OFFER_SECRET_REQUIRED";
|
|
359
|
-
readonly CHALLENGE_TAMPERED: "CHALLENGE_TAMPERED";
|
|
360
|
-
readonly CHALLENGE_EXPIRED: "CHALLENGE_EXPIRED";
|
|
361
|
-
readonly MALFORMED_CHALLENGE: "MALFORMED_CHALLENGE";
|
|
362
|
-
readonly POLICY_REJECTED: "POLICY_REJECTED";
|
|
363
|
-
readonly GRANT_DENIED: "GRANT_DENIED";
|
|
364
|
-
readonly BUILD_FAILED: "BUILD_FAILED";
|
|
365
|
-
readonly TX_MISMATCH: "TX_MISMATCH";
|
|
366
|
-
readonly SIGN_FAILED: "SIGN_FAILED";
|
|
367
|
-
readonly EXECUTE_UNAVAILABLE: "EXECUTE_UNAVAILABLE";
|
|
368
|
-
readonly EXECUTE_AMBIGUOUS: "EXECUTE_AMBIGUOUS";
|
|
369
|
-
readonly FINALITY_AMBIGUOUS: "FINALITY_AMBIGUOUS";
|
|
370
|
-
readonly FINALIZATION_TIMEOUT: "FINALIZATION_TIMEOUT";
|
|
371
|
-
readonly SETTLEMENT_REJECTED: "SETTLEMENT_REJECTED";
|
|
372
|
-
readonly PROOF_PRESENTATION_FAILED: "PROOF_PRESENTATION_FAILED";
|
|
373
|
-
readonly GATEWAY_REFUSED: "GATEWAY_REFUSED";
|
|
374
|
-
readonly UNSUPPORTED_REQUEST: "UNSUPPORTED_REQUEST";
|
|
375
|
-
readonly IDEMPOTENT_PRIOR: "IDEMPOTENT_PRIOR";
|
|
376
|
-
readonly PAYMENT_LEDGER_REQUIRED: "PAYMENT_LEDGER_REQUIRED";
|
|
377
|
-
readonly SHARED_OBJECT_RESOLVE_FAILED: "SHARED_OBJECT_RESOLVE_FAILED";
|
|
378
|
-
/** Atomic reserve or complete could not be persisted; never sign unprotected. */
|
|
379
|
-
readonly PAYMENT_LEDGER_FAILED: "PAYMENT_LEDGER_FAILED";
|
|
380
|
-
/** Another attempt holds the in-flight reservation for this payment_id. */
|
|
381
|
-
readonly PAYMENT_ATTEMPT_IN_FLIGHT: "PAYMENT_ATTEMPT_IN_FLIGHT";
|
|
382
|
-
/** Platform sponsor challenge/create/execute failed or returned unusable data. */
|
|
383
|
-
readonly SPONSOR_UNAVAILABLE: "SPONSOR_UNAVAILABLE";
|
|
384
|
-
/** Sponsored bytes did not reconstruct the intended pay. */
|
|
385
|
-
readonly SPONSORED_TX_MISMATCH: "SPONSORED_TX_MISMATCH";
|
|
386
|
-
/** Personal-message signature is required for sponsored gas. */
|
|
387
|
-
readonly PERSONAL_MESSAGE_SIGN_REQUIRED: "PERSONAL_MESSAGE_SIGN_REQUIRED";
|
|
388
|
-
/** Resource answered a non-402 4xx (or other non-2xx client class): rejected. */
|
|
389
|
-
readonly RESOURCE_REJECTED: "RESOURCE_REJECTED";
|
|
390
|
-
/** Resource answered a non-402 5xx: temporarily unavailable, not a rejection. */
|
|
391
|
-
readonly RESOURCE_UNAVAILABLE: "RESOURCE_UNAVAILABLE";
|
|
392
|
-
/** No finality reader configured: refuse to sign a pay we cannot confirm. */
|
|
393
|
-
readonly FINALITY_UNAVAILABLE: "FINALITY_UNAVAILABLE";
|
|
394
|
-
/**
|
|
395
|
-
* The settlement hop's offer prices something other than the terms that were
|
|
396
|
-
* verified at prepare. Distinct from TX_MISMATCH: the transaction bytes were
|
|
397
|
-
* never in question — the *offer they would be built from* moved between the
|
|
398
|
-
* hop that was checked and the hop that would sign.
|
|
399
|
-
*/
|
|
400
|
-
readonly PREPARED_OFFER_DIVERGED: "PREPARED_OFFER_DIVERGED";
|
|
401
|
-
/**
|
|
402
|
-
* The pre-sign check could not run to a verdict (e.g. the unsigned getObject
|
|
403
|
-
* read was unreachable). "Could not verify" is not "verified and it failed":
|
|
404
|
-
* reporting an RPC outage as tampering sends an operator hunting a security
|
|
405
|
-
* incident that did not happen.
|
|
406
|
-
*/
|
|
407
|
-
readonly PREPARED_VERIFY_UNAVAILABLE: "PREPARED_VERIFY_UNAVAILABLE";
|
|
408
|
-
/**
|
|
409
|
-
* The offer prices something other than what the caller said it was buying.
|
|
410
|
-
* Distinct from POLICY_REJECTED, which is the grant's opinion: this is the
|
|
411
|
-
* AGENT's own ceiling, and it is the check that does not need the gateway's
|
|
412
|
-
* secret to be meaningful.
|
|
413
|
-
*/
|
|
414
|
-
readonly SPEND_INTENT_VIOLATED: "SPEND_INTENT_VIOLATED";
|
|
415
|
-
};
|
|
416
|
-
type DelegatedPayErrorCode = (typeof DELEGATED_PAY_ERROR_CODES)[keyof typeof DELEGATED_PAY_ERROR_CODES];
|
|
417
|
-
/**
|
|
418
|
-
* Classification of a resource's non-402 response. Distinguishes a resource
|
|
419
|
-
* served without payment (`unpaid_ok`, a 2xx) from a client-side refusal
|
|
420
|
-
* (`rejected`, a non-2xx below 500) and a transient outage (`unavailable`, a
|
|
421
|
-
* 5xx) — so a caller never mistakes a 503 for "already paid / ok". Absent on a
|
|
422
|
-
* 402-driven pay outcome, which the `status`/`code`/`paid` fields describe.
|
|
423
|
-
*/
|
|
424
|
-
type DelegatedPayResponseClass = 'unpaid_ok' | 'rejected' | 'unavailable';
|
|
425
|
-
/**
|
|
426
|
-
* The settled effects of a finality-confirmed pay, so a caller need not do a
|
|
427
|
-
* separate on-chain read to learn what moved. `spend_account::settle_policy_payment` debits exactly
|
|
428
|
-
* `amount` of `coinType` to `recipient` from the grant's pool, and a `success`
|
|
429
|
-
* finality confirms that transfer executed — so these are the settled effects,
|
|
430
|
-
* not merely the intended ones. Present only on a settled (`paid`) result.
|
|
431
|
-
*/
|
|
432
|
-
interface DelegatedPaySettlement {
|
|
433
|
-
/** Finality-confirmed settlement status (only `success` reaches a paid result). */
|
|
434
|
-
status: 'success';
|
|
435
|
-
/** The settling transaction digest. */
|
|
436
|
-
txDigest: string;
|
|
437
|
-
/** Atomic units debited to the recipient (the offer amount the pay enforced). */
|
|
438
|
-
amount: string;
|
|
439
|
-
/** The paid recipient (the offer/target payTo the pay debited to). */
|
|
440
|
-
recipient: string;
|
|
441
|
-
/** Coin type settled. */
|
|
442
|
-
coinType: string;
|
|
443
|
-
/** Off-chain asset id of the offer. */
|
|
444
|
-
asset: string;
|
|
445
|
-
/** Grant object that authorized the draw. */
|
|
446
|
-
grantObjectId: string;
|
|
447
|
-
/** Pool object the draw debited. */
|
|
448
|
-
poolObjectId: string;
|
|
449
|
-
}
|
|
450
|
-
interface DelegatedPayResult {
|
|
451
|
-
/**
|
|
452
|
-
* How resolved the outcome is: `ok` = settled AND delivered; `ambiguous` =
|
|
453
|
-
* something after the signature is unresolved, so reconcile rather than retry;
|
|
454
|
-
* `failed` = nothing was signed, or the chain rejected the settlement.
|
|
455
|
-
*/
|
|
456
|
-
status: DelegatedPayStatus;
|
|
457
|
-
/**
|
|
458
|
-
* Did money leave the grant?
|
|
459
|
-
*
|
|
460
|
-
* - `true` — settlement was finality-confirmed `success`. {@link settlement}
|
|
461
|
-
* carries the confirmed effects.
|
|
462
|
-
* - `false` — nothing was signed, or the chain rejected the settlement. The
|
|
463
|
-
* money is still in the pool.
|
|
464
|
-
* - `'unknown'` — a signature left this process and execute/finality did not
|
|
465
|
-
* resolve. The money may have moved. A caller that treats this as `false`
|
|
466
|
-
* and retries will pay twice. `if (!result.paid)` is false for `'unknown'`.
|
|
467
|
-
*/
|
|
468
|
-
paid: boolean | 'unknown';
|
|
469
|
-
body?: unknown;
|
|
470
|
-
receipt?: Receipt | null;
|
|
471
|
-
/** Closed-set code only; never a gateway header/body string. */
|
|
472
|
-
code?: DelegatedPayErrorCode;
|
|
473
|
-
/** Resource HTTP status for a non-402 outcome (preserved, not swallowed). */
|
|
474
|
-
httpStatus?: number;
|
|
475
|
-
/** Classification of a non-402 outcome; see {@link DelegatedPayResponseClass}. */
|
|
476
|
-
responseClass?: DelegatedPayResponseClass;
|
|
477
|
-
/** Caller-safe detail only; never raw RPC/gateway exception text. */
|
|
478
|
-
detail?: string;
|
|
479
|
-
/**
|
|
480
|
-
* On-chain digest when known. For digestless ambiguity after a possible
|
|
481
|
-
* broadcast, set to {@link BROADCAST_UNKNOWN}.
|
|
482
|
-
*/
|
|
483
|
-
txDigest?: string;
|
|
484
|
-
/** payment_id = offer.challengeId; reconcile key on ambiguous outcomes. */
|
|
485
|
-
paymentId?: string;
|
|
486
|
-
/**
|
|
487
|
-
* Settled effects (amount/recipient/status) of a finality-confirmed pay.
|
|
488
|
-
* Present on every `paid` result, including a settled pay whose delivery then
|
|
489
|
-
* failed — that is exactly the case where a caller cannot afford to guess.
|
|
490
|
-
*/
|
|
491
|
-
settlement?: DelegatedPaySettlement;
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Non-secret connection manifest produced at authorize-agent success.
|
|
495
|
-
* Enough for the agent to resolve grant/policy/target without owner SIWS.
|
|
496
|
-
*/
|
|
497
|
-
interface DelegatedSignerConnectionManifest {
|
|
498
|
-
network: string;
|
|
499
|
-
packageId: string;
|
|
500
|
-
poolObjectId: string;
|
|
501
|
-
grantObjectId: string;
|
|
502
|
-
coinType: string;
|
|
503
|
-
delegateAddress: string;
|
|
504
|
-
/** Off-chain grant id for audit; optional. */
|
|
505
|
-
grantId?: string;
|
|
506
|
-
status?: GrantSnapshot['status'];
|
|
507
|
-
policies: GrantSnapshot['policies'];
|
|
508
|
-
/** Grant-level per-signer ceiling (GrantCap max_per_payment). */
|
|
509
|
-
maxPerPayment?: string;
|
|
510
|
-
/** Grant-level session cap. Required positive for open surface. */
|
|
511
|
-
sessionCap?: string;
|
|
512
|
-
/** `open` = full access (no allowlist); omit/scoped = policy-bound. */
|
|
513
|
-
accessMode?: 'scoped' | 'open';
|
|
514
|
-
}
|
|
515
|
-
/** Signer callback: address + sign over full transaction bytes (base64). */
|
|
516
|
-
interface DelegatedKeySigner {
|
|
517
|
-
address: string;
|
|
518
|
-
signTransaction(txBytes: string): Promise<string>;
|
|
519
|
-
/**
|
|
520
|
-
* Personal-message signature (Sui IntentScope.PersonalMessage). Required
|
|
521
|
-
* for the sponsored-gas personal-message path; not used when the agent supplies gas.
|
|
522
|
-
*/
|
|
523
|
-
signPersonalMessage?(message: Uint8Array): Promise<string>;
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Platform gas sponsorship client for BYO personal-message (ADR-0008). The payer obtains
|
|
527
|
-
* a single-use nonce, signs the domain-separated personal-message over the pre-sponsor
|
|
528
|
-
* kind hash, then create+execute the sponsored pay. Does not enable x402
|
|
529
|
-
* transaction-submit for shared_pool.
|
|
530
|
-
*/
|
|
531
|
-
interface SponsoredGasClient {
|
|
532
|
-
/** Gateway origin hosting /api/sponsor (no trailing slash). */
|
|
533
|
-
sponsorUrl: string;
|
|
534
|
-
fetchImpl?: typeof fetch;
|
|
535
|
-
}
|
|
536
|
-
type DelegatedSignerInput = DelegatedKeySigner | Ed25519Keypair | (() => Promise<DelegatedKeySigner> | DelegatedKeySigner);
|
|
537
|
-
/**
|
|
538
|
-
* Authority for one payment. Prefer an in-process snapshot/manifest; a
|
|
539
|
-
* read-only fetch callback may load the same shape from a connection
|
|
540
|
-
* manifest or a read endpoint the agent is allowed to call.
|
|
541
|
-
*/
|
|
542
|
-
type GrantResolutionSource = GrantSnapshot | DelegatedSignerConnectionManifest | (() => Promise<GrantSnapshot | DelegatedSignerConnectionManifest>);
|
|
543
|
-
interface DelegatedPayerSession {
|
|
544
|
-
/** Package id of the published shared_pool module (must match offer). */
|
|
545
|
-
packageId: string;
|
|
546
|
-
/** Network as offer.network expects, e.g. `sui:testnet`. */
|
|
547
|
-
network: string;
|
|
548
|
-
/** Grant + pool + policies for resolveGrantTarget. */
|
|
549
|
-
authority: GrantResolutionSource;
|
|
550
|
-
/** BYO delegated key (keypair or sign callback). Never platform-custodied. */
|
|
551
|
-
signer: DelegatedSignerInput;
|
|
552
|
-
/**
|
|
553
|
-
* Optional re-check immediately before sign (pause/revoke race). Throw to
|
|
554
|
-
* abort. When absent, request-time snapshot is the only pre-sign gate.
|
|
555
|
-
*/
|
|
556
|
-
assertLive?: () => Promise<void>;
|
|
557
|
-
}
|
|
558
|
-
/** Gas coin ref for a complete executable transaction. */
|
|
559
|
-
interface GasPaymentRef {
|
|
560
|
-
objectId: string;
|
|
561
|
-
version: string | number | bigint;
|
|
562
|
-
digest: string;
|
|
563
|
-
}
|
|
564
|
-
interface AgentGasInput {
|
|
565
|
-
budget?: string | number | bigint;
|
|
566
|
-
price?: string | number | bigint;
|
|
567
|
-
payment: GasPaymentRef[];
|
|
568
|
-
/** Defaults to the delegate (sender). */
|
|
569
|
-
owner?: string;
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* Inputs for building a complete executable spend_account::settle_policy_payment transaction
|
|
573
|
-
* (sender + gas + move call). Not kind-only bytes.
|
|
574
|
-
*
|
|
575
|
-
* Pool and grant must carry real initial shared versions from chain (not a
|
|
576
|
-
* hard-coded "1"). Mirror SpendAccountChain.buildPayKind / MCP production path
|
|
577
|
-
* which resolve via getObject / tx.object + client.
|
|
578
|
-
*/
|
|
579
|
-
interface BuildPayTxInput {
|
|
580
|
-
packageId: string;
|
|
581
|
-
delegate: string;
|
|
582
|
-
coinType: string;
|
|
583
|
-
poolObjectId: string;
|
|
584
|
-
grantObjectId: string;
|
|
585
|
-
/** Real initial shared version of the pool object (from chain). */
|
|
586
|
-
poolInitialSharedVersion: string;
|
|
587
|
-
/** Real initial shared version of the grant object (from chain). */
|
|
588
|
-
grantInitialSharedVersion: string;
|
|
589
|
-
/**
|
|
590
|
-
* Initial shared version of the system Clock (0x6). Defaults to genesis
|
|
591
|
-
* version "1" when omitted.
|
|
592
|
-
*/
|
|
593
|
-
clockInitialSharedVersion?: string;
|
|
594
|
-
policyId: number | string;
|
|
595
|
-
targetHash: string;
|
|
596
|
-
amount: string;
|
|
597
|
-
paymentIdHash: Uint8Array;
|
|
598
|
-
termsHash: Uint8Array;
|
|
599
|
-
gas: AgentGasInput;
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Result of an atomic payment-id reserve (exactly-once attempt claim).
|
|
603
|
-
*
|
|
604
|
-
* - reserved: this caller owns the attempt; only then may build/sign/execute
|
|
605
|
-
* - in_flight: another attempt is mid-flight (or complete never landed); do not sign
|
|
606
|
-
* - done: a terminal ok/ambiguous is recorded; return validated prior
|
|
607
|
-
*/
|
|
608
|
-
type PaymentAttemptReserveResult = {
|
|
609
|
-
state: 'reserved';
|
|
610
|
-
} | {
|
|
611
|
-
state: 'in_flight';
|
|
612
|
-
prior?: DelegatedPayResult;
|
|
613
|
-
} | {
|
|
614
|
-
state: 'done';
|
|
615
|
-
prior: DelegatedPayResult;
|
|
616
|
-
};
|
|
617
|
-
/**
|
|
618
|
-
* Durable ledger of payment attempts keyed by payment_id (offer.challengeId).
|
|
619
|
-
* REQUIRED on the pay path. Exactly-once is reserve-before-sign:
|
|
620
|
-
* reserve (atomic) -> build/validate/sign/execute only if reserved -> complete
|
|
621
|
-
* Persistence failure fails closed (never sign without a durable claim).
|
|
622
|
-
*/
|
|
623
|
-
interface PaymentAttemptLedger {
|
|
624
|
-
/**
|
|
625
|
-
* Atomically claim paymentId for this attempt, or report prior/in-flight.
|
|
626
|
-
* Must not interleave another reserve for the same id between check and claim
|
|
627
|
-
* (memory: sync Map check-and-insert; Postgres: INSERT ON CONFLICT DO NOTHING).
|
|
628
|
-
*/
|
|
629
|
-
reserve(paymentId: string, fingerprint: string): Promise<PaymentAttemptReserveResult>;
|
|
630
|
-
/**
|
|
631
|
-
* Write the terminal ok/ambiguous result for a reserved payment_id.
|
|
632
|
-
* After complete, further reserve() calls return state:'done' with prior.
|
|
633
|
-
* Throws on persistence failure (caller must not swallow).
|
|
634
|
-
*/
|
|
635
|
-
complete(paymentId: string, result: DelegatedPayResult): Promise<void>;
|
|
636
|
-
/**
|
|
637
|
-
* Drop an in-flight reservation when no sign/execute happened (clean abort).
|
|
638
|
-
* No-op when the row is already terminal. Optional; missing release leaves
|
|
639
|
-
* in_flight so retries stay fail-closed (ambiguous, no re-sign).
|
|
640
|
-
*/
|
|
641
|
-
release?(paymentId: string): Promise<void>;
|
|
642
|
-
}
|
|
643
|
-
/**
|
|
644
|
-
* Resolve real initial shared versions for pool + grant from chain.
|
|
645
|
-
* Production should call getObject (or SpendAccountChain-equivalent resolution).
|
|
646
|
-
*/
|
|
647
|
-
type ResolveSharedObjectVersions = (ids: {
|
|
648
|
-
poolObjectId: string;
|
|
649
|
-
grantObjectId: string;
|
|
650
|
-
clockObjectId?: string;
|
|
651
|
-
}) => Promise<{
|
|
652
|
-
poolInitialSharedVersion: string;
|
|
653
|
-
grantInitialSharedVersion: string;
|
|
654
|
-
clockInitialSharedVersion?: string;
|
|
655
|
-
}>;
|
|
656
|
-
interface DelegatedPayerDeps {
|
|
657
|
-
fetchImpl?: typeof fetch;
|
|
658
|
-
now?: () => number;
|
|
659
|
-
/**
|
|
660
|
-
* The gateway's HMAC secret, when the caller legitimately holds one — an
|
|
661
|
-
* operator running its own gateway, or a test. Present: offer digests are
|
|
662
|
-
* verified client-side before any ledger, capability, hash, build, or sign.
|
|
663
|
-
*
|
|
664
|
-
* Optional, because an external agent must never be given it: it is the
|
|
665
|
-
* secret that authenticates the gateway to itself, and handing it out makes
|
|
666
|
-
* every holder able to forge offers for every other. An agent without it
|
|
667
|
-
* supplies a {@link SpendIntent} instead. One of the two is REQUIRED — with
|
|
668
|
-
* neither, nothing bounds what the offer may charge, and payment is refused
|
|
669
|
-
* before any ledger, hash, build, or sign.
|
|
670
|
-
*/
|
|
671
|
-
offerSecret?: string;
|
|
672
|
-
/**
|
|
673
|
-
* REQUIRED payment-attempt ledger. Absent ledger refuses to pay (config
|
|
674
|
-
* error) rather than run an unprotected re-sign/rebroadcast path.
|
|
675
|
-
*/
|
|
676
|
-
paymentLedger: PaymentAttemptLedger;
|
|
677
|
-
/**
|
|
678
|
-
* Build a COMPLETE executable pay transaction (delegate sender, gas,
|
|
679
|
-
* real move call). Default uses {@link buildSpendAccountPayTx} with
|
|
680
|
-
* {@link gas}. Must never return kind-only non-executable bytes.
|
|
681
|
-
*/
|
|
682
|
-
buildPayTx?: (input: BuildPayTxInput) => Promise<{
|
|
683
|
-
txBytes: string;
|
|
684
|
-
}>;
|
|
685
|
-
/**
|
|
686
|
-
* Agent-owned gas payment objects for the default full-tx builder.
|
|
687
|
-
* Required when buildPayTx is not injected and sponsor is not set.
|
|
688
|
-
* When both `gas` and `sponsor` are set, `gasMode` selects the path
|
|
689
|
-
* (default: agent gas when `gas` is present, else sponsored).
|
|
690
|
-
*/
|
|
691
|
-
gas?: AgentGasInput;
|
|
692
|
-
/**
|
|
693
|
-
* Sponsored-gas path gated by sponsor personal-message challenge (Phase C2).
|
|
694
|
-
* Alternative to agent-provided gas. Keep agent gas as the other option.
|
|
695
|
-
*/
|
|
696
|
-
sponsor?: SponsoredGasClient;
|
|
697
|
-
/**
|
|
698
|
-
* Force gas path when both agent gas and sponsor are configured.
|
|
699
|
-
* Default: `'agent'` when `gas` has payment objects, else `'sponsored'`.
|
|
700
|
-
*/
|
|
701
|
-
gasMode?: 'agent' | 'sponsored';
|
|
702
|
-
/**
|
|
703
|
-
* Resolve real initial shared versions for pool/grant. Required for the
|
|
704
|
-
* default full-tx builder when {@link sharedObjectVersions} is not set.
|
|
705
|
-
* Mirror SpendAccountChain.buildPayKind (getObject Shared owner / tx.object).
|
|
706
|
-
*/
|
|
707
|
-
resolveSharedObjectVersions?: ResolveSharedObjectVersions;
|
|
708
|
-
/**
|
|
709
|
-
* Pre-resolved pool/grant initial shared versions (tests / offline inject).
|
|
710
|
-
* When set, skips {@link resolveSharedObjectVersions}.
|
|
711
|
-
*/
|
|
712
|
-
sharedObjectVersions?: {
|
|
713
|
-
poolInitialSharedVersion: string;
|
|
714
|
-
grantInitialSharedVersion: string;
|
|
715
|
-
clockInitialSharedVersion?: string;
|
|
716
|
-
};
|
|
717
|
-
/** Submit signed full transaction bytes; returns the broadcast digest. */
|
|
718
|
-
executeTx?: (txBytes: string, signature: string) => Promise<{
|
|
719
|
-
digest: string;
|
|
720
|
-
}>;
|
|
721
|
-
/**
|
|
722
|
-
* Confirm on-chain settlement of a broadcast digest: `success`/`failed`, or
|
|
723
|
-
* `null` while not yet observed. REQUIRED on any pay that reaches settlement —
|
|
724
|
-
* a pay is refused (`FINALITY_UNAVAILABLE`) before signing when this is absent,
|
|
725
|
-
* so a settled tx is never mis-reported as a false `FINALIZATION_TIMEOUT`.
|
|
726
|
-
*/
|
|
727
|
-
getFinalizedTx?: (digest: string) => Promise<{
|
|
728
|
-
status: 'success' | 'failed';
|
|
729
|
-
reason?: string;
|
|
730
|
-
} | null>;
|
|
731
|
-
/**
|
|
732
|
-
* Await the proof-presentation delivery before returning (DEFAULT `true` —
|
|
733
|
-
* today's behavior: the result carries the delivered `body` + `receipt`). Set
|
|
734
|
-
* `false` to return `paid:true` with the digest + settlement summary as soon
|
|
735
|
-
* as settlement is finality-confirmed, skipping the (possibly slow, e.g.
|
|
736
|
-
* ~13s Walrus blob-publish) delivery fetch — the caller presents the proof and
|
|
737
|
-
* fetches the body later. Non-breaking: only an explicit `false` changes flow.
|
|
738
|
-
*/
|
|
739
|
-
awaitDelivery?: boolean;
|
|
740
|
-
/**
|
|
741
|
-
* Server-side logger for internal exception detail. Never surfaces to the
|
|
742
|
-
* caller result (error hygiene).
|
|
743
|
-
*/
|
|
744
|
-
logError?: (message: string, detail?: unknown) => void;
|
|
745
|
-
}
|
|
746
|
-
interface DelegatedPayerConfig {
|
|
747
|
-
/** Gateway origin the resource URL must match. */
|
|
748
|
-
gatewayUrl: string;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* The agent's own statement of what it is buying, checked against the offer
|
|
752
|
-
* before anything else happens.
|
|
753
|
-
*
|
|
754
|
-
* This is the input that lets an agent hold nothing but its key and a gateway
|
|
755
|
-
* URL. The offer HMAC ({@link DelegatedPayerDeps.offerSecret}) proves an offer
|
|
756
|
-
* came from the party that minted it — which, on this path, is the same gateway
|
|
757
|
-
* the agent is paying and reached over TLS at an origin the payer already pins.
|
|
758
|
-
* A gateway that wanted to overcharge never needed to forge its own offer; it
|
|
759
|
-
* could simply mint an honest one for the wrong amount. So the HMAC was never
|
|
760
|
-
* the check that protected the agent from its counterparty, and requiring the
|
|
761
|
-
* agent to hold the gateway's secret to perform it bought nothing while making
|
|
762
|
-
* every agent able to forge offers for every other.
|
|
763
|
-
*
|
|
764
|
-
* What does protect the agent is a ceiling it set itself, which no gateway can
|
|
765
|
-
* see or change. That is this.
|
|
766
|
-
*/
|
|
767
|
-
interface SpendIntent {
|
|
768
|
-
/** Inclusive per-payment ceiling in atomic units, as a decimal string. */
|
|
769
|
-
maxAmount: string;
|
|
770
|
-
/** The coin type the agent is willing to spend. */
|
|
771
|
-
asset: string;
|
|
772
|
-
/**
|
|
773
|
-
* The exact recipient the agent expects to pay. Optional: an agent buying
|
|
774
|
-
* from a catalog usually learns `payTo` from the offer itself. When it does
|
|
775
|
-
* know, pinning it here is the strongest single check available, because
|
|
776
|
-
* recipient substitution — not overspend — is the attack the caps do not stop.
|
|
777
|
-
*/
|
|
778
|
-
recipient?: string;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/**
|
|
782
|
-
* Agent-held settlement wiring for the `pay` tool.
|
|
783
|
-
*
|
|
784
|
-
* The gateway prepares (it holds no key). Settlement needs the delegate key, so
|
|
785
|
-
* it can only happen in the process that holds one. This module answers a single
|
|
786
|
-
* question for a given grant: *is this process that grant's agent, and is it
|
|
787
|
-
* configured to settle?* Any "no" returns null and `pay` falls back to handing
|
|
788
|
-
* back unsigned bytes — the pre-existing behavior.
|
|
789
|
-
*
|
|
790
|
-
* Two conditions gate it, and the first is the security one:
|
|
791
|
-
*
|
|
792
|
-
* 1. **The persisted key must be the key the grant names.** A hosted gateway
|
|
793
|
-
* running this same tool code either holds no credentials file (null) or
|
|
794
|
-
* holds one for some unrelated key (address mismatch → null). It can only
|
|
795
|
-
* settle by already possessing the grant's delegate seed — which is exactly
|
|
796
|
-
* the custody ADR-0015 removed, not a state a flag protects against.
|
|
797
|
-
* 2. **The settlement dependencies must all be present.** A half-configured
|
|
798
|
-
* settler is worse than none: it would sign and then fail to confirm. Missing
|
|
799
|
-
* anything → null, prepare-only.
|
|
800
|
-
*
|
|
801
|
-
* The key is read, never minted. See `loadLocalSigner`.
|
|
802
|
-
*/
|
|
803
|
-
|
|
804
|
-
/** Everything `pay` needs to settle rather than prepare. */
|
|
805
|
-
interface AgentHeldSettlement {
|
|
806
|
-
signer: DelegatedKeySigner;
|
|
807
|
-
getObjectJson: GetObjectJson;
|
|
808
|
-
payerDeps: DelegatedPayerDeps;
|
|
809
|
-
}
|
|
810
|
-
/**
|
|
811
|
-
* Resolve agent-held settlement for one grant, or null to stay prepare-only.
|
|
812
|
-
* Injectable so `createServer` can be driven without touching disk,
|
|
813
|
-
* chain, or environment.
|
|
814
|
-
*/
|
|
815
|
-
type AgentHeldResolver = (cfg: McpConfig, spendAccountPay: McpSpendAccountPayAuth) => AgentHeldSettlement | null;
|
|
816
|
-
/** Test seam: drop the process ledger so suites do not share reservations. */
|
|
817
|
-
declare function resetAgentHeldProcessLedger(): void;
|
|
818
|
-
declare function resolveAgentHeldSettlement(cfg: McpConfig, spendAccountPay: McpSpendAccountPayAuth, env?: NodeJS.ProcessEnv): AgentHeldSettlement | null;
|
|
819
|
-
|
|
820
|
-
/**
|
|
821
|
-
* Canonical live-trace contract.
|
|
822
|
-
*
|
|
823
|
-
* One owner module for every observable MCP / payment / chain fact the live
|
|
824
|
-
* audience view renders. No emitter invents its own event shape: emitters call
|
|
825
|
-
* TraceSink.emit with a TraceEventInput, the dispatcher sanitizes it, and the
|
|
826
|
-
* store persists an append-only TraceEventRecord.
|
|
827
|
-
*
|
|
828
|
-
* Two rules shape everything here:
|
|
829
|
-
*
|
|
830
|
-
* 1. A trace event is *observation*, never authority. It is emitted after a
|
|
831
|
-
* canonical decision returns and can never authorize the next step.
|
|
832
|
-
* 2. The database event id is the canonical display order and is a bigserial.
|
|
833
|
-
* Outside the store it is always a decimal string — a JavaScript number
|
|
834
|
-
* silently loses precision past 2^53 and would corrupt SSE resume.
|
|
835
|
-
*/
|
|
836
|
-
|
|
837
|
-
type TraceSource = 'mcp_wire' | 'suipay' | 'sui';
|
|
838
|
-
type TraceStatus = 'started' | 'ok' | 'warning' | 'error' | 'ambiguous';
|
|
839
|
-
type TraceEventKind = 'mcp_connected' | 'tools_listed' | 'tool_called' | 'tool_result' | 'tool_error' | 'challenge_received' | 'authority_matched' | 'authority_revalidated' | 'sponsor_requested' | 'transaction_sponsored' | 'delegate_signed' | 'transaction_submitted' | 'payment_finalized' | 'proof_presented' | 'upstream_delivered' | 'upstream_delivery_failed' | 'settlement_projected' | 'settlement_projection_failed' | 'receipt_issued' | 'payment_failed' | 'payment_ambiguous';
|
|
840
|
-
interface TraceEventInput {
|
|
841
|
-
traceId: string;
|
|
842
|
-
requestId: string | null;
|
|
843
|
-
buyerAccountId: string;
|
|
844
|
-
connectionId: string;
|
|
845
|
-
at: string;
|
|
846
|
-
source: TraceSource;
|
|
847
|
-
kind: TraceEventKind;
|
|
848
|
-
status: TraceStatus;
|
|
849
|
-
summary: string;
|
|
850
|
-
publicPayload: Record<string, unknown>;
|
|
851
|
-
technicalPayload?: Record<string, unknown>;
|
|
852
|
-
}
|
|
853
|
-
/**
|
|
854
|
-
* Correlation constraints an emitter can attach to one event.
|
|
855
|
-
*
|
|
856
|
-
* `requireSoleActiveRunForBuyer` is the server-side (ADR-0011) fallback's
|
|
857
|
-
* atomicity guard: the event is persisted only if, at append time, that buyer
|
|
858
|
-
* still has exactly one active run. It closes the window between selecting the
|
|
859
|
-
* sole run and appending to it — a second run opening in between makes the
|
|
860
|
-
* append fail closed rather than land on a run that is no longer sole.
|
|
861
|
-
*/
|
|
862
|
-
interface TraceEmitOptions {
|
|
863
|
-
requireSoleActiveRunForBuyer?: string;
|
|
864
|
-
}
|
|
865
|
-
interface TraceSink {
|
|
866
|
-
emit(event: TraceEventInput, options?: TraceEmitOptions): Promise<void>;
|
|
867
|
-
}
|
|
868
|
-
type TraceRunEndReason = 'completed' | 'idle' | 'superseded' | 'event_cap' | 'byte_cap' | 'shutdown';
|
|
869
|
-
interface TraceRun {
|
|
870
|
-
id: string;
|
|
871
|
-
buyerAccountId: string;
|
|
872
|
-
connectionId: string;
|
|
873
|
-
clientName: string | null;
|
|
874
|
-
startedAt: string;
|
|
875
|
-
lastEventAt: string;
|
|
876
|
-
endedAt: string | null;
|
|
877
|
-
endReason: TraceRunEndReason | null;
|
|
878
|
-
/** Persisted events accepted into this run. */
|
|
879
|
-
eventCount: number;
|
|
880
|
-
/** Serialized sanitized payload bytes accepted into this run. */
|
|
881
|
-
payloadBytes: number;
|
|
882
|
-
}
|
|
883
|
-
/** Run selection for one authenticated OAuth connection (implemented in context.ts). */
|
|
884
|
-
interface TraceRunResolver {
|
|
885
|
-
resolveRun(input: {
|
|
886
|
-
buyerAccountId: string;
|
|
887
|
-
connectionId: string;
|
|
888
|
-
jsonRpcMethod: string | null;
|
|
889
|
-
clientName: string | null;
|
|
890
|
-
now: number;
|
|
891
|
-
}): Promise<TraceRun>;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
/**
|
|
895
|
-
* Transparent MCP wire proxy.
|
|
896
|
-
*
|
|
897
|
-
* This module is the *only* place in the system that parses MCP methods and
|
|
898
|
-
* JSON-RPC ids. The gateway authenticates and hands over a run manager and a
|
|
899
|
-
* sink; it never sniffs an MCP body a second time. Payment code emits domain
|
|
900
|
-
* facts, never wire facts. That single-owner rule is what stops two subsystems
|
|
901
|
-
* from disagreeing about which tool call a payment belongs to.
|
|
902
|
-
*
|
|
903
|
-
* Transparency is the top invariant, and it is structural rather than
|
|
904
|
-
* best-effort:
|
|
905
|
-
*
|
|
906
|
-
* - With no runtime, this file is a pass-through and does not touch the
|
|
907
|
-
* request or the response at all.
|
|
908
|
-
* - With a runtime, observation reads `Request.clone()` and `Response.clone()`
|
|
909
|
-
* only. The exact `Response` instance the handler produced is what the caller
|
|
910
|
-
* receives, so byte equality is by construction, not by careful copying.
|
|
911
|
-
* - Response observation is started and deliberately not awaited. A trace
|
|
912
|
-
* store that hangs cannot hold an MCP response open.
|
|
913
|
-
* - The request side cannot be fire-and-forget — the proxy must know the run
|
|
914
|
-
* and the JSON-RPC ids before the handler runs — so it is bounded instead:
|
|
915
|
-
* one deadline over envelope parsing plus run selection, and the same byte
|
|
916
|
-
* cap the response observer uses. A hung store or an oversized body costs
|
|
917
|
-
* the trace, never the request.
|
|
918
|
-
* - Every observation path is wrapped: a hostile body, a failing run manager or
|
|
919
|
-
* a throwing sink degrades to "no trace", never to a changed response.
|
|
920
|
-
*
|
|
921
|
-
* Volume control lives here too. One `tool_called` per JSON-RPC id and one
|
|
922
|
-
* terminal `tool_result` / `tool_error` per id — never one row per SSE frame.
|
|
923
|
-
*/
|
|
924
|
-
|
|
925
|
-
/** Everything the proxy needs to attribute wire facts to one owned run. */
|
|
926
|
-
interface McpTraceRuntime {
|
|
927
|
-
buyerAccountId: string;
|
|
928
|
-
connectionId: string;
|
|
929
|
-
runs: TraceRunResolver;
|
|
930
|
-
sink: TraceSink;
|
|
931
|
-
/**
|
|
932
|
-
* HMAC secret for signed cross-request context. Supplied by the composition
|
|
933
|
-
* root so a published SDK never reads a gateway-only environment variable.
|
|
934
|
-
* Absent means internal hops carry no correlation and the gateway simply
|
|
935
|
-
* emits no linked events.
|
|
936
|
-
*/
|
|
937
|
-
secret?: string | null;
|
|
938
|
-
/** Injected clock; tests pin it, production leaves it out. */
|
|
939
|
-
now?: () => number;
|
|
940
|
-
}
|
|
941
|
-
/** The proxy-resolved context handed down to payment code (Task 5 seams). */
|
|
942
|
-
interface McpTraceContext {
|
|
943
|
-
traceId: string;
|
|
944
|
-
requestId: string | null;
|
|
945
|
-
}
|
|
946
|
-
interface McpTraceHooks {
|
|
947
|
-
runtime: McpTraceRuntime;
|
|
948
|
-
context: McpTraceContext;
|
|
949
|
-
sink: TraceSink;
|
|
950
|
-
}
|
|
951
|
-
/** One JSON-RPC message read off the request side. */
|
|
952
|
-
interface McpEnvelopeEntry {
|
|
953
|
-
method: string | null;
|
|
954
|
-
jsonRpcId: string | number | null;
|
|
955
|
-
/** Canonical, header-safe request id. `null` for notifications. */
|
|
956
|
-
requestId: string | null;
|
|
957
|
-
toolName: string | null;
|
|
958
|
-
toolArguments: unknown;
|
|
959
|
-
clientName: string | null;
|
|
960
|
-
clientVersion: string | null;
|
|
961
|
-
protocolVersion: string | null;
|
|
962
|
-
}
|
|
963
|
-
interface McpEnvelope {
|
|
964
|
-
batch: boolean;
|
|
965
|
-
entries: McpEnvelopeEntry[];
|
|
966
|
-
/** First entry's method — what run selection keys on. */
|
|
967
|
-
method: string | null;
|
|
968
|
-
requestId: string | null;
|
|
969
|
-
clientName: string | null;
|
|
970
|
-
}
|
|
971
|
-
/**
|
|
972
|
-
* Canonical MCP request id.
|
|
973
|
-
*
|
|
974
|
-
* JSON-RPC allows both `7` and `"7"` as distinct ids, and they must stay
|
|
975
|
-
* distinct: correlating a payment to the wrong tool call is worse than not
|
|
976
|
-
* correlating it. Numbers keep their JSON form under `n:`; strings are
|
|
977
|
-
* base64url-encoded under `s:` so an id containing newlines, colons or quotes
|
|
978
|
-
* survives being carried in an HTTP header without escaping games.
|
|
979
|
-
*/
|
|
980
|
-
declare function canonicalMcpRequestId(id: unknown): string | null;
|
|
981
|
-
/**
|
|
982
|
-
* Read the JSON-RPC envelope from a request **clone**.
|
|
983
|
-
*
|
|
984
|
-
* The caller owns cloning; this consumes the body it is given. An unparsable,
|
|
985
|
-
* bodiless or over-cap request yields an empty envelope rather than an error — a
|
|
986
|
-
* malformed request is the transport's problem to answer, not tracing's problem
|
|
987
|
-
* to block.
|
|
988
|
-
*/
|
|
989
|
-
declare function inspectMcpEnvelope(request: Request, maxBytes?: number): Promise<McpEnvelope>;
|
|
990
|
-
interface TraceMcpHttpRequestInput {
|
|
991
|
-
request: Request;
|
|
992
|
-
/**
|
|
993
|
-
* The real MCP handler. Receives the untouched original request, plus the
|
|
994
|
-
* resolved trace context when tracing is live.
|
|
995
|
-
*/
|
|
996
|
-
handle: (request: Request, hooks?: McpTraceHooks) => Promise<Response>;
|
|
997
|
-
runtime?: McpTraceRuntime | null;
|
|
998
|
-
/** Cap on bytes read for observation, request and response. Never unbounded. */
|
|
999
|
-
maxObservedBytes?: number;
|
|
1000
|
-
/**
|
|
1001
|
-
* Deadline for envelope parsing plus run selection, the only trace work that
|
|
1002
|
-
* happens before the handler. Past it the exchange proceeds untraced.
|
|
1003
|
-
*/
|
|
1004
|
-
runSetupTimeoutMs?: number;
|
|
1005
|
-
}
|
|
1006
|
-
/**
|
|
1007
|
-
* Wrap one MCP HTTP exchange in observation.
|
|
1008
|
-
*
|
|
1009
|
-
* The response returned here is the exact object `handle` produced. Nothing on
|
|
1010
|
-
* the observation path can change it, delay it, or prevent it.
|
|
1011
|
-
*/
|
|
1012
|
-
declare function traceMcpHttpRequest(input: TraceMcpHttpRequestInput): Promise<Response>;
|
|
1013
|
-
|
|
1014
|
-
/**
|
|
1015
|
-
* Transport-neutral SuiPay MCP server + tool registry.
|
|
1016
|
-
* Used by stdio (index.ts) and Streamable HTTP (http.ts).
|
|
1017
|
-
* Remote HTTP passes McpAuthContext so tools enforce OAuth scope + shared-pool pay.
|
|
1018
|
-
*/
|
|
1019
|
-
|
|
1020
|
-
declare const PACKAGE_NAME = "@cmdoss/suipay-mcp";
|
|
1021
|
-
declare const TOOLS: readonly [{
|
|
1022
|
-
readonly name: "access_context";
|
|
1023
|
-
readonly description: "Inspect profiles, policies, service targets, spend caps, usage, and lifecycle state enforced for this authenticated SuiPay session. Call before choosing a paid service.";
|
|
1024
|
-
readonly inputSchema: {
|
|
1025
|
-
readonly type: "object";
|
|
1026
|
-
readonly properties: {};
|
|
1027
|
-
};
|
|
1028
|
-
}, {
|
|
1029
|
-
readonly name: "pay";
|
|
1030
|
-
readonly description: "Pay a HTTP resource via shared_pool. The gateway PREPARES an unsigned transaction (it never holds the delegate key). Only a process that holds the delegate key the grant names can settle: it verifies the prepared kind (target, amount, recipient, grant.delegate) and settles through the same path as direct signer mode. Every other process returns a signingRequest to sign locally. Pass recipient and/or maxAmount to state who you intend to pay and what you will spend; both are checked before anything is signed or handed back. Local V1 allowance pay is retired. Use method POST with json to pay for a JSON request body; the body you send is bound into the offer, so it cannot be changed after signing.";
|
|
1031
|
-
readonly inputSchema: {
|
|
1032
|
-
readonly type: "object";
|
|
1033
|
-
readonly properties: {
|
|
1034
|
-
readonly url: {
|
|
1035
|
-
readonly type: "string";
|
|
1036
|
-
readonly description: "Full gateway resource URL.";
|
|
1037
|
-
};
|
|
1038
|
-
readonly method: {
|
|
1039
|
-
readonly type: "string";
|
|
1040
|
-
readonly enum: readonly ["GET", "POST"];
|
|
1041
|
-
readonly description: "HTTP method of the paid request. Defaults to GET.";
|
|
1042
|
-
};
|
|
1043
|
-
readonly json: {
|
|
1044
|
-
readonly type: "object";
|
|
1045
|
-
readonly description: "JSON request body for a POST. Sent as application/json and bound to the payment.";
|
|
1046
|
-
};
|
|
1047
|
-
readonly recipient: {
|
|
1048
|
-
readonly type: "string";
|
|
1049
|
-
readonly description: "Sui address you expect to be paid. The payment is refused, unsigned, if the prepared transaction pays anyone else.";
|
|
1050
|
-
};
|
|
1051
|
-
readonly maxAmount: {
|
|
1052
|
-
readonly type: "string";
|
|
1053
|
-
readonly description: "Atomic ceiling you will spend on this call. The payment is refused, unsigned, if the offer costs more.";
|
|
1054
|
-
};
|
|
1055
|
-
};
|
|
1056
|
-
readonly required: readonly ["url"];
|
|
1057
|
-
};
|
|
1058
|
-
}, {
|
|
1059
|
-
readonly name: "discover";
|
|
1060
|
-
readonly description: "Search SuiPay gateway resources.";
|
|
1061
|
-
readonly inputSchema: {
|
|
1062
|
-
readonly type: "object";
|
|
1063
|
-
readonly properties: {
|
|
1064
|
-
readonly query: {
|
|
1065
|
-
readonly type: "string";
|
|
1066
|
-
readonly description: "Optional service search terms.";
|
|
1067
|
-
};
|
|
1068
|
-
};
|
|
1069
|
-
};
|
|
1070
|
-
}, {
|
|
1071
|
-
readonly name: "receipts";
|
|
1072
|
-
readonly description: "List SuiPay settlement receipts, optionally filtered by challenge id.";
|
|
1073
|
-
readonly inputSchema: {
|
|
1074
|
-
readonly type: "object";
|
|
1075
|
-
readonly properties: {
|
|
1076
|
-
readonly challengeId: {
|
|
1077
|
-
readonly type: "string";
|
|
1078
|
-
readonly description: "Optional payment challenge id.";
|
|
1079
|
-
};
|
|
1080
|
-
};
|
|
1081
|
-
};
|
|
1082
|
-
}, {
|
|
1083
|
-
readonly name: "suipay_login";
|
|
1084
|
-
readonly description: "Mint or reuse the local delegate key (version-2, mode 0600) and open the console with the public address only so the owner can bind a spend-account grant. Stdio only; hosted /mcp never holds a spendable key.";
|
|
1085
|
-
readonly inputSchema: {
|
|
1086
|
-
readonly type: "object";
|
|
1087
|
-
readonly properties: {
|
|
1088
|
-
readonly label: {
|
|
1089
|
-
readonly type: "string";
|
|
1090
|
-
readonly description: "Label shown in SuiPay console.";
|
|
1091
|
-
};
|
|
1092
|
-
readonly gatewayResourceUrl: {
|
|
1093
|
-
readonly type: "string";
|
|
1094
|
-
readonly description: "Gateway resource URL whose 402 defines recipient, asset, and package.";
|
|
1095
|
-
};
|
|
1096
|
-
};
|
|
1097
|
-
};
|
|
1098
|
-
}, {
|
|
1099
|
-
readonly name: "suipay_logout";
|
|
1100
|
-
readonly description: "Remove the local delegate-key credentials file. Missing file is success. Force clears a corrupt file without printing the seed.";
|
|
1101
|
-
readonly inputSchema: {
|
|
1102
|
-
readonly type: "object";
|
|
1103
|
-
readonly properties: {
|
|
1104
|
-
readonly force: {
|
|
1105
|
-
readonly type: "boolean";
|
|
1106
|
-
readonly description: "Remove local credentials even if the file is unreadable.";
|
|
1107
|
-
};
|
|
1108
|
-
};
|
|
1109
|
-
};
|
|
1110
|
-
}];
|
|
1111
|
-
/**
|
|
1112
|
-
* Create a Server with the public SuiPay tool surface registered.
|
|
1113
|
-
*
|
|
1114
|
-
* `trace` is the proxy-resolved run for this HTTP exchange. It is threaded into
|
|
1115
|
-
* tool dependencies so payment code can emit *domain* events, and nothing else:
|
|
1116
|
-
* this wrapper deliberately emits no tool lifecycle of its own, because the
|
|
1117
|
-
* proxy observes the actual JSON-RPC wire and a second source would double-count
|
|
1118
|
-
* every call and disagree on ids.
|
|
1119
|
-
*/
|
|
1120
|
-
interface McpServerOptions {
|
|
1121
|
-
/**
|
|
1122
|
-
* How `pay` finds an agent-held delegate key for the authenticated grant.
|
|
1123
|
-
* Defaults to the persisted local key (`resolveAgentHeldSettlement`), which
|
|
1124
|
-
* returns null on any process that does not hold the key the grant names — so
|
|
1125
|
-
* the default is prepare-only everywhere except the agent's own machine.
|
|
1126
|
-
* Injectable for tests; there is no way to make it hand over a key the grant
|
|
1127
|
-
* does not already authorize.
|
|
1128
|
-
*/
|
|
1129
|
-
resolveAgentHeld?: AgentHeldResolver;
|
|
1130
|
-
}
|
|
1131
|
-
declare function createServer(cfg: McpConfig, auth?: McpAuthContext, trace?: McpTraceHooks, options?: McpServerOptions): Server;
|
|
1132
|
-
|
|
1133
|
-
/**
|
|
1134
|
-
* Streamable HTTP transport for SuiPay MCP.
|
|
1135
|
-
* Stateless per-request (sessionIdGenerator undefined) — same public tools as stdio.
|
|
1136
|
-
* Auth context is required for remote gateway /mcp (bearer resolved upstream).
|
|
1137
|
-
*
|
|
1138
|
-
* The optional trace runtime turns on live observation. It is a pure wrapper:
|
|
1139
|
-
* `traceMcpHttpRequest` reads clones and returns the transport's own Response,
|
|
1140
|
-
* so passing a runtime cannot change what an MCP client sees.
|
|
1141
|
-
*/
|
|
1142
|
-
|
|
1143
|
-
/**
|
|
1144
|
-
* Handle one MCP Streamable HTTP request (initialize, tools/list, tools/call, …).
|
|
1145
|
-
* Creates a fresh transport+server pair per request (stateless mode).
|
|
1146
|
-
*/
|
|
1147
|
-
declare function handleSuipayMcpHttpRequest(req: Request, cfg: McpConfig, auth?: McpAuthContext, trace?: McpTraceRuntime | null, options?: McpServerOptions): Promise<Response>;
|
|
1148
|
-
|
|
1149
|
-
export { type AgentHeldResolver as A, type Dialect as D, type GrantSnapshot as G, type McpConfig as M, PACKAGE_NAME as P, type SpendIntent as S, type TraceSink as T, type DelegatedKeySigner as a, type GetObjectJson as b, type DelegatedPayerSession as c, type DelegatedPayerConfig as d, type DelegatedPayerDeps as e, type DelegatedPayResult as f, type AgentHeldSettlement as g, type McpEnvelope as h, type McpEnvelopeEntry as i, type McpServerOptions as j, type McpTraceContext as k, type McpTraceHooks as l, type McpTraceRuntime as m, TOOLS as n, canonicalMcpRequestId as o, createServer as p, handleSuipayMcpHttpRequest as q, inspectMcpEnvelope as r, loadMcpConfig as s, resetAgentHeldProcessLedger as t, resolveAgentHeldSettlement as u, resolveGrantTarget as v, traceMcpHttpRequest as w };
|