@cmdoss/suipay-mcp 0.2.2-dev.9 → 0.3.0-dev.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/dist/http.d.ts CHANGED
@@ -1,11 +1,3 @@
1
- export { r as handleSuipayMcpHttpRequest } from './http-RP-Xlg60.js';
2
- import '@cmdoss/suipay-core/policy/grant-target';
3
- import '@cmdoss/suipay-sdk/mcp/access-context';
4
- import '@cmdoss/suipay-sdk/buyer/settlement-dto';
1
+ export { H as handleSuipayMcpHttpRequest } from './http-BCFfQFIg.js';
5
2
  import '@modelcontextprotocol/sdk/server/index.js';
6
- import '@cmdoss/suipay-sdk/agent-sdk/reads';
7
- import '@cmdoss/suipay-sdk/delegated-signer/payer';
8
- import '@cmdoss/suipay-core/trace/types';
9
- import '@cmdoss/suipay-sdk/protocol/paid-http-request';
10
- import '@cmdoss/suipay-sdk/protocol/types';
11
- import '@cmdoss/suipay-sdk/pay-operation';
3
+ import '@mysten/sui/keypairs/ed25519';
package/dist/http.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleSuipayMcpHttpRequest
3
- } from "./chunk-NDJ7BFI4.js";
3
+ } from "./chunk-FKDC22O6.js";
4
4
  export {
5
5
  handleSuipayMcpHttpRequest
6
6
  };
package/dist/index.d.ts CHANGED
@@ -1,18 +1,15 @@
1
- import { Wallet } from '@cmdoss/suipay-core/chain/types';
2
- import { S as SpendAccountSigningRequest, M as McpConfig, a as McpAuthContext, b as McpTraceHooks, c as SpendAccountPayDeps } from './http-RP-Xlg60.js';
3
- export { A as AgentHeldResolver, d as AgentHeldSettlement, e as MCP_TARGET_PRESETS, f as McpEnvelope, g as McpEnvelopeEntry, h as McpServerOptions, i as McpTarget, j as McpTraceContext, k as McpTraceRuntime, P as PACKAGE_NAME, l as PreparedPayment, m as SpendAccountPrepareResult, n as SpendAccountPrepareSession, T as TOOLS, o as buildSpendAccountPayKind, p as canonicalMcpRequestId, q as createServer, r as handleSuipayMcpHttpRequest, s as inspectMcpEnvelope, t as loadMcpConfig, u as parseMcpTargetFlag, v as prepareSpendAccountPayment, w as resetAgentHeldProcessLedger, x as resolveAgentHeldSettlement, y as resolveMcpTarget, z as sameMcpGateway, B as traceMcpHttpRequest, C as verifySpendAccountPayReconstructs } from './http-RP-Xlg60.js';
4
- import { GetObjectJson, createReader } from '@cmdoss/suipay-sdk/agent-sdk/reads';
5
- import { DelegatedKeySigner, DelegatedPayerSession, DelegatedPayerConfig, DelegatedPayerDeps, SpendIntent, DelegatedPayResult } from '@cmdoss/suipay-sdk/delegated-signer/payer';
6
- import { PaidHttpRequest } from '@cmdoss/suipay-sdk/protocol/paid-http-request';
7
- import { createPayer } from '@cmdoss/suipay-sdk/agent-sdk/delegate-agent';
1
+ import { S as SpendAccountSigningRequest, P as PaidHttpRequest, D as DelegatedKeySigner, G as GetObjectJson, a as DelegatedPayerSession, b as DelegatedPayerConfig, c as DelegatedPayerDeps, d as SpendIntent, e as DelegatedPayResult, f as DelegationScope, C as CodeFor, N as NextAction, g as GrantPolicyBinding, h as PaymentAttemptLedger, i as DelegatedPayerLog, j as PreparedSettlementTerms, X as X402PayProgress, O as Offer, M as McpConfig, k as McpAuthContext, l as McpTraceHooks, m as SpendAccountPayDeps, n as createReader } from './http-BCFfQFIg.js';
2
+ export { A as AgentHeldResolver, o as AgentHeldSettlement, p as MCP_TARGET_PRESETS, q as McpEnvelope, r as McpEnvelopeEntry, s as McpServerOptions, t as McpTarget, u as McpTraceContext, v as McpTraceRuntime, w as PACKAGE_NAME, x as PreparedPayment, y as SpendAccountPrepareResult, z as SpendAccountPrepareSession, T as TOOLS, B as buildSpendAccountPayKind, E as canonicalMcpRequestId, F as createServer, H as handleSuipayMcpHttpRequest, I as inspectMcpEnvelope, J as loadMcpConfig, K as parseMcpTargetFlag, L as prepareSpendAccountPayment, Q as resetAgentHeldProcessLedger, R as resolveAgentHeldSettlement, U as resolveGrantTarget, V as resolveMcpTarget, W as sameMcpGateway, Y as traceMcpHttpRequest, Z as verifySpendAccountPayReconstructs } from './http-BCFfQFIg.js';
3
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
4
+ import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
8
5
  import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
9
- export { resolveGrantTarget } from '@cmdoss/suipay-core/policy/grant-target';
10
- import '@cmdoss/suipay-sdk/mcp/access-context';
11
- import '@cmdoss/suipay-sdk/buyer/settlement-dto';
12
6
  import '@modelcontextprotocol/sdk/server/index.js';
13
- import '@cmdoss/suipay-core/trace/types';
14
- import '@cmdoss/suipay-sdk/protocol/types';
15
- import '@cmdoss/suipay-sdk/pay-operation';
7
+
8
+ /** Holds a key and signs transaction bytes. Never leaves the payer. */
9
+ interface Wallet {
10
+ readonly address: string;
11
+ signTransaction(txBytes: string): Promise<string>;
12
+ }
16
13
 
17
14
  interface SuiPayCredentials {
18
15
  /** 64-hex Ed25519 seed. NEVER logged. */
@@ -113,6 +110,401 @@ declare function settlePreparedMcpPayment(args: {
113
110
  intent?: SpendIntent;
114
111
  }): Promise<DelegatedPayResult>;
115
112
 
113
+ /**
114
+ * The executable settlement a 402 carries so the agent needs no chain access.
115
+ *
116
+ * ADR-0016 §2 says "the server prepares, the agent verifies, the agent signs".
117
+ * ADR-0015 shipped only the first half: the prepare path emitted a placeholder
118
+ * `poolInitialSharedVersion: '1'`, so its bytes described a payment instead of
119
+ * executing one, and an agent still had to make two full-node reads to build
120
+ * something submittable. These bytes are executable — the gateway resolves the
121
+ * real shared-object initial versions before it builds them.
122
+ *
123
+ * This travels ALONGSIDE the offer on the 402 body, never inside it, exactly as
124
+ * `requestSchema` does (`src/gateway/app.ts`). The offer digest is a
125
+ * consensus-relevant wire shape whose fields go on chain via `terms_hash`;
126
+ * adding to it is a protocol change. A prepared settlement authorizes nothing
127
+ * on its own — it is unsigned bytes, worthless until the delegate's key signs
128
+ * them — so it has no business inside a signed digest.
129
+ *
130
+ * Every field here exists to let the agent REBUILD the same transaction kind
131
+ * offline and compare it byte for byte. Nothing here is trusted: see
132
+ * `verifyPreparedPayment` in `src/agent-sdk/verify-prepared-settlement.ts`
133
+ * for what an agent must check before it signs, and why what it can check from
134
+ * the 402 alone is sufficient.
135
+ */
136
+
137
+ /** Current prepared-settlement wire version. Bumped on any shape change. */
138
+ declare const PREPARED_SETTLEMENT_VERSION: 1;
139
+ /**
140
+ * An unsigned, executable settlement transaction plus everything needed to
141
+ * reconstruct it offline.
142
+ *
143
+ * `transactionBytes` is the full sponsored `TransactionData` — gas is already
144
+ * attached by the gateway's sponsor, so this is the ONE thing the agent signs.
145
+ * `transactionKindBytes` is the pre-sponsor programmable-transaction kind: the
146
+ * Move call and nothing else, which is what the agent rebuilds and compares.
147
+ */
148
+ interface PreparedSettlement {
149
+ version: typeof PREPARED_SETTLEMENT_VERSION;
150
+ /** Base64 sponsored `TransactionData`. The agent signs exactly these bytes. */
151
+ transactionBytes: string;
152
+ /** Base64 pre-sponsor transaction kind (the Move call baseline). */
153
+ transactionKindBytes: string;
154
+ /**
155
+ * The address that must sign. Move asserts `ctx.sender() == grant.delegate`,
156
+ * so an agent that checks this equals its own address has the chain enforce
157
+ * that the named grant is one it may draw on — no `getObject` required.
158
+ */
159
+ sender: string;
160
+ /** Deployed `suipay` package the call targets (normalized). */
161
+ packageId: string;
162
+ /** Fully-qualified `package::module::function` the call invokes. */
163
+ moveTarget: string;
164
+ /**
165
+ * Delegation scope: `open` pays an arbitrary recipient, `scoped` an
166
+ * allowlist. This is the SCOPE discriminator (which pay function) — distinct
167
+ * from the x402 eligibility (`SpendAccountGrantKind`) and the budget cap. The
168
+ * `'open'`/`'scoped'` value strings are a frozen wire shape (parsed by
169
+ * `asPreparedSettlement`); the type only names the concept.
170
+ */
171
+ accessMode: DelegationScope;
172
+ /** Shared `Account` the payment debits. */
173
+ poolObjectId: string;
174
+ /** Shared `Grant` naming the delegate. */
175
+ grantObjectId: string;
176
+ /** Real initial shared versions — the gap ADR-0015's placeholder `'1'` left. */
177
+ poolInitialSharedVersion: string;
178
+ grantInitialSharedVersion: string;
179
+ clockInitialSharedVersion: string;
180
+ /** On-chain policy id; `'0'` for an open grant. Decimal string (u64). */
181
+ policyId: string;
182
+ /** Coin type the call spends. Must equal the offer's asset. */
183
+ coinType: string;
184
+ /** Atomic amount the call moves. Must equal the offer's amount. */
185
+ amount: string;
186
+ /** Recipient the call pays. Must equal the offer's payTo. */
187
+ recipient: string;
188
+ /**
189
+ * Fresh lineage (ADR-0043 Option B): settlement is MANDATORY-guarded, so the
190
+ * prepared call always consumes the offer's single-use exclusion marker before
191
+ * funds move. These four let the agent rebuild the SAME guarded kind offline
192
+ * and compare it byte for byte. The `ExclusionDirectory` the offer committed
193
+ * to (from its `registryIdentity`), read-only.
194
+ */
195
+ exclusionDirectoryId: string;
196
+ /** The per-recipient `RecipientRegistry` the marker is claimed in (mutable). */
197
+ recipientRegistryId: string;
198
+ /** Real initial shared version of the exclusion directory. */
199
+ exclusionDirectoryInitialSharedVersion: string;
200
+ /** Real initial shared version of the recipient registry. */
201
+ recipientRegistryInitialSharedVersion: string;
202
+ /** Signed expiry (epoch-ms, decimal string) bound into the guarded settle. */
203
+ expiresAtMs: string;
204
+ /** Absolute URL to POST `{challengeId, signature, body}` to. */
205
+ payUrl: string;
206
+ }
207
+
208
+ /**
209
+ * Connection-manifest → SDK session bridge.
210
+ *
211
+ * The dashboard hands an agent a non-secret "Connection manifest" after it
212
+ * authorizes a delegate key. Historically that manifest could NOT be passed to
213
+ * the SDK: it named the signer `agentAddress` (not `delegateAddress`), the asset
214
+ * by symbol (`"USDC"`, not the full `coinType`), and its policies by off-chain
215
+ * UUID — while the payer needs the full coin type and each policy's NUMERIC
216
+ * on-chain id + target hashes (`GrantPolicyBinding`). This module closes that
217
+ * mismatch two ways:
218
+ *
219
+ * 1. {@link AgentConnectionManifest} — the SDK-consumable shape a corrected
220
+ * console emits directly (delegate address, full coin type, numeric policy
221
+ * ids + target hashes). {@link manifestToSession} turns it, plus an agent
222
+ * key, into a ready `DelegatedPayerSession` — no protocol reverse-engineering
223
+ * and no on-chain lookups.
224
+ *
225
+ * 2. {@link dashboardManifestToAgentManifest} — a bridge from the legacy
226
+ * console shape, resolving asset→coinType and (for scoped grants) UUID→
227
+ * numeric policy binding through injected resolvers.
228
+ *
229
+ * Every failure is a typed, caller-safe error (never a thrown internal): a
230
+ * malformed or legacy manifest that cannot be resolved fails loudly, not
231
+ * silently.
232
+ */
233
+
234
+ /**
235
+ * A manifest or session that cannot be paid from. Nothing was signed, so the
236
+ * money state is always `not_charged`. Branch on `code`; `reason` names the
237
+ * internal check for logs.
238
+ */
239
+ interface ManifestError {
240
+ code: CodeFor<'sdk'>;
241
+ detail: string;
242
+ paymentState: 'not_charged';
243
+ retryable: boolean;
244
+ nextAction: NextAction;
245
+ }
246
+ type ManifestResult<T> = {
247
+ ok: true;
248
+ value: T;
249
+ } | {
250
+ ok: false;
251
+ error: ManifestError;
252
+ };
253
+ /**
254
+ * A manifest policy binding. `onChainPolicyId` is always a validated u64 DECIMAL
255
+ * STRING — never a JS number — so `BigInt(onChainPolicyId)` on the money path
256
+ * (`spend_account::settle_policy`) is exact. A `u64` policy id can exceed `2^53`, past which
257
+ * a JS number loses precision and would bind the WRONG on-chain policy; carrying
258
+ * the string preserves every id exactly.
259
+ */
260
+ type AgentPolicyBinding = Omit<GrantPolicyBinding, 'onChainPolicyId'> & {
261
+ onChainPolicyId: string;
262
+ };
263
+ /** One grant's SDK-consumable binding: everything the payer needs to settle. */
264
+ interface AgentSessionBinding {
265
+ /** Display asset symbol (informational; `coinType` is authoritative). */
266
+ asset: string;
267
+ /** Full coin struct type, e.g. `0x..::usdc::USDC`. Required for pay. */
268
+ coinType: string;
269
+ poolObjectId: string;
270
+ grantObjectId: string;
271
+ /** `open` = capped, no allowlist; `scoped` = policy-bound. */
272
+ accessMode: 'scoped' | 'open';
273
+ /** Grant-level session cap (atomic); null/undefined = unlimited. */
274
+ sessionCap?: string | null;
275
+ /** Grant-level per-payment ceiling (atomic); null/undefined = unlimited. */
276
+ maxPerPayment?: string | null;
277
+ /** On-chain policy ids (u64 strings) + target hashes. Empty for open grants. */
278
+ policies: AgentPolicyBinding[];
279
+ }
280
+ /** Which grant to drive when a manifest carries several. */
281
+ interface SessionSelector {
282
+ grantObjectId?: string;
283
+ asset?: string;
284
+ coinType?: string;
285
+ }
286
+ /** @deprecated Renamed to {@link AgentSessionBinding}. */
287
+ type AgentGrantBinding = AgentSessionBinding;
288
+ /** @deprecated Renamed to {@link SessionSelector}. */
289
+ type GrantSelector = SessionSelector;
290
+
291
+ /**
292
+ * Key + gateway URL → a ready delegated-pay session.
293
+ *
294
+ * This module is the point of `docs/decisions/ADR-0016-delegate-key-sole-agent-input.md`
295
+ * §1. Before it, an agent needed a connection manifest — network, package id,
296
+ * pool id, grant id, caps, expiry — copied out of the console at authorize time
297
+ * and liable to go stale the moment the owner tightened a cap or the operator
298
+ * rotated a package. After it, the agent is handed one secret and one URL, and
299
+ * everything else is resolved from the chain's own projection at startup.
300
+ *
301
+ * The order is forced by the protocol. A bootstrap signature binds `network` and
302
+ * `packageId`, which the gateway reconstructs from its own config, so the agent
303
+ * must know them before it can sign anything that will verify. It learns them
304
+ * from the gateway's public deployment constants — the same two values every 402
305
+ * offer already carries in the clear — and only then signs.
306
+ *
307
+ * Nothing here spends. It resolves authority and hands back a session; the
308
+ * payment is still built and signed later, on this machine, by
309
+ * `payDelegatedSpendAccount` with a key that never leaves the process.
310
+ */
311
+
312
+ /** The gateway's public deployment constants. */
313
+ interface GatewayDeployment {
314
+ network: string;
315
+ packageId: string;
316
+ /**
317
+ * The canonical `ExclusionDirectory` object id, present only while the gateway
318
+ * mints guarded offers. Absent means every offer is unguarded and no registry
319
+ * ever needs resolving.
320
+ *
321
+ * It enables the resolver; it is never resolved against. A guarded settle
322
+ * resolves the directory the OFFER committed to under the HMAC, so a gateway
323
+ * cannot point a payer at a directory of its choosing by answering here.
324
+ */
325
+ exclusionDirectoryObjectId?: string;
326
+ }
327
+
328
+ /**
329
+ * A delegate key and a gateway URL, and the agent can pay.
330
+ *
331
+ * `resolvePayerSession` already turned a key into a pay *session*
332
+ * (ADR-0016 §1). What it did not do was assemble the rest of what
333
+ * `payDelegatedSpendAccount` demands, so a real agent still had to supply four
334
+ * things its key does not carry: the gateway's own HMAC secret, a fullnode
335
+ * connection to confirm settlement, a second fullnode read for live
336
+ * shared-object versions, and a personal-message signer for the sponsor's
337
+ * personal-message challenge, separate from the transaction signer. This module is
338
+ * where those four go.
339
+ *
340
+ * Where each one went, and why that is safe:
341
+ *
342
+ * - **The gateway's HMAC secret is gone, not relocated.** It authenticated the
343
+ * offer's issuer to the agent — but the issuer is the same gateway the agent
344
+ * is paying, reached over TLS at an origin the payer pins, so a gateway that
345
+ * wanted to overcharge never needed to forge its own offer. What replaces it
346
+ * is a bound the gateway cannot see: the agent's own {@link SpendIntent}.
347
+ * - **Both fullnode reads stay with the AGENT**, against a public Sui fullnode
348
+ * derived from the network the gateway reports. They are not proxied through
349
+ * the gateway, because their whole value is that they are independent of it:
350
+ * an agent that asked the gateway whether the gateway's transaction settled
351
+ * would be verifying nothing. The gateway supplies no input here it could
352
+ * not already supply; what it never gains is the ability to answer for the
353
+ * chain.
354
+ * - **The personal-message challenge signer is the same key**, taken from the one
355
+ * keypair the agent already holds. It was never a second credential, only a
356
+ * second callback the caller had to wire.
357
+ *
358
+ * The key never leaves this process, and the gateway never gains the ability to
359
+ * spend: every payment is still built here, checked here against the chain's
360
+ * own view of the grant, and signed here.
361
+ */
362
+
363
+ interface PayerOptions {
364
+ /** Gateway origin, e.g. `https://gateway.suipay.dev`. */
365
+ gatewayUrl: string;
366
+ /**
367
+ * The delegate key. Used for the bootstrap signature, the sponsor
368
+ * personal-message challenge, and the payment signature — one key, three uses, none
369
+ * of which leave this process.
370
+ */
371
+ keypair: Ed25519Keypair;
372
+ /** Which grant to drive when the delegate holds several. */
373
+ select?: GrantSelector;
374
+ /** Injectable fetch (tests / custom transports). Defaults to global `fetch`. */
375
+ fetchImpl?: typeof fetch;
376
+ /**
377
+ * Sui fullnode for the agent's own on-chain reads. Defaults to the public
378
+ * fullnode for the network the gateway reports. An operator running a private
379
+ * network sets it; an agent does not need to.
380
+ */
381
+ fullnodeUrl?: string;
382
+ /**
383
+ * A chain transport to read through, for a caller that already has one (or a
384
+ * test). The seam is the CLIENT, not the individual reads: an option to
385
+ * supply `getSettledTx` directly would let a caller point settlement
386
+ * confirmation at something that is not the chain.
387
+ */
388
+ client?: SuiGrpcClient;
389
+ /**
390
+ * Skip deployment discovery by supplying the constants directly. Same escape
391
+ * hatch `resolvePayerSession` offers.
392
+ */
393
+ deployment?: GatewayDeployment;
394
+ /**
395
+ * Durable payment-attempt ledger. Defaults to an in-process one, which is
396
+ * exactly-once for the lifetime of THIS process. An agent that must survive a
397
+ * restart mid-payment supplies a durable one.
398
+ */
399
+ paymentLedger?: PaymentAttemptLedger;
400
+ /**
401
+ * The gateway's HMAC secret, when the caller legitimately holds one (an
402
+ * operator running its own gateway). An external agent leaves it unset and
403
+ * relies on its spend intent; see {@link SpendIntent}.
404
+ */
405
+ offerSecret?: string;
406
+ /**
407
+ * The canonical `ExclusionDirectory` object id, so this payer can build a
408
+ * GUARDED delegate settle for a guarded offer out of the box.
409
+ *
410
+ * Optional: `createPayer` otherwise takes it from `GET /v1/delegate/deployment`,
411
+ * which discovery already calls, so an agent holding only a key and a gateway
412
+ * URL needs no out-of-band value to pay a guarded offer. Pass it to pin the
413
+ * behaviour against a gateway that does not publish one.
414
+ *
415
+ * When present from either source, `createPayer` constructs the
416
+ * `resolveExclusionRegistry` dependency bound to this payer's own gRPC reader
417
+ * (the same client that reads the grant and confirms settlement), which
418
+ * resolves the per-recipient `RecipientRegistry` from the directory's
419
+ * dynamic-field binding at settle-build time. When absent from BOTH, a guarded
420
+ * offer FAILS CLOSED (BUILD_FAILED) — the payer never builds an unguarded
421
+ * settle, which would reopen the cross-rail double-settle hole and be rejected
422
+ * by the gateway's self-settled verifier anyway. An unguarded offer never
423
+ * resolves a registry, so it is unaffected either way.
424
+ */
425
+ exclusionDirectoryObjectId?: string;
426
+ /** Server-side log port for internal failure detail. Never reaches a result. */
427
+ log?: DelegatedPayerLog;
428
+ }
429
+ /** Result of `payer.pay`. Same shape as the internal settlement result. */
430
+ type PayResult = DelegatedPayResult;
431
+
432
+ /** One paid request. `intent` is what this agent says it is buying. */
433
+ interface PayInput {
434
+ method?: string;
435
+ body?: string | Uint8Array;
436
+ contentType?: string;
437
+ /**
438
+ * Required. Without it nothing bounds what the offer may charge, and the
439
+ * payer refuses — the whole point of the key-only path is that the ceiling
440
+ * comes from the agent, not from a secret it should not hold.
441
+ */
442
+ intent: SpendIntent;
443
+ /**
444
+ * Terms the caller has ALREADY verified, which the offer this payer reads
445
+ * must price exactly or nothing is signed.
446
+ *
447
+ * Distinct from {@link SpendIntent}, and not a replacement for it: `intent`
448
+ * is a ceiling — it refuses an offer that charges MORE — while this is an
449
+ * equality. A caller that showed a person a specific price, or checked a
450
+ * server-prepared kind, is not agreeing to "that or less from anyone in the
451
+ * catalogue"; it is agreeing to one exact payment. The payer fetches its own
452
+ * offer immediately before signing, so without this that final offer is only
453
+ * ceiling-bounded and could legitimately differ from the one the caller
454
+ * verified.
455
+ *
456
+ * Optional, so every existing caller keeps ceiling semantics unchanged.
457
+ */
458
+ preparedTerms?: PreparedSettlementTerms;
459
+ /**
460
+ * Which dialect to pay in. Default `'mpp'`, unchanged: the sponsor executes
461
+ * the pay and the payer presents a finalized proof. `'x402'` signs the pay
462
+ * with the offer's pinned sponsor gas and presents it as `PAYMENT-SIGNATURE`;
463
+ * the gateway co-signs and submits (ADR-0045). Before reserving anything,
464
+ * x402 refuses an open-recipient grant and an offer without the pins.
465
+ */
466
+ dialect?: 'mpp' | 'x402';
467
+ /**
468
+ * x402 only: each step as it happens (built, signed, then presented and
469
+ * answered per presentation). Called synchronously; a throw is logged and
470
+ * never affects the payment.
471
+ */
472
+ onX402Progress?: (event: X402PayProgress) => void;
473
+ }
474
+ interface Payer {
475
+ /** The delegate's own address, derived from the key it holds. */
476
+ address: string;
477
+ /** Deployment constants the gateway published and the bootstrap bound. */
478
+ deployment: GatewayDeployment;
479
+ /** The grant this agent will pay from, as resolved and then verified on chain. */
480
+ grant: AgentGrantBinding;
481
+ /** The assembled session; exposed so a caller can inspect what it will sign with. */
482
+ session: DelegatedPayerSession;
483
+ /** Pay for one resource and return its response. */
484
+ pay(url: string, input: PayInput): Promise<PayResult>;
485
+ /**
486
+ * Verify a 402 prepared settlement against the grant this agent resolved.
487
+ * Always pins {@link Payer.grant} — a settlement drawn on another
488
+ * buyer's grant is refused. Callers with no resolved grant still use
489
+ * {@link verifyPreparedPayment} unpinned.
490
+ */
491
+ verifySettlement(prepared: unknown, offer: Offer): Promise<PreparedSettlement>;
492
+ }
493
+ /**
494
+ * Create a payer from its key and a gateway URL.
495
+ *
496
+ * The call sequence, all of it derivable from those two inputs:
497
+ * 1. `GET /v1/delegate/deployment` — network, package id, and the exclusion
498
+ * directory id when guarded minting is on. All in the clear.
499
+ * 2. `GET /v1/delegate/grants`, signed by the key — the grants naming it.
500
+ * 3. an unsigned `getObject` on the resolved grant, against a public
501
+ * fullnode — the agent's own check that the grant is its own.
502
+ *
503
+ * Typed failure, never a throw: an agent that cannot verify its own authority
504
+ * must refuse to sign, not proceed on the gateway's word.
505
+ */
506
+ declare function createPayer(options: PayerOptions): Promise<ManifestResult<Payer>>;
507
+
116
508
  interface StdioLoginOptions {
117
509
  consoleUrl: string;
118
510
  gatewayUrl: string;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadBootProfile,
3
3
  main
4
- } from "./chunk-LQOZBRH6.js";
4
+ } from "./chunk-W4RIN664.js";
5
5
  import {
6
6
  MCP_TARGET_PRESETS,
7
7
  PACKAGE_NAME,
@@ -26,7 +26,7 @@ import {
26
26
  settlePreparedMcpPayment,
27
27
  traceMcpHttpRequest,
28
28
  verifySpendAccountPayReconstructs
29
- } from "./chunk-NDJ7BFI4.js";
29
+ } from "./chunk-FKDC22O6.js";
30
30
  export {
31
31
  MCP_TARGET_PRESETS,
32
32
  PACKAGE_NAME,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmdoss/suipay-mcp",
3
- "version": "0.2.2-dev.9",
3
+ "version": "0.3.0-dev.0",
4
4
  "type": "module",
5
5
  "description": "SuiPay MCP — pay MPP-gated APIs from a spend-account grant with an agent-held delegate key.",
6
6
  "main": "./dist/index.js",
@@ -37,8 +37,8 @@
37
37
  "tsup": "^8.0.0",
38
38
  "typescript": "^6.0.3",
39
39
  "vitest": "^4.1.10",
40
- "@cmdoss/suipay-core": "0.1.0",
41
- "@cmdoss/suipay-sdk": "0.1.0"
40
+ "@cmdoss/suipay-sdk": "0.1.0",
41
+ "@cmdoss/suipay-core": "0.1.0"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup",