@shroud-fi/x402 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/cjs/client.d.ts +43 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +199 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/constants.d.ts +16 -0
- package/dist/cjs/constants.d.ts.map +1 -0
- package/dist/cjs/constants.js +19 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/errors.d.ts +61 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +82 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/facilitator.d.ts +50 -0
- package/dist/cjs/facilitator.d.ts.map +1 -0
- package/dist/cjs/facilitator.js +106 -0
- package/dist/cjs/facilitator.js.map +1 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/protocol.d.ts +117 -0
- package/dist/cjs/protocol.d.ts.map +1 -0
- package/dist/cjs/protocol.js +39 -0
- package/dist/cjs/protocol.js.map +1 -0
- package/dist/cjs/server.d.ts +49 -0
- package/dist/cjs/server.d.ts.map +1 -0
- package/dist/cjs/server.js +237 -0
- package/dist/cjs/server.js.map +1 -0
- package/dist/cjs/signing.d.ts +93 -0
- package/dist/cjs/signing.d.ts.map +1 -0
- package/dist/cjs/signing.js +170 -0
- package/dist/cjs/signing.js.map +1 -0
- package/dist/cjs/types.d.ts +93 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/client.d.ts +43 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +196 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/constants.d.ts +16 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +16 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/errors.d.ts +61 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +73 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/facilitator.d.ts +50 -0
- package/dist/esm/facilitator.d.ts.map +1 -0
- package/dist/esm/facilitator.js +100 -0
- package/dist/esm/facilitator.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/protocol.d.ts +117 -0
- package/dist/esm/protocol.d.ts.map +1 -0
- package/dist/esm/protocol.js +36 -0
- package/dist/esm/protocol.js.map +1 -0
- package/dist/esm/server.d.ts +49 -0
- package/dist/esm/server.d.ts.map +1 -0
- package/dist/esm/server.js +234 -0
- package/dist/esm/server.js.map +1 -0
- package/dist/esm/signing.d.ts +93 -0
- package/dist/esm/signing.d.ts.map +1 -0
- package/dist/esm/signing.js +131 -0
- package/dist/esm/signing.js.map +1 -0
- package/dist/esm/types.d.ts +93 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +5 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defaults for the @shroud-fi/x402 package.
|
|
3
|
+
*
|
|
4
|
+
* Tight defaults reduce blast radius if a signed payload leaks:
|
|
5
|
+
* - 5-minute validity window matches Coinbase CDP recommendation and the
|
|
6
|
+
* PayAI free tier facilitator's default maxTimeoutSeconds (300).
|
|
7
|
+
* - x402Version pinned to 2 (current shipping spec). We deliberately do NOT
|
|
8
|
+
* implement v1 backward-compat per LOCKED-DECISIONS (whitepaper field
|
|
9
|
+
* names are deprecated).
|
|
10
|
+
*/
|
|
11
|
+
export const X402_VERSION = 2;
|
|
12
|
+
/** Default EIP-3009 authorization validity window (seconds). */
|
|
13
|
+
export const DEFAULT_AUTHORIZATION_TTL_SECS = 300;
|
|
14
|
+
/** Default facilitator `maxTimeoutSeconds` echoed back in PaymentRequired. */
|
|
15
|
+
export const DEFAULT_MAX_TIMEOUT_SECS = 300;
|
|
16
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAU,CAAC;AAEvC,gEAAgE;AAChE,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAElD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 error hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* Privacy invariants:
|
|
5
|
+
* - No amount, value, or balance numbers in any .message string.
|
|
6
|
+
* - No private keys, signature bytes, or nonce bytes in any .message string.
|
|
7
|
+
* - No recipient main wallet addresses in any .message string (stealth
|
|
8
|
+
* addresses are derivable on-chain so leaking them post-payment is fine,
|
|
9
|
+
* but the registrant wallet is identity-bearing — never include it).
|
|
10
|
+
* - All errors extend the same base class so callers can `instanceof X402Error`
|
|
11
|
+
* once at the boundary.
|
|
12
|
+
*/
|
|
13
|
+
export declare class X402Error extends Error {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The 402 challenge body (or its header) could not be parsed / is malformed.
|
|
19
|
+
* Catch-all for "we received something the spec disallows".
|
|
20
|
+
*/
|
|
21
|
+
export declare class X402InvalidChallengeError extends X402Error {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
constructor();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The signed `PAYMENT-SIGNATURE` payload submitted by the client could not be
|
|
27
|
+
* verified against the challenge (signer mismatch, malformed JSON, expired
|
|
28
|
+
* authorization, etc).
|
|
29
|
+
*/
|
|
30
|
+
export declare class X402SignatureVerificationError extends X402Error {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
constructor();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Facilitator HTTP call (verify or settle) failed. Tag identifies the
|
|
36
|
+
* facilitator stage but never carries response body, token amount, or signed
|
|
37
|
+
* payload.
|
|
38
|
+
*/
|
|
39
|
+
export declare class X402FacilitatorError extends X402Error {
|
|
40
|
+
readonly name: string;
|
|
41
|
+
constructor(stage: 'verify' | 'settle' | 'network');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The server's configured asset is not the canonical USDC on the configured
|
|
45
|
+
* chain (or USDC is not deployed on the chain). Hard-fail to avoid signing
|
|
46
|
+
* authorizations against the wrong token.
|
|
47
|
+
*/
|
|
48
|
+
export declare class X402AssetNotSupportedError extends X402Error {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
constructor();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The server's quoted price exceeded the client's `maxPriceAtomic` safety cap,
|
|
54
|
+
* or the verified payload's value did not equal the challenge requirement.
|
|
55
|
+
* The error carries no amount bytes — caller can read inputs separately.
|
|
56
|
+
*/
|
|
57
|
+
export declare class X402AmountMismatchError extends X402Error {
|
|
58
|
+
readonly name: string;
|
|
59
|
+
constructor();
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qBAAa,SAAU,SAAQ,KAAK;IAClC,SAAkB,IAAI,EAAE,MAAM,CAAe;gBACjC,OAAO,EAAE,MAAM;CAG5B;AAED;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACtD,SAAkB,IAAI,EAAE,MAAM,CAA+B;;CAI9D;AAED;;;;GAIG;AACH,qBAAa,8BAA+B,SAAQ,SAAS;IAC3D,SAAkB,IAAI,EAAE,MAAM,CAAoC;;CAInE;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IACjD,SAAkB,IAAI,EAAE,MAAM,CAA0B;gBAC5C,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS;CAGnD;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,SAAS;IACvD,SAAkB,IAAI,EAAE,MAAM,CAAgC;;CAI/D;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACpD,SAAkB,IAAI,EAAE,MAAM,CAA6B;;CAI5D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 error hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* Privacy invariants:
|
|
5
|
+
* - No amount, value, or balance numbers in any .message string.
|
|
6
|
+
* - No private keys, signature bytes, or nonce bytes in any .message string.
|
|
7
|
+
* - No recipient main wallet addresses in any .message string (stealth
|
|
8
|
+
* addresses are derivable on-chain so leaking them post-payment is fine,
|
|
9
|
+
* but the registrant wallet is identity-bearing — never include it).
|
|
10
|
+
* - All errors extend the same base class so callers can `instanceof X402Error`
|
|
11
|
+
* once at the boundary.
|
|
12
|
+
*/
|
|
13
|
+
export class X402Error extends Error {
|
|
14
|
+
name = 'X402Error';
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The 402 challenge body (or its header) could not be parsed / is malformed.
|
|
21
|
+
* Catch-all for "we received something the spec disallows".
|
|
22
|
+
*/
|
|
23
|
+
export class X402InvalidChallengeError extends X402Error {
|
|
24
|
+
name = 'X402InvalidChallengeError';
|
|
25
|
+
constructor() {
|
|
26
|
+
super('Invalid x402 challenge payload');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The signed `PAYMENT-SIGNATURE` payload submitted by the client could not be
|
|
31
|
+
* verified against the challenge (signer mismatch, malformed JSON, expired
|
|
32
|
+
* authorization, etc).
|
|
33
|
+
*/
|
|
34
|
+
export class X402SignatureVerificationError extends X402Error {
|
|
35
|
+
name = 'X402SignatureVerificationError';
|
|
36
|
+
constructor() {
|
|
37
|
+
super('x402 signed payment payload failed verification');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Facilitator HTTP call (verify or settle) failed. Tag identifies the
|
|
42
|
+
* facilitator stage but never carries response body, token amount, or signed
|
|
43
|
+
* payload.
|
|
44
|
+
*/
|
|
45
|
+
export class X402FacilitatorError extends X402Error {
|
|
46
|
+
name = 'X402FacilitatorError';
|
|
47
|
+
constructor(stage) {
|
|
48
|
+
super(`x402 facilitator request failed (stage=${stage})`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The server's configured asset is not the canonical USDC on the configured
|
|
53
|
+
* chain (or USDC is not deployed on the chain). Hard-fail to avoid signing
|
|
54
|
+
* authorizations against the wrong token.
|
|
55
|
+
*/
|
|
56
|
+
export class X402AssetNotSupportedError extends X402Error {
|
|
57
|
+
name = 'X402AssetNotSupportedError';
|
|
58
|
+
constructor() {
|
|
59
|
+
super('x402: requested asset is not supported on the configured chain');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The server's quoted price exceeded the client's `maxPriceAtomic` safety cap,
|
|
64
|
+
* or the verified payload's value did not equal the challenge requirement.
|
|
65
|
+
* The error carries no amount bytes — caller can read inputs separately.
|
|
66
|
+
*/
|
|
67
|
+
export class X402AmountMismatchError extends X402Error {
|
|
68
|
+
name = 'X402AmountMismatchError';
|
|
69
|
+
constructor() {
|
|
70
|
+
super('x402: payment amount exceeds caller cap or does not match challenge');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAChB,IAAI,GAAW,WAAW,CAAC;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IACpC,IAAI,GAAW,2BAA2B,CAAC;IAC7D;QACE,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC1C,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,8BAA+B,SAAQ,SAAS;IACzC,IAAI,GAAW,gCAAgC,CAAC;IAClE;QACE,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC3D,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IAC/B,IAAI,GAAW,sBAAsB,CAAC;IACxD,YAAY,KAAsC;QAChD,KAAK,CAAC,0CAA0C,KAAK,GAAG,CAAC,CAAC;IAC5D,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,0BAA2B,SAAQ,SAAS;IACrC,IAAI,GAAW,4BAA4B,CAAC;IAC9D;QACE,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAC1E,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,SAAS;IAClC,IAAI,GAAW,yBAAyB,CAAC;IAC3D;QACE,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAC/E,CAAC;CACF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facilitator HTTP client.
|
|
3
|
+
*
|
|
4
|
+
* Two endpoints per the x402 spec:
|
|
5
|
+
* - POST /verify — facilitator validates signature + balance + simulation.
|
|
6
|
+
* - POST /settle — facilitator broadcasts the on-chain settlement tx.
|
|
7
|
+
*
|
|
8
|
+
* Privacy invariants:
|
|
9
|
+
* - We forward only the signed PaymentPayload + the PaymentRequirements. The
|
|
10
|
+
* facilitator never receives the recipient's main wallet — only the
|
|
11
|
+
* freshly derived stealth address (the `payTo` field of the requirements).
|
|
12
|
+
* - We never log request/response bodies. Tags are short strings only.
|
|
13
|
+
* - Auth token (if any) is attached as a Bearer header. We never log the
|
|
14
|
+
* full token; tests verify the header is set but redaction is the
|
|
15
|
+
* operator's responsibility upstream.
|
|
16
|
+
*/
|
|
17
|
+
import type { Hex } from 'viem';
|
|
18
|
+
import { type X402FacilitatorConfig } from './protocol.js';
|
|
19
|
+
export interface FacilitatorVerifyResult {
|
|
20
|
+
readonly isValid: boolean;
|
|
21
|
+
readonly invalidReason?: string;
|
|
22
|
+
readonly payer?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface FacilitatorSettleResult {
|
|
25
|
+
readonly success: boolean;
|
|
26
|
+
readonly txHash?: Hex;
|
|
27
|
+
readonly errorReason?: string;
|
|
28
|
+
readonly payer?: string;
|
|
29
|
+
readonly network?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Resolve the facilitator config, defaulting to PayAI free tier. */
|
|
32
|
+
export declare function resolveFacilitator(config: X402FacilitatorConfig | undefined): X402FacilitatorConfig;
|
|
33
|
+
/**
|
|
34
|
+
* Build standard headers for a facilitator request. When an Ed25519 auth
|
|
35
|
+
* token is configured, attach `Authorization: Bearer <token>`. Otherwise
|
|
36
|
+
* the request hits the PayAI free-tier endpoint (no auth required).
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildFacilitatorHeaders(config: X402FacilitatorConfig): Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Call the facilitator's `/verify` endpoint. Returns the parsed verification
|
|
41
|
+
* result. Re-wraps every failure path as a tagged X402FacilitatorError so
|
|
42
|
+
* no upstream response body leaks through.
|
|
43
|
+
*/
|
|
44
|
+
export declare function facilitatorVerify(config: X402FacilitatorConfig, body: unknown, fetchImpl?: typeof fetch): Promise<FacilitatorVerifyResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Call the facilitator's `/settle` endpoint. Returns the parsed settle
|
|
47
|
+
* result (including the on-chain tx hash on success).
|
|
48
|
+
*/
|
|
49
|
+
export declare function facilitatorSettle(config: X402FacilitatorConfig, body: unknown, fetchImpl?: typeof fetch): Promise<FacilitatorSettleResult>;
|
|
50
|
+
//# sourceMappingURL=facilitator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facilitator.d.ts","sourceRoot":"","sources":["../../src/facilitator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAyB,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGlF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAAG,SAAS,GACxC,qBAAqB,CAKvB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,OAAO,EACb,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAsBlC;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,OAAO,EACb,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAsBlC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facilitator HTTP client.
|
|
3
|
+
*
|
|
4
|
+
* Two endpoints per the x402 spec:
|
|
5
|
+
* - POST /verify — facilitator validates signature + balance + simulation.
|
|
6
|
+
* - POST /settle — facilitator broadcasts the on-chain settlement tx.
|
|
7
|
+
*
|
|
8
|
+
* Privacy invariants:
|
|
9
|
+
* - We forward only the signed PaymentPayload + the PaymentRequirements. The
|
|
10
|
+
* facilitator never receives the recipient's main wallet — only the
|
|
11
|
+
* freshly derived stealth address (the `payTo` field of the requirements).
|
|
12
|
+
* - We never log request/response bodies. Tags are short strings only.
|
|
13
|
+
* - Auth token (if any) is attached as a Bearer header. We never log the
|
|
14
|
+
* full token; tests verify the header is set but redaction is the
|
|
15
|
+
* operator's responsibility upstream.
|
|
16
|
+
*/
|
|
17
|
+
import { PAYAI_FACILITATOR_URL } from './protocol.js';
|
|
18
|
+
import { X402FacilitatorError } from './errors.js';
|
|
19
|
+
/** Resolve the facilitator config, defaulting to PayAI free tier. */
|
|
20
|
+
export function resolveFacilitator(config) {
|
|
21
|
+
if (config === undefined) {
|
|
22
|
+
return { url: PAYAI_FACILITATOR_URL };
|
|
23
|
+
}
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build standard headers for a facilitator request. When an Ed25519 auth
|
|
28
|
+
* token is configured, attach `Authorization: Bearer <token>`. Otherwise
|
|
29
|
+
* the request hits the PayAI free-tier endpoint (no auth required).
|
|
30
|
+
*/
|
|
31
|
+
export function buildFacilitatorHeaders(config) {
|
|
32
|
+
const headers = {
|
|
33
|
+
'content-type': 'application/json',
|
|
34
|
+
accept: 'application/json',
|
|
35
|
+
};
|
|
36
|
+
if (config.ed25519AuthToken !== undefined) {
|
|
37
|
+
headers['authorization'] = `Bearer ${config.ed25519AuthToken}`;
|
|
38
|
+
}
|
|
39
|
+
return headers;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Call the facilitator's `/verify` endpoint. Returns the parsed verification
|
|
43
|
+
* result. Re-wraps every failure path as a tagged X402FacilitatorError so
|
|
44
|
+
* no upstream response body leaks through.
|
|
45
|
+
*/
|
|
46
|
+
export async function facilitatorVerify(config, body, fetchImpl = fetch) {
|
|
47
|
+
const url = `${config.url.replace(/\/+$/, '')}/verify`;
|
|
48
|
+
let res;
|
|
49
|
+
try {
|
|
50
|
+
res = await fetchImpl(url, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: buildFacilitatorHeaders(config),
|
|
53
|
+
body: JSON.stringify(body),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new X402FacilitatorError('network');
|
|
58
|
+
}
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
throw new X402FacilitatorError('verify');
|
|
61
|
+
}
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = (await res.json());
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new X402FacilitatorError('verify');
|
|
68
|
+
}
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Call the facilitator's `/settle` endpoint. Returns the parsed settle
|
|
73
|
+
* result (including the on-chain tx hash on success).
|
|
74
|
+
*/
|
|
75
|
+
export async function facilitatorSettle(config, body, fetchImpl = fetch) {
|
|
76
|
+
const url = `${config.url.replace(/\/+$/, '')}/settle`;
|
|
77
|
+
let res;
|
|
78
|
+
try {
|
|
79
|
+
res = await fetchImpl(url, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: buildFacilitatorHeaders(config),
|
|
82
|
+
body: JSON.stringify(body),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new X402FacilitatorError('network');
|
|
87
|
+
}
|
|
88
|
+
if (!res.ok) {
|
|
89
|
+
throw new X402FacilitatorError('settle');
|
|
90
|
+
}
|
|
91
|
+
let parsed;
|
|
92
|
+
try {
|
|
93
|
+
parsed = (await res.json());
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new X402FacilitatorError('settle');
|
|
97
|
+
}
|
|
98
|
+
return parsed;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=facilitator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facilitator.js","sourceRoot":"","sources":["../../src/facilitator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createX402Server } from './server.js';
|
|
2
|
+
export type { X402Server, X402ServerConfig, X402Challenge, X402PaymentRequirements, X402PaymentVerification, } from './server.js';
|
|
3
|
+
export { createX402Client } from './client.js';
|
|
4
|
+
export type { X402Client, X402ClientConfig, X402PaymentResult, } from './client.js';
|
|
5
|
+
export { X402_PAYMENT_REQUIRED_HEADER, X402_PAYMENT_SIGNATURE_HEADER, X402_PAYMENT_RESPONSE_HEADER, X402_SCHEME_EXACT, PAYAI_FACILITATOR_URL, COINBASE_FACILITATOR_URL, } from './protocol.js';
|
|
6
|
+
export type { X402PaymentPayload, X402SchemeId, X402FacilitatorConfig, } from './protocol.js';
|
|
7
|
+
export { X402Error, X402InvalidChallengeError, X402SignatureVerificationError, X402FacilitatorError, X402AssetNotSupportedError, X402AmountMismatchError, } from './errors.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,SAAS,EACT,yBAAyB,EACzB,8BAA8B,EAC9B,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Public surface — @shroud-fi/x402
|
|
2
|
+
// HTTP 402 + stealth-address payment routing for AI agents on Base.
|
|
3
|
+
// See packages/x402/README and docs/research/competitive/x402-spec-and-ecosystem.md.
|
|
4
|
+
// Server side
|
|
5
|
+
export { createX402Server } from './server.js';
|
|
6
|
+
// Client side
|
|
7
|
+
export { createX402Client } from './client.js';
|
|
8
|
+
// Protocol constants + types
|
|
9
|
+
export { X402_PAYMENT_REQUIRED_HEADER, X402_PAYMENT_SIGNATURE_HEADER, X402_PAYMENT_RESPONSE_HEADER, X402_SCHEME_EXACT, PAYAI_FACILITATOR_URL, COINBASE_FACILITATOR_URL, } from './protocol.js';
|
|
10
|
+
// Errors
|
|
11
|
+
export { X402Error, X402InvalidChallengeError, X402SignatureVerificationError, X402FacilitatorError, X402AssetNotSupportedError, X402AmountMismatchError, } from './errors.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,oEAAoE;AACpE,qFAAqF;AAErF,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAS/C,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAO/C,6BAA6B;AAC7B,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAOvB,SAAS;AACT,OAAO,EACL,SAAS,EACT,yBAAyB,EACzB,8BAA8B,EAC9B,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 protocol constants + wire types.
|
|
3
|
+
*
|
|
4
|
+
* v2 spec only. See docs/research/competitive/x402-spec-and-ecosystem.md §1
|
|
5
|
+
* for the canonical field names. v1 (whitepaper, deprecated) names are not
|
|
6
|
+
* accepted by this package.
|
|
7
|
+
*/
|
|
8
|
+
import type { Address, Hex } from 'viem';
|
|
9
|
+
/** Server → client: 402 challenge envelope (raw JSON, no base64 in v2). */
|
|
10
|
+
export declare const X402_PAYMENT_REQUIRED_HEADER: "X-PAYMENT-REQUIRED";
|
|
11
|
+
/**
|
|
12
|
+
* Client → server: signed PaymentPayload (base64-encoded JSON).
|
|
13
|
+
*
|
|
14
|
+
* Canonical name per the v2 spec is `X-PAYMENT`. Older drafts and some
|
|
15
|
+
* SDKs use `X-PAYMENT-SIGNATURE`; we use `X-PAYMENT` to stay aligned with
|
|
16
|
+
* the foundation SDKs (`@x402/fetch`, `@x402/axios`, `@x402/express` all
|
|
17
|
+
* read `X-PAYMENT`).
|
|
18
|
+
*/
|
|
19
|
+
export declare const X402_PAYMENT_SIGNATURE_HEADER: "X-PAYMENT";
|
|
20
|
+
/** Server → client: settlement confirmation (base64-encoded JSON, on 2xx). */
|
|
21
|
+
export declare const X402_PAYMENT_RESPONSE_HEADER: "X-PAYMENT-RESPONSE";
|
|
22
|
+
/** "Exact" scheme — seller knows price up front. Only scheme we support in v1. */
|
|
23
|
+
export declare const X402_SCHEME_EXACT: "exact";
|
|
24
|
+
export type X402SchemeId = typeof X402_SCHEME_EXACT;
|
|
25
|
+
/**
|
|
26
|
+
* PayAI Network facilitator — free tier (≤ 10k settlements/mo) requires no
|
|
27
|
+
* authentication at all. Our default.
|
|
28
|
+
*/
|
|
29
|
+
export declare const PAYAI_FACILITATOR_URL: "https://facilitator.payai.network";
|
|
30
|
+
/**
|
|
31
|
+
* Coinbase CDP facilitator — secondary. Requires CDP API key for use.
|
|
32
|
+
* URL verified against research doc §3 (cdp.coinbase.com/platform/v2/x402).
|
|
33
|
+
*/
|
|
34
|
+
export declare const COINBASE_FACILITATOR_URL: "https://api.cdp.coinbase.com/platform/v2/x402";
|
|
35
|
+
/**
|
|
36
|
+
* The `accepts[N]` entry from a v2 `PaymentRequired` object — the exact shape
|
|
37
|
+
* a client receives over the wire.
|
|
38
|
+
*
|
|
39
|
+
* Field names match the spec verbatim (NOT the v1 whitepaper names — see
|
|
40
|
+
* research doc §10.1 for the drift table).
|
|
41
|
+
*/
|
|
42
|
+
export interface X402PaymentRequirements {
|
|
43
|
+
/** Scheme id; only `'exact'` supported in v1. */
|
|
44
|
+
readonly scheme: X402SchemeId;
|
|
45
|
+
/** CAIP-2 network id, e.g. `'eip155:8453'`. */
|
|
46
|
+
readonly network: string;
|
|
47
|
+
/**
|
|
48
|
+
* Maximum payment amount in token base units (string-encoded to survive
|
|
49
|
+
* uint256). For scheme `exact`, this is the exact required amount.
|
|
50
|
+
*
|
|
51
|
+
* Spec field name: `maxAmountRequired`. We mirror it verbatim.
|
|
52
|
+
*/
|
|
53
|
+
readonly maxAmountRequired: string;
|
|
54
|
+
/** ERC-20 contract address of the asset. */
|
|
55
|
+
readonly asset: Address;
|
|
56
|
+
/**
|
|
57
|
+
* Recipient address. In ShroudFi servers this is ALWAYS a freshly derived
|
|
58
|
+
* stealth address — never the server's main wallet.
|
|
59
|
+
*/
|
|
60
|
+
readonly payTo: Address;
|
|
61
|
+
/** Authorization validity window (seconds). */
|
|
62
|
+
readonly maxTimeoutSeconds: number;
|
|
63
|
+
/** Resource being paid for (URL or pseudo-URL). */
|
|
64
|
+
readonly resource: string;
|
|
65
|
+
/** Optional human-readable description. */
|
|
66
|
+
readonly description?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Scheme-specific extra data. For `exact` on EVM, contains the EIP-712
|
|
69
|
+
* domain `name` + `version` for the asset (so the client can rebuild the
|
|
70
|
+
* domain separator without having to look the token up).
|
|
71
|
+
*/
|
|
72
|
+
readonly extra: {
|
|
73
|
+
readonly name: string;
|
|
74
|
+
readonly version: string;
|
|
75
|
+
/**
|
|
76
|
+
* ShroudFi-specific extension: emitted so a ShroudFi-aware client can
|
|
77
|
+
* relay the Announcement event after settlement. Forward-compatible —
|
|
78
|
+
* non-ShroudFi clients ignore unknown keys.
|
|
79
|
+
*/
|
|
80
|
+
readonly shroudfiAnnouncement?: {
|
|
81
|
+
readonly ephemeralPubKey: Hex;
|
|
82
|
+
readonly viewTag: number;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The signed payload the client sends back in `X-PAYMENT`. EIP-3009
|
|
88
|
+
* `transferWithAuthorization` shape.
|
|
89
|
+
*/
|
|
90
|
+
export interface X402PaymentPayload {
|
|
91
|
+
readonly x402Version: 2;
|
|
92
|
+
readonly scheme: X402SchemeId;
|
|
93
|
+
readonly network: string;
|
|
94
|
+
readonly payload: {
|
|
95
|
+
readonly signature: Hex;
|
|
96
|
+
readonly authorization: {
|
|
97
|
+
readonly from: Address;
|
|
98
|
+
readonly to: Address;
|
|
99
|
+
/** uint256 as string. */
|
|
100
|
+
readonly value: string;
|
|
101
|
+
readonly validAfter: string;
|
|
102
|
+
readonly validBefore: string;
|
|
103
|
+
readonly nonce: Hex;
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Optional facilitator config. When unset, the default is PayAI free-tier
|
|
109
|
+
* (no auth). When `ed25519AuthToken` is provided, the facilitator client
|
|
110
|
+
* attaches `Authorization: Bearer <token>` to every request — caller is
|
|
111
|
+
* responsible for minting the JWT per PayAI's spec (research doc §10.5).
|
|
112
|
+
*/
|
|
113
|
+
export interface X402FacilitatorConfig {
|
|
114
|
+
readonly url: string;
|
|
115
|
+
readonly ed25519AuthToken?: string;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAIzC,2EAA2E;AAC3E,eAAO,MAAM,4BAA4B,EAAG,oBAA6B,CAAC;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,EAAG,WAAoB,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,4BAA4B,EAAG,oBAA6B,CAAC;AAI1E,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,EAAG,OAAgB,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,OAAO,iBAAiB,CAAC;AAIpD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAChC,mCAA4C,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EACnC,+CAAwD,CAAC;AAI3D;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB;;;;WAIG;QACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE;YAC9B,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC;YAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;SAC1B,CAAC;KACH,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;QACxB,QAAQ,CAAC,aAAa,EAAE;YACtB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;YACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;YACrB,yBAAyB;YACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;YAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;YAC7B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;SACrB,CAAC;KACH,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 protocol constants + wire types.
|
|
3
|
+
*
|
|
4
|
+
* v2 spec only. See docs/research/competitive/x402-spec-and-ecosystem.md §1
|
|
5
|
+
* for the canonical field names. v1 (whitepaper, deprecated) names are not
|
|
6
|
+
* accepted by this package.
|
|
7
|
+
*/
|
|
8
|
+
// ─── HTTP header names ───────────────────────────────────────────────────────
|
|
9
|
+
/** Server → client: 402 challenge envelope (raw JSON, no base64 in v2). */
|
|
10
|
+
export const X402_PAYMENT_REQUIRED_HEADER = 'X-PAYMENT-REQUIRED';
|
|
11
|
+
/**
|
|
12
|
+
* Client → server: signed PaymentPayload (base64-encoded JSON).
|
|
13
|
+
*
|
|
14
|
+
* Canonical name per the v2 spec is `X-PAYMENT`. Older drafts and some
|
|
15
|
+
* SDKs use `X-PAYMENT-SIGNATURE`; we use `X-PAYMENT` to stay aligned with
|
|
16
|
+
* the foundation SDKs (`@x402/fetch`, `@x402/axios`, `@x402/express` all
|
|
17
|
+
* read `X-PAYMENT`).
|
|
18
|
+
*/
|
|
19
|
+
export const X402_PAYMENT_SIGNATURE_HEADER = 'X-PAYMENT';
|
|
20
|
+
/** Server → client: settlement confirmation (base64-encoded JSON, on 2xx). */
|
|
21
|
+
export const X402_PAYMENT_RESPONSE_HEADER = 'X-PAYMENT-RESPONSE';
|
|
22
|
+
// ─── Scheme identifiers ──────────────────────────────────────────────────────
|
|
23
|
+
/** "Exact" scheme — seller knows price up front. Only scheme we support in v1. */
|
|
24
|
+
export const X402_SCHEME_EXACT = 'exact';
|
|
25
|
+
// ─── Facilitator URLs ────────────────────────────────────────────────────────
|
|
26
|
+
/**
|
|
27
|
+
* PayAI Network facilitator — free tier (≤ 10k settlements/mo) requires no
|
|
28
|
+
* authentication at all. Our default.
|
|
29
|
+
*/
|
|
30
|
+
export const PAYAI_FACILITATOR_URL = 'https://facilitator.payai.network';
|
|
31
|
+
/**
|
|
32
|
+
* Coinbase CDP facilitator — secondary. Requires CDP API key for use.
|
|
33
|
+
* URL verified against research doc §3 (cdp.coinbase.com/platform/v2/x402).
|
|
34
|
+
*/
|
|
35
|
+
export const COINBASE_FACILITATOR_URL = 'https://api.cdp.coinbase.com/platform/v2/x402';
|
|
36
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,gFAAgF;AAEhF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,4BAA4B,GAAG,oBAA6B,CAAC;AAE1E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,WAAoB,CAAC;AAElE,8EAA8E;AAC9E,MAAM,CAAC,MAAM,4BAA4B,GAAG,oBAA6B,CAAC;AAE1E,gFAAgF;AAEhF,kFAAkF;AAClF,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAgB,CAAC;AAIlD,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,mCAA4C,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,+CAAwD,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 server — challenge generation + signed-payment verification.
|
|
3
|
+
*
|
|
4
|
+
* Privacy invariants enforced here:
|
|
5
|
+
* - Every challenge derives a FRESH stealth address from the recipient's
|
|
6
|
+
* meta-address. The recipient's main wallet NEVER appears in the
|
|
7
|
+
* PaymentRequired body.
|
|
8
|
+
* - The facilitator is only ever shown the stealth `payTo` — same property.
|
|
9
|
+
* - Error paths never include amount values, signature bytes, or the
|
|
10
|
+
* server's spend key.
|
|
11
|
+
*/
|
|
12
|
+
import { type X402PaymentPayload } from './protocol.js';
|
|
13
|
+
import type { X402Challenge, X402PaymentVerification, X402ServerConfig } from './types.js';
|
|
14
|
+
export interface X402Server {
|
|
15
|
+
/**
|
|
16
|
+
* Build a 402 challenge for a given resource. Each call derives a fresh
|
|
17
|
+
* stealth address — calls are deliberately non-idempotent.
|
|
18
|
+
*/
|
|
19
|
+
challenge(args: {
|
|
20
|
+
resource: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
priceAtomic?: bigint;
|
|
23
|
+
}): Promise<X402Challenge>;
|
|
24
|
+
/**
|
|
25
|
+
* Verify a signed payload submitted by the client. Optionally settles via
|
|
26
|
+
* the configured facilitator.
|
|
27
|
+
*
|
|
28
|
+
* When `skipFacilitator: true` is passed, verify returns `valid: true` after
|
|
29
|
+
* signature recovery succeeds and does NOT contact the facilitator. The
|
|
30
|
+
* caller is then responsible for settling the EIP-3009 authorization on-chain
|
|
31
|
+
* itself (e.g. by calling `USDC.transferWithAuthorization` directly through
|
|
32
|
+
* its own walletClient). Use this when the operator runs its own settler EOA
|
|
33
|
+
* and does not want a facilitator in the trust chain — e.g. headless
|
|
34
|
+
* agent-to-agent demos, anon-stack deployments.
|
|
35
|
+
*/
|
|
36
|
+
verify(args: {
|
|
37
|
+
signedPayload: string | X402PaymentPayload;
|
|
38
|
+
challenge: X402Challenge;
|
|
39
|
+
skipFacilitator?: boolean;
|
|
40
|
+
}): Promise<X402PaymentVerification>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build an X402Server bound to a single recipient meta-address + asset.
|
|
44
|
+
*/
|
|
45
|
+
export declare function createX402Server(config: X402ServerConfig): X402Server;
|
|
46
|
+
/** Re-export so consumers don't have to dig into types.ts. */
|
|
47
|
+
export type { X402Challenge, X402PaymentVerification, X402ServerConfig, } from './types.js';
|
|
48
|
+
export type { X402PaymentRequirements } from './protocol.js';
|
|
49
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,eAAe,CAAC;AAMvB,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAmCpB,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,EAAE;QACX,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAAC;QAC3C,SAAS,EAAE,aAAa,CAAC;QACzB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CA2MrE;AAED,8DAA8D;AAC9D,YAAY,EACV,aAAa,EACb,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC"}
|