@devlab.group/agent-commerce 2.4.1 → 2.5.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/README.md +115 -15
- package/dist/ap2.d.ts +24 -12
- package/dist/ap2.js +31 -13
- package/dist/ap2.js.map +1 -1
- package/dist/{chunk-DTKU3Z2M.js → chunk-3OTCFFFT.js} +37 -4
- package/dist/chunk-3OTCFFFT.js.map +1 -0
- package/dist/{chunk-QPV3EGJO.js → chunk-4K7FIBJM.js} +25 -4
- package/dist/chunk-4K7FIBJM.js.map +1 -0
- package/dist/{chunk-CXWC5LWM.js → chunk-FKQK5XZA.js} +652 -68
- package/dist/chunk-FKQK5XZA.js.map +1 -0
- package/dist/chunk-GA3O2A7R.js +92 -0
- package/dist/chunk-GA3O2A7R.js.map +1 -0
- package/dist/{chunk-WZW5ORZH.js → chunk-VUCMBGUR.js} +3 -3
- package/dist/{chunk-WZW5ORZH.js.map → chunk-VUCMBGUR.js.map} +1 -1
- package/dist/cli/{ap2-GWSP4LYY.js → ap2-YAPLERSC.js} +34 -15
- package/dist/cli/ap2-YAPLERSC.js.map +1 -0
- package/dist/cli/{chunk-G2JEY7MB.js → chunk-2J2IQQ4X.js} +8 -7
- package/dist/cli/chunk-2J2IQQ4X.js.map +1 -0
- package/dist/cli/chunk-2UPPX3FJ.js +311 -0
- package/dist/cli/chunk-2UPPX3FJ.js.map +1 -0
- package/dist/cli/{chunk-WYOGIANL.js → chunk-4H2QLHQI.js} +4 -4
- package/dist/cli/{chunk-WYOGIANL.js.map → chunk-4H2QLHQI.js.map} +1 -1
- package/dist/cli/{chunk-OZ4LAWBK.js → chunk-5R7DM5LM.js} +25 -4
- package/dist/cli/chunk-5R7DM5LM.js.map +1 -0
- package/dist/cli/chunk-663ALDZA.js +92 -0
- package/dist/cli/chunk-663ALDZA.js.map +1 -0
- package/dist/cli/{chunk-QQ3WY5L3.js → chunk-IDY2735M.js} +36 -104
- package/dist/cli/chunk-IDY2735M.js.map +1 -0
- package/dist/cli/chunk-JFVRG2HH.js +107 -0
- package/dist/cli/chunk-JFVRG2HH.js.map +1 -0
- package/dist/cli/chunk-M7NXVRU5.js +8 -0
- package/dist/cli/{chunk-ITWNSS2B.js.map → chunk-M7NXVRU5.js.map} +1 -1
- package/dist/cli/chunk-NIU5EMSB.js +119 -0
- package/dist/cli/chunk-NIU5EMSB.js.map +1 -0
- package/dist/cli/{chunk-TNMLDPUO.js → chunk-QA2OPHBF.js} +655 -70
- package/dist/cli/chunk-QA2OPHBF.js.map +1 -0
- package/dist/cli/{chunk-GJIMDMYT.js → chunk-QLUCNPRT.js} +404 -161
- package/dist/cli/chunk-QLUCNPRT.js.map +1 -0
- package/dist/cli/chunk-SYQLJXIU.js +105 -0
- package/dist/cli/chunk-SYQLJXIU.js.map +1 -0
- package/dist/cli/{chunk-3MGAJ5FX.js → chunk-VJ4EO4LE.js} +3 -3
- package/dist/cli/{chunk-3MGAJ5FX.js.map → chunk-VJ4EO4LE.js.map} +1 -1
- package/dist/cli/{chunk-PIMFPCNZ.js → chunk-Z34UMZBB.js} +234 -85
- package/dist/cli/chunk-Z34UMZBB.js.map +1 -0
- package/dist/cli/config-BWFMN2ZB.js +12 -0
- package/dist/cli/{config-UI4EDG4L.js.map → config-BWFMN2ZB.js.map} +1 -1
- package/dist/cli/index.js +258 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-PGBRWZVA.js → mcp-KZEMXLHR.js} +5 -4
- package/dist/cli/mcp-KZEMXLHR.js.map +1 -0
- package/dist/cli/{near-5AY3HWYF.js → near-U6365VFX.js} +15 -4
- package/dist/cli/near-U6365VFX.js.map +1 -0
- package/dist/cli/payment-providers-SZL36H3Y.js +6 -0
- package/dist/cli/payment-providers-SZL36H3Y.js.map +1 -0
- package/dist/cli/{provider-I2ESL6RS.js → provider-6TKB5ADJ.js} +26 -15
- package/dist/cli/provider-6TKB5ADJ.js.map +1 -0
- package/dist/cli/receipts-ZGLJWMQG.js +8 -0
- package/dist/cli/receipts-ZGLJWMQG.js.map +1 -0
- package/dist/cli/reconcile-IC22MJD5.js +4 -0
- package/dist/cli/reconcile-IC22MJD5.js.map +1 -0
- package/dist/cli/{run-JK4ERPJV.js → run-ZTYPQI4D.js} +151 -115
- package/dist/cli/run-ZTYPQI4D.js.map +1 -0
- package/dist/cli/svm-KDSPDFJG.js +48 -0
- package/dist/cli/svm-KDSPDFJG.js.map +1 -0
- package/dist/cli/{x402-7WBFZQXV.js → x402-WLYBLODI.js} +10 -9
- package/dist/cli/x402-WLYBLODI.js.map +1 -0
- package/dist/index.d.ts +112 -12
- package/dist/index.js +948 -157
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -2
- package/dist/mcp.js +1 -1
- package/dist/mpp.js +20 -10
- package/dist/mpp.js.map +1 -1
- package/dist/{near-D6C42VPE.js → near-FH7HPZV3.js} +15 -4
- package/dist/near-FH7HPZV3.js.map +1 -0
- package/dist/{protocol-adapter-C9odYl6l.d.ts → protocol-adapter-DEXpdp8m.d.ts} +102 -48
- package/dist/{runtime-Cl_BLVZV.d.ts → runtime-Dz2fSO-P.d.ts} +220 -2
- package/dist/svm-KNC3PHMS.js +48 -0
- package/dist/svm-KNC3PHMS.js.map +1 -0
- package/dist/x402.js +5 -5
- package/package.json +1 -1
- package/dist/authorization-DjAecwuW.d.ts +0 -115
- package/dist/chunk-CXWC5LWM.js.map +0 -1
- package/dist/chunk-DTKU3Z2M.js.map +0 -1
- package/dist/chunk-KA2AX5FH.js +0 -44
- package/dist/chunk-KA2AX5FH.js.map +0 -1
- package/dist/chunk-QPV3EGJO.js.map +0 -1
- package/dist/cli/ap2-GWSP4LYY.js.map +0 -1
- package/dist/cli/chunk-G2JEY7MB.js.map +0 -1
- package/dist/cli/chunk-GJIMDMYT.js.map +0 -1
- package/dist/cli/chunk-ITWNSS2B.js +0 -8
- package/dist/cli/chunk-OSTCU6ZK.js +0 -44
- package/dist/cli/chunk-OSTCU6ZK.js.map +0 -1
- package/dist/cli/chunk-OZ4LAWBK.js.map +0 -1
- package/dist/cli/chunk-PIMFPCNZ.js.map +0 -1
- package/dist/cli/chunk-QQ3WY5L3.js.map +0 -1
- package/dist/cli/chunk-TNMLDPUO.js.map +0 -1
- package/dist/cli/config-UI4EDG4L.js +0 -11
- package/dist/cli/mcp-PGBRWZVA.js.map +0 -1
- package/dist/cli/near-5AY3HWYF.js.map +0 -1
- package/dist/cli/provider-I2ESL6RS.js.map +0 -1
- package/dist/cli/run-JK4ERPJV.js.map +0 -1
- package/dist/cli/svm-3MMYFPC7.js +0 -33
- package/dist/cli/svm-3MMYFPC7.js.map +0 -1
- package/dist/cli/x402-7WBFZQXV.js.map +0 -1
- package/dist/near-D6C42VPE.js.map +0 -1
- package/dist/svm-QEUAUNPQ.js +0 -33
- package/dist/svm-QEUAUNPQ.js.map +0 -1
|
@@ -67,6 +67,75 @@ interface AdapterDescriptor {
|
|
|
67
67
|
readonly unsupported?: readonly string[];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
interface CommerceReceipt {
|
|
71
|
+
readonly id: string;
|
|
72
|
+
readonly requestId: string;
|
|
73
|
+
/** Optional for compatibility with rows written before 2.5.0 */
|
|
74
|
+
readonly transactionId?: string;
|
|
75
|
+
readonly resourceId: string;
|
|
76
|
+
/** Absent for free resources */
|
|
77
|
+
readonly payment?: PaymentResult;
|
|
78
|
+
/**
|
|
79
|
+
* Present only when the resource required authorization. A method and a digest,
|
|
80
|
+
* so the receipt records that consent existed without storing the proof.
|
|
81
|
+
*/
|
|
82
|
+
readonly authorization?: AuthorizationRecord;
|
|
83
|
+
readonly deliveredAt: IsoTimestamp;
|
|
84
|
+
readonly backendStatus: number;
|
|
85
|
+
readonly durationMs?: number;
|
|
86
|
+
readonly protocol?: string;
|
|
87
|
+
/** Non-secret summary only, never a sensitive backend body */
|
|
88
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
89
|
+
}
|
|
90
|
+
/** Record of a single payment authorization seen by the gateway */
|
|
91
|
+
interface PaymentAttempt {
|
|
92
|
+
readonly id: string;
|
|
93
|
+
readonly requestId: string;
|
|
94
|
+
/** Optional for compatibility with rows written before 2.5.0 */
|
|
95
|
+
readonly transactionId?: string;
|
|
96
|
+
readonly resourceId: string;
|
|
97
|
+
readonly provider: string;
|
|
98
|
+
/** Unique across the store; see `PaymentResult.replayKey` */
|
|
99
|
+
readonly replayKey: string;
|
|
100
|
+
/**
|
|
101
|
+
* State of the authorization, as far as the gateway can prove it.
|
|
102
|
+
*
|
|
103
|
+
* `settlement-uncertain` means settlement was attempted and no verdict came
|
|
104
|
+
* back (RPC timeout, dropped connection, a facilitator that accepted the
|
|
105
|
+
* transfer and lost the response). The transfer may or may not have
|
|
106
|
+
* happened, so the attempt is unresolved rather than terminal and needs
|
|
107
|
+
* evidence from the chain, not a retry. `externalReference` holds the
|
|
108
|
+
* broadcast transaction hash when one is known.
|
|
109
|
+
*
|
|
110
|
+
* The execution pipeline never writes `failed`: a throw out of `settle()`
|
|
111
|
+
* never proves that nothing moved. It stays in the union because existing
|
|
112
|
+
* databases hold rows with that status.
|
|
113
|
+
*/
|
|
114
|
+
readonly status: 'reserved' | 'verified' | 'settled' | 'rejected' | 'failed' | 'settlement-uncertain';
|
|
115
|
+
readonly amount: string;
|
|
116
|
+
readonly currency: string;
|
|
117
|
+
readonly payer?: string;
|
|
118
|
+
readonly payee?: string;
|
|
119
|
+
readonly externalReference?: string;
|
|
120
|
+
readonly rejectionReason?: string;
|
|
121
|
+
/** Records how an unresolved attempt became `settled` or `rejected` after its request ended */
|
|
122
|
+
readonly resolution?: PaymentAttemptResolution;
|
|
123
|
+
readonly createdAt: IsoTimestamp;
|
|
124
|
+
readonly updatedAt: IsoTimestamp;
|
|
125
|
+
}
|
|
126
|
+
/** Who resolved an attempt, manually or by reconciliation, and why */
|
|
127
|
+
interface PaymentAttemptResolution {
|
|
128
|
+
readonly method: 'reconcile' | 'manual';
|
|
129
|
+
/** Caller-supplied identity; the admin token does not identify an individual */
|
|
130
|
+
readonly actor: string;
|
|
131
|
+
readonly reason: string;
|
|
132
|
+
readonly at: IsoTimestamp;
|
|
133
|
+
/** For `manual`, an unverified reference supplied by the operator */
|
|
134
|
+
readonly externalReference?: string;
|
|
135
|
+
/** Public chain facts only */
|
|
136
|
+
readonly evidence?: Readonly<Record<string, unknown>>;
|
|
137
|
+
}
|
|
138
|
+
|
|
70
139
|
/** HTTP methods a backend handler may use */
|
|
71
140
|
type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
72
141
|
/**
|
|
@@ -157,6 +226,13 @@ interface ResourceRegistry {
|
|
|
157
226
|
* EVM-specific type may appear in this file.
|
|
158
227
|
*/
|
|
159
228
|
|
|
229
|
+
/**
|
|
230
|
+
* `PaymentResult.metadata` key for public coordinates returned by `verify`
|
|
231
|
+
* for later provider reconciliation. Core must store the value unchanged and
|
|
232
|
+
* interpret only `expiresAt`. Never include signatures, payloads or
|
|
233
|
+
* transaction bytes. Experimental: may change in a minor release.
|
|
234
|
+
*/
|
|
235
|
+
declare const RECONCILIATION_METADATA_KEY = "reconciliation";
|
|
160
236
|
/**
|
|
161
237
|
* Provider-native payment challenge, opaque to core. For x402 the `accepts`
|
|
162
238
|
* entries are x402 `PaymentRequirements` objects, passed to protocol adapters
|
|
@@ -263,6 +339,30 @@ interface PaymentVerificationContext {
|
|
|
263
339
|
interface PaymentSettlementContext extends PaymentVerificationContext {
|
|
264
340
|
readonly verification: PaymentResult;
|
|
265
341
|
}
|
|
342
|
+
/** Input to {@link PaymentProvider.reconcile}. Experimental: may change in a minor release */
|
|
343
|
+
interface PaymentReconciliationContext {
|
|
344
|
+
readonly attempt: PaymentAttempt;
|
|
345
|
+
/** Coordinates from `verify`; optional for compatibility with pre-2.5.0 attempts */
|
|
346
|
+
readonly locator?: Readonly<Record<string, unknown>>;
|
|
347
|
+
readonly now: IsoTimestamp;
|
|
348
|
+
}
|
|
349
|
+
/** Chain evidence for resolving an attempt. Experimental: may change in a minor release */
|
|
350
|
+
interface PaymentReconciliationResult {
|
|
351
|
+
/**
|
|
352
|
+
* Report `settled` only with a final transfer record for this authorization.
|
|
353
|
+
* Report `not-settled` only when a state read proves it unused after it can
|
|
354
|
+
* no longer land; missing logs or receipts are insufficient. Otherwise,
|
|
355
|
+
* report `unknown`.
|
|
356
|
+
*/
|
|
357
|
+
readonly outcome: 'settled' | 'not-settled' | 'unknown';
|
|
358
|
+
/** A machine-readable token, such as `not_final` */
|
|
359
|
+
readonly reason: string;
|
|
360
|
+
readonly externalReference?: string;
|
|
361
|
+
/** Public chain facts only */
|
|
362
|
+
readonly evidence?: Readonly<Record<string, unknown>>;
|
|
363
|
+
/** For `unknown`, the earliest time a different answer is possible, if known */
|
|
364
|
+
readonly retryAfter?: IsoTimestamp;
|
|
365
|
+
}
|
|
266
366
|
/**
|
|
267
367
|
* Contract every payment rail implements. Implementations must be
|
|
268
368
|
* non-custodial: they orchestrate an external payment protocol and never hold
|
|
@@ -296,6 +396,124 @@ interface PaymentProvider {
|
|
|
296
396
|
* returned result; the pipeline records any throw as settlement-uncertain.
|
|
297
397
|
*/
|
|
298
398
|
settle(context: PaymentSettlementContext): Promise<PaymentResult>;
|
|
399
|
+
/**
|
|
400
|
+
* Read chain evidence for an attempt with an unknown outcome. Implementations
|
|
401
|
+
* must not write, broadcast or call a facilitator. Providers without this
|
|
402
|
+
* hook require manual resolution. Experimental: may change in a minor release.
|
|
403
|
+
*/
|
|
404
|
+
reconcile?(context: PaymentReconciliationContext): Promise<PaymentReconciliationResult>;
|
|
405
|
+
health(): Promise<AdapterHealth>;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Canonical authorization model. FROZEN CONTRACT.
|
|
410
|
+
*
|
|
411
|
+
* Payment proves that funds moved; authorization proves that the human behind
|
|
412
|
+
* the agent approved this exact purchase. A valid authorization gates
|
|
413
|
+
* settlement but never unlocks a paid resource on its own and never moves
|
|
414
|
+
* money, so a resource that requires one still needs a payment proof.
|
|
415
|
+
*
|
|
416
|
+
* Core decides that a resource requires authorization and when the pipeline
|
|
417
|
+
* checks it. Authorization providers decide how a submission is parsed,
|
|
418
|
+
* verified and bound to the purchase. No AP2, SD-JWT or JWT type may appear in
|
|
419
|
+
* this file.
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Opaque authorization proof supplied by the buyer's client. Over HTTP it
|
|
424
|
+
* arrives as base64url JSON in the `Agent-Authorization` header; over MCP and
|
|
425
|
+
* A2A it is the same `{ method, payload }` object in the reserved
|
|
426
|
+
* `_authorization` input field.
|
|
427
|
+
*
|
|
428
|
+
* `payload` is kept byte for byte from the wire. It may hold signed or
|
|
429
|
+
* encoding-sensitive provider data, so transport adapters must not normalize
|
|
430
|
+
* it.
|
|
431
|
+
*/
|
|
432
|
+
interface AuthorizationSubmission {
|
|
433
|
+
readonly method: AuthorizationMethodName;
|
|
434
|
+
readonly payload: string;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* What a buyer must present, advertised with the payment challenge so a client
|
|
438
|
+
* learns before it pays that a payment proof alone will not do. The gateway
|
|
439
|
+
* never issues the authorization; it names the method, the spec version it
|
|
440
|
+
* verifies against and the payload profile it expects.
|
|
441
|
+
*/
|
|
442
|
+
interface AuthorizationRequirement {
|
|
443
|
+
readonly method: AuthorizationMethodName;
|
|
444
|
+
readonly version: string;
|
|
445
|
+
readonly profile?: string;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Safe audit identity of an authorization, fit for a receipt. `reference` is a
|
|
449
|
+
* digest, because a receipt outlives its request and a stored proof would be a
|
|
450
|
+
* spendable secret at rest.
|
|
451
|
+
*/
|
|
452
|
+
interface AuthorizationRecord {
|
|
453
|
+
readonly method: AuthorizationMethodName;
|
|
454
|
+
readonly reference: string;
|
|
455
|
+
/** Safe audit summary only. Never the proof, its disclosures, or PII */
|
|
456
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* A verified, reserved authorization. `reservationId` is the handle the
|
|
460
|
+
* pipeline consumes, releases or marks uncertain once the payment resolves. It
|
|
461
|
+
* stays out of `AuthorizationRecord` because a handle is not an audit fact.
|
|
462
|
+
*/
|
|
463
|
+
interface AuthorizationVerification extends AuthorizationRecord {
|
|
464
|
+
readonly status: 'verified';
|
|
465
|
+
readonly reservationId: string;
|
|
466
|
+
}
|
|
467
|
+
/** Input to {@link AuthorizationProvider.verifyAndReserve} */
|
|
468
|
+
interface AuthorizationVerificationContext {
|
|
469
|
+
readonly requestId: string;
|
|
470
|
+
readonly resourceId: string;
|
|
471
|
+
/**
|
|
472
|
+
* The validated resource input with reserved fields stripped: the same value
|
|
473
|
+
* the merchant backend is called with. A provider that binds a proof to the
|
|
474
|
+
* request hashes it, so it excludes `_payment`, `_authorization`, the request
|
|
475
|
+
* id and transport metadata.
|
|
476
|
+
*/
|
|
477
|
+
readonly input: unknown;
|
|
478
|
+
readonly submission: AuthorizationSubmission;
|
|
479
|
+
/** The resolved price and destination the proof must match */
|
|
480
|
+
readonly requirement: PaymentRequirement;
|
|
481
|
+
}
|
|
482
|
+
/** Input to {@link AuthorizationProvider.consume}, `release` and `markUncertain` */
|
|
483
|
+
interface AuthorizationFinalizeContext {
|
|
484
|
+
readonly requestId: string;
|
|
485
|
+
readonly resourceId: string;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Contract every authorization method implements.
|
|
489
|
+
*
|
|
490
|
+
* The lifecycle straddles settlement: a proof is reserved before funds move, so
|
|
491
|
+
* a replay cannot race it, and its fate is known only afterwards. A reservation
|
|
492
|
+
* is released only after a failure that provably moved no money. Anything
|
|
493
|
+
* ambiguous is marked uncertain, because a proof handed back after a settlement
|
|
494
|
+
* that may have landed can be spent twice.
|
|
495
|
+
*/
|
|
496
|
+
interface AuthorizationProvider {
|
|
497
|
+
readonly name: AuthorizationMethodName;
|
|
498
|
+
readonly descriptor: AdapterDescriptor;
|
|
499
|
+
/** What a buyer must present, advertised with the payment challenge */
|
|
500
|
+
readonly requirement: AuthorizationRequirement;
|
|
501
|
+
/**
|
|
502
|
+
* Verify a submission against the resolved purchase and atomically reserve it
|
|
503
|
+
* against reuse. Throws a `CommerceError` with an `AUTHORIZATION_*` code,
|
|
504
|
+
* never a payment code; a verifier or store outage is
|
|
505
|
+
* `AUTHORIZATION_PROVIDER_UNAVAILABLE`, not the buyer's fault.
|
|
506
|
+
*/
|
|
507
|
+
verifyAndReserve(context: AuthorizationVerificationContext): Promise<AuthorizationVerification>;
|
|
508
|
+
/** Mark a reservation permanently spent. Called after settlement succeeds */
|
|
509
|
+
consume(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
510
|
+
/** Return a reservation to unused. Only for failures that moved no funds */
|
|
511
|
+
release(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
512
|
+
/**
|
|
513
|
+
* Settlement threw, so whether funds moved is unknown: neither spend the
|
|
514
|
+
* reservation nor hand it back, and flag it for an operator
|
|
515
|
+
*/
|
|
516
|
+
markUncertain(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
299
517
|
health(): Promise<AdapterHealth>;
|
|
300
518
|
}
|
|
301
519
|
|
|
@@ -328,5 +546,5 @@ interface IdGenerator {
|
|
|
328
546
|
}
|
|
329
547
|
declare const systemClock: Clock;
|
|
330
548
|
|
|
331
|
-
export { NOOP_LOGGER as N,
|
|
332
|
-
export type {
|
|
549
|
+
export { RECONCILIATION_METADATA_KEY as M, NOOP_LOGGER as N, systemClock as O, DEFAULT_BACKEND_TIMEOUT_MS as t, PAYMENT_METHOD_NAMES as u, PROTOCOL_NAMES as v };
|
|
550
|
+
export type { AuthorizationProvider as A, BackendHandler as B, Clock as C, DecimalAmount as D, PaymentRequirement as E, PaymentResult as F, PaymentSettlementContext as G, PaymentVerificationContext as H, IsoTimestamp as I, JsonSchema as J, Pricing as K, Logger as L, PaymentMethodName as P, ResourceRegistry as R, AuthorizationRequirement as a, CommerceResource as b, PaymentSubmission as c, AuthorizationSubmission as d, ProtocolName as e, AuthorizationRecord as f, PaymentAttempt as g, CommerceReceipt as h, PaymentAttemptResolution as i, AdapterDescriptor as j, AdapterHealth as k, PaymentProvider as l, IdGenerator as m, AdapterHealthComponent as n, AuthorizationFinalizeContext as o, AuthorizationMethodName as p, AuthorizationVerification as q, AuthorizationVerificationContext as r, BackendMethod as s, PaymentChallenge as w, PaymentContext as x, PaymentReconciliationContext as y, PaymentReconciliationResult as z };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LOCATOR_VERSION, computeSvmReplayKey } from './chunk-GA3O2A7R.js';
|
|
2
|
+
import { isRecord } from './chunk-2CJNA7MS.js';
|
|
3
|
+
import { getAddressEncoder, getProgramDerivedAddress, address, getCompiledTransactionMessageDecoder } from '@solana/kit';
|
|
4
|
+
import { decodeTransactionFromPayload, transactionMessageHash } from '@x402/svm';
|
|
5
|
+
|
|
6
|
+
var MAX_TRANSACTION_BASE64 = 1644;
|
|
7
|
+
var ASSOCIATED_TOKEN_PROGRAM = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
8
|
+
async function associatedTokenAccount(owner, mint, tokenProgram) {
|
|
9
|
+
const encoder = getAddressEncoder();
|
|
10
|
+
const [account] = await getProgramDerivedAddress({
|
|
11
|
+
programAddress: address(ASSOCIATED_TOKEN_PROGRAM),
|
|
12
|
+
seeds: [owner, tokenProgram, mint].map((key) => encoder.encode(address(key)))
|
|
13
|
+
});
|
|
14
|
+
return account;
|
|
15
|
+
}
|
|
16
|
+
function inspectSvmPayload(payload, network) {
|
|
17
|
+
if (!isRecord(payload)) return "invalid_exact_svm_payload_transaction";
|
|
18
|
+
const transaction = payload["transaction"];
|
|
19
|
+
if (typeof transaction !== "string" || transaction.length > MAX_TRANSACTION_BASE64) {
|
|
20
|
+
return "invalid_exact_svm_payload_transaction";
|
|
21
|
+
}
|
|
22
|
+
let messageHash;
|
|
23
|
+
let recentBlockhash;
|
|
24
|
+
try {
|
|
25
|
+
const decoded = decodeTransactionFromPayload({ transaction });
|
|
26
|
+
messageHash = transactionMessageHash(decoded);
|
|
27
|
+
recentBlockhash = getCompiledTransactionMessageDecoder().decode(
|
|
28
|
+
decoded.messageBytes
|
|
29
|
+
).lifetimeToken;
|
|
30
|
+
} catch {
|
|
31
|
+
return "invalid_exact_svm_payload_transaction_could_not_be_decoded";
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
replayKey: computeSvmReplayKey({ network, messageHash }),
|
|
35
|
+
locator: { v: LOCATOR_VERSION, network, messageHash, recentBlockhash }
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function messageHashOf(transaction) {
|
|
39
|
+
try {
|
|
40
|
+
return transactionMessageHash(decodeTransactionFromPayload({ transaction }));
|
|
41
|
+
} catch {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { associatedTokenAccount, inspectSvmPayload, messageHashOf };
|
|
47
|
+
//# sourceMappingURL=svm-KNC3PHMS.js.map
|
|
48
|
+
//# sourceMappingURL=svm-KNC3PHMS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/payments/x402/svm.ts"],"names":[],"mappings":";;;;;AAsBA,IAAM,sBAAA,GAAyB,IAAA;AAE/B,IAAM,wBAAA,GAA2B,8CAAA;AAMjC,eAAsB,sBAAA,CACpB,KAAA,EACA,IAAA,EACA,YAAA,EACiB;AACjB,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,CAAC,OAAO,CAAA,GAAI,MAAM,wBAAA,CAAyB;AAAA,IAC/C,cAAA,EAAgB,QAAQ,wBAAwB,CAAA;AAAA,IAChD,KAAA,EAAO,CAAC,KAAA,EAAO,YAAA,EAAc,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,KAAQ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAC,CAAC;AAAA,GAC7E,CAAA;AACD,EAAA,OAAO,OAAA;AACT;AAOO,SAAS,iBAAA,CACd,SACA,OAAA,EAC8F;AAC9F,EAAA,IAAI,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG,OAAO,uCAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,QAAQ,aAAa,CAAA;AACzC,EAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,IAAY,WAAA,CAAY,SAAS,sBAAA,EAAwB;AAClF,IAAA,OAAO,uCAAA;AAAA,EACT;AACA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,eAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,4BAAA,CAA6B,EAAE,WAAA,EAAa,CAAA;AAC5D,IAAA,WAAA,GAAc,uBAAuB,OAAO,CAAA;AAC5C,IAAA,eAAA,GAAkB,sCAAqC,CAAE,MAAA;AAAA,MACvD,OAAA,CAAQ;AAAA,KACV,CAAE,aAAA;AAAA,EACJ,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,4DAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,mBAAA,CAAoB,EAAE,OAAA,EAAS,aAAa,CAAA;AAAA,IACvD,SAAS,EAAE,CAAA,EAAG,eAAA,EAAiB,OAAA,EAAS,aAAa,eAAA;AAAgB,GACvE;AACF;AAMO,SAAS,cAAc,WAAA,EAAyC;AACrE,EAAA,IAAI;AACF,IAAA,OAAO,sBAAA,CAAuB,4BAAA,CAA6B,EAAE,WAAA,EAAa,CAAC,CAAA;AAAA,EAC7E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF","file":"svm-KNC3PHMS.js","sourcesContent":["/**\n * Solana `exact` payload inspection with bounded decoding, replay identity and\n * reconciliation coordinates. The provider loads this module, including its\n * `@x402/svm` and `@solana/kit` imports, when a Solana offer is configured.\n *\n * The facilitator checks the transaction itself: the fee payer, signatures,\n * instruction layout, mint, recipient token account and amount, and a\n * simulation. Its smart-wallet path accepts layouts the gateway could not\n * parse, so the gateway does not read the transfer.\n */\nimport {\n address,\n getAddressEncoder,\n getCompiledTransactionMessageDecoder,\n getProgramDerivedAddress,\n} from '@solana/kit';\nimport { decodeTransactionFromPayload, transactionMessageHash } from '@x402/svm';\nimport { isRecord } from '../../core/is-record';\nimport { LOCATOR_VERSION } from './locator';\nimport { computeSvmReplayKey } from './replay-key';\n\n// A Solana transaction fits a 1232-byte packet, which is 1644 base64 characters\nconst MAX_TRANSACTION_BASE64 = 1644;\n\nconst ASSOCIATED_TOKEN_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';\n\n/**\n * The associated token account of `owner` for `mint`, where the SDK client\n * sends a Solana `exact` payment. Its transaction cannot create the account.\n */\nexport async function associatedTokenAccount(\n owner: string,\n mint: string,\n tokenProgram: string,\n): Promise<string> {\n const encoder = getAddressEncoder();\n const [account] = await getProgramDerivedAddress({\n programAddress: address(ASSOCIATED_TOKEN_PROGRAM),\n seeds: [owner, tokenProgram, mint].map((key) => encoder.encode(address(key))),\n });\n return account;\n}\n\n/**\n * Returns the Solana `exact` replay key and locator, or an SDK refusal reason\n * for a missing, oversized or undecodable transaction. The provider adds the\n * payer from the facilitator's verdict when a usable address is available.\n */\nexport function inspectSvmPayload(\n payload: unknown,\n network: string,\n): { readonly replayKey: string; readonly locator: Readonly<Record<string, unknown>> } | string {\n if (!isRecord(payload)) return 'invalid_exact_svm_payload_transaction';\n const transaction = payload['transaction'];\n if (typeof transaction !== 'string' || transaction.length > MAX_TRANSACTION_BASE64) {\n return 'invalid_exact_svm_payload_transaction';\n }\n let messageHash: string;\n let recentBlockhash: string;\n try {\n const decoded = decodeTransactionFromPayload({ transaction });\n messageHash = transactionMessageHash(decoded);\n recentBlockhash = getCompiledTransactionMessageDecoder().decode(\n decoded.messageBytes,\n ).lifetimeToken;\n } catch {\n return 'invalid_exact_svm_payload_transaction_could_not_be_decoded';\n }\n return {\n replayKey: computeSvmReplayKey({ network, messageHash }),\n locator: { v: LOCATOR_VERSION, network, messageHash, recentBlockhash },\n };\n}\n\n/**\n * Returns the message hash of base64 transaction bytes using the same decoder\n * as payment inspection, or undefined if decoding or hashing fails\n */\nexport function messageHashOf(transaction: string): string | undefined {\n try {\n return transactionMessageHash(decodeTransactionFromPayload({ transaction }));\n } catch {\n return undefined;\n }\n}\n"]}
|
package/dist/x402.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { chainIdFromCaip2 } from './chunk-
|
|
2
|
-
export { createX402PaymentProvider, createX402PaymentProvider as x402 } from './chunk-
|
|
3
|
-
export { SUPPORTED_NETWORK_IDS } from './chunk-
|
|
4
|
-
import { CommerceError } from './chunk-
|
|
5
|
-
import './chunk-
|
|
1
|
+
import { chainIdFromCaip2 } from './chunk-FKQK5XZA.js';
|
|
2
|
+
export { createX402PaymentProvider, createX402PaymentProvider as x402 } from './chunk-FKQK5XZA.js';
|
|
3
|
+
export { SUPPORTED_NETWORK_IDS } from './chunk-4K7FIBJM.js';
|
|
4
|
+
import { CommerceError } from './chunk-3OTCFFFT.js';
|
|
5
|
+
import './chunk-GA3O2A7R.js';
|
|
6
6
|
import './chunk-2CJNA7MS.js';
|
|
7
7
|
import { PaymentRequirementsV2Schema } from '@x402/core/schemas';
|
|
8
8
|
import { getAddress, toHex } from 'viem';
|
package/package.json
CHANGED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { g as AuthorizationMethodName, A as AdapterDescriptor, n as PaymentRequirement, c as AdapterHealth } from './runtime-Cl_BLVZV.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Canonical authorization model. FROZEN CONTRACT.
|
|
5
|
-
*
|
|
6
|
-
* Payment proves that funds moved; authorization proves that the human behind
|
|
7
|
-
* the agent approved this exact purchase. A valid authorization gates
|
|
8
|
-
* settlement but never unlocks a paid resource on its own and never moves
|
|
9
|
-
* money, so a resource that requires one still needs a payment proof.
|
|
10
|
-
*
|
|
11
|
-
* Core decides that a resource requires authorization and when the pipeline
|
|
12
|
-
* checks it. Authorization providers decide how a submission is parsed,
|
|
13
|
-
* verified and bound to the purchase. No AP2, SD-JWT or JWT type may appear in
|
|
14
|
-
* this file.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Opaque authorization proof supplied by the buyer's client. Over HTTP it
|
|
19
|
-
* arrives as base64url JSON in the `Agent-Authorization` header; over MCP and
|
|
20
|
-
* A2A it is the same `{ method, payload }` object in the reserved
|
|
21
|
-
* `_authorization` input field.
|
|
22
|
-
*
|
|
23
|
-
* `payload` is kept byte for byte from the wire. It may hold signed or
|
|
24
|
-
* encoding-sensitive provider data, so transport adapters must not normalize
|
|
25
|
-
* it.
|
|
26
|
-
*/
|
|
27
|
-
interface AuthorizationSubmission {
|
|
28
|
-
readonly method: AuthorizationMethodName;
|
|
29
|
-
readonly payload: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* What a buyer must present, advertised with the payment challenge so a client
|
|
33
|
-
* learns before it pays that a payment proof alone will not do. The gateway
|
|
34
|
-
* never issues the authorization; it names the method, the spec version it
|
|
35
|
-
* verifies against and the payload profile it expects.
|
|
36
|
-
*/
|
|
37
|
-
interface AuthorizationRequirement {
|
|
38
|
-
readonly method: AuthorizationMethodName;
|
|
39
|
-
readonly version: string;
|
|
40
|
-
readonly profile?: string;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Safe audit identity of an authorization, fit for a receipt. `reference` is a
|
|
44
|
-
* digest, because a receipt outlives its request and a stored proof would be a
|
|
45
|
-
* spendable secret at rest.
|
|
46
|
-
*/
|
|
47
|
-
interface AuthorizationRecord {
|
|
48
|
-
readonly method: AuthorizationMethodName;
|
|
49
|
-
readonly reference: string;
|
|
50
|
-
/** Safe audit summary only. Never the proof, its disclosures, or PII */
|
|
51
|
-
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* A verified, reserved authorization. `reservationId` is the handle the
|
|
55
|
-
* pipeline consumes, releases or marks uncertain once the payment resolves. It
|
|
56
|
-
* stays out of `AuthorizationRecord` because a handle is not an audit fact.
|
|
57
|
-
*/
|
|
58
|
-
interface AuthorizationVerification extends AuthorizationRecord {
|
|
59
|
-
readonly status: 'verified';
|
|
60
|
-
readonly reservationId: string;
|
|
61
|
-
}
|
|
62
|
-
/** Input to {@link AuthorizationProvider.verifyAndReserve} */
|
|
63
|
-
interface AuthorizationVerificationContext {
|
|
64
|
-
readonly requestId: string;
|
|
65
|
-
readonly resourceId: string;
|
|
66
|
-
/**
|
|
67
|
-
* The validated resource input with reserved fields stripped: the same value
|
|
68
|
-
* the merchant backend is called with. A provider that binds a proof to the
|
|
69
|
-
* request hashes it, so it excludes `_payment`, `_authorization`, the request
|
|
70
|
-
* id and transport metadata.
|
|
71
|
-
*/
|
|
72
|
-
readonly input: unknown;
|
|
73
|
-
readonly submission: AuthorizationSubmission;
|
|
74
|
-
/** The resolved price and destination the proof must match */
|
|
75
|
-
readonly requirement: PaymentRequirement;
|
|
76
|
-
}
|
|
77
|
-
/** Input to {@link AuthorizationProvider.consume}, `release` and `markUncertain` */
|
|
78
|
-
interface AuthorizationFinalizeContext {
|
|
79
|
-
readonly requestId: string;
|
|
80
|
-
readonly resourceId: string;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Contract every authorization method implements.
|
|
84
|
-
*
|
|
85
|
-
* The lifecycle straddles settlement: a proof is reserved before funds move, so
|
|
86
|
-
* a replay cannot race it, and its fate is known only afterwards. A reservation
|
|
87
|
-
* is released only after a failure that provably moved no money. Anything
|
|
88
|
-
* ambiguous is marked uncertain, because a proof handed back after a settlement
|
|
89
|
-
* that may have landed can be spent twice.
|
|
90
|
-
*/
|
|
91
|
-
interface AuthorizationProvider {
|
|
92
|
-
readonly name: AuthorizationMethodName;
|
|
93
|
-
readonly descriptor: AdapterDescriptor;
|
|
94
|
-
/** What a buyer must present, advertised with the payment challenge */
|
|
95
|
-
readonly requirement: AuthorizationRequirement;
|
|
96
|
-
/**
|
|
97
|
-
* Verify a submission against the resolved purchase and atomically reserve it
|
|
98
|
-
* against reuse. Throws a `CommerceError` with an `AUTHORIZATION_*` code,
|
|
99
|
-
* never a payment code; a verifier or store outage is
|
|
100
|
-
* `AUTHORIZATION_PROVIDER_UNAVAILABLE`, not the buyer's fault.
|
|
101
|
-
*/
|
|
102
|
-
verifyAndReserve(context: AuthorizationVerificationContext): Promise<AuthorizationVerification>;
|
|
103
|
-
/** Mark a reservation permanently spent. Called after settlement succeeds */
|
|
104
|
-
consume(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
105
|
-
/** Return a reservation to unused. Only for failures that moved no funds */
|
|
106
|
-
release(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
107
|
-
/**
|
|
108
|
-
* Settlement threw, so whether funds moved is unknown: neither spend the
|
|
109
|
-
* reservation nor hand it back, and flag it for an operator
|
|
110
|
-
*/
|
|
111
|
-
markUncertain(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
|
|
112
|
-
health(): Promise<AdapterHealth>;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export type { AuthorizationProvider as A, AuthorizationRequirement as a, AuthorizationSubmission as b, AuthorizationFinalizeContext as c, AuthorizationRecord as d, AuthorizationVerification as e, AuthorizationVerificationContext as f };
|