uvd-x402-sdk 2.74.0 → 2.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +145 -1
  2. package/dist/adapters/index.d.mts +3 -3
  3. package/dist/adapters/index.d.ts +3 -3
  4. package/dist/adapters/index.js.map +1 -1
  5. package/dist/adapters/index.mjs.map +1 -1
  6. package/dist/backend/index.d.mts +350 -54
  7. package/dist/backend/index.d.ts +350 -54
  8. package/dist/backend/index.js +488 -253
  9. package/dist/backend/index.js.map +1 -1
  10. package/dist/backend/index.mjs +477 -254
  11. package/dist/backend/index.mjs.map +1 -1
  12. package/dist/erc8128/index.d.mts +1 -1
  13. package/dist/erc8128/index.d.ts +1 -1
  14. package/dist/{index-BkeMrSHP.d.mts → index-CiRbsqXe.d.mts} +2 -2
  15. package/dist/{index-BQ45e-Xa.d.ts → index-DTXTOEby.d.ts} +2 -2
  16. package/dist/{index-DeJMYEKC.d.mts → index-ZH10otHE.d.mts} +1 -1
  17. package/dist/{index-DeJMYEKC.d.ts → index-ZH10otHE.d.ts} +1 -1
  18. package/dist/index.d.mts +50 -10
  19. package/dist/index.d.ts +50 -10
  20. package/dist/index.js +238 -39
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +228 -40
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/{ows-Z9v4GxOZ.d.mts → ows-CYIVd4xO.d.mts} +1 -1
  25. package/dist/{ows-C-KmORG9.d.ts → ows-DTDixPzO.d.ts} +1 -1
  26. package/dist/providers/algorand/index.d.mts +1 -1
  27. package/dist/providers/algorand/index.d.ts +1 -1
  28. package/dist/providers/algorand/index.js +2 -0
  29. package/dist/providers/algorand/index.js.map +1 -1
  30. package/dist/providers/algorand/index.mjs +2 -0
  31. package/dist/providers/algorand/index.mjs.map +1 -1
  32. package/dist/providers/evm/index.d.mts +1 -1
  33. package/dist/providers/evm/index.d.ts +1 -1
  34. package/dist/providers/evm/index.js.map +1 -1
  35. package/dist/providers/evm/index.mjs.map +1 -1
  36. package/dist/providers/near/index.d.mts +1 -1
  37. package/dist/providers/near/index.d.ts +1 -1
  38. package/dist/providers/near/index.js +2 -0
  39. package/dist/providers/near/index.js.map +1 -1
  40. package/dist/providers/near/index.mjs +2 -0
  41. package/dist/providers/near/index.mjs.map +1 -1
  42. package/dist/providers/solana/index.d.mts +1 -1
  43. package/dist/providers/solana/index.d.ts +1 -1
  44. package/dist/providers/solana/index.js +2 -0
  45. package/dist/providers/solana/index.js.map +1 -1
  46. package/dist/providers/solana/index.mjs +2 -0
  47. package/dist/providers/solana/index.mjs.map +1 -1
  48. package/dist/providers/stellar/index.d.mts +1 -1
  49. package/dist/providers/stellar/index.d.ts +1 -1
  50. package/dist/providers/stellar/index.js +2 -0
  51. package/dist/providers/stellar/index.js.map +1 -1
  52. package/dist/providers/stellar/index.mjs +2 -0
  53. package/dist/providers/stellar/index.mjs.map +1 -1
  54. package/dist/providers/sui/index.d.mts +1 -1
  55. package/dist/providers/sui/index.d.ts +1 -1
  56. package/dist/providers/sui/index.js +2 -0
  57. package/dist/providers/sui/index.js.map +1 -1
  58. package/dist/providers/sui/index.mjs +2 -0
  59. package/dist/providers/sui/index.mjs.map +1 -1
  60. package/dist/providers/xrpl/index.d.mts +1 -1
  61. package/dist/providers/xrpl/index.d.ts +1 -1
  62. package/dist/providers/xrpl/index.js +2 -0
  63. package/dist/providers/xrpl/index.js.map +1 -1
  64. package/dist/providers/xrpl/index.mjs +2 -0
  65. package/dist/providers/xrpl/index.mjs.map +1 -1
  66. package/dist/react/index.d.mts +3 -3
  67. package/dist/react/index.d.ts +3 -3
  68. package/dist/react/index.js.map +1 -1
  69. package/dist/react/index.mjs.map +1 -1
  70. package/dist/utils/index.d.mts +31 -260
  71. package/dist/utils/index.d.ts +31 -260
  72. package/dist/utils/index.js +17 -0
  73. package/dist/utils/index.js.map +1 -1
  74. package/dist/utils/index.mjs +16 -1
  75. package/dist/utils/index.mjs.map +1 -1
  76. package/dist/validation-De3bessL.d.mts +273 -0
  77. package/dist/validation-DsbfDAtV.d.ts +273 -0
  78. package/dist/{wallet-w7BnImDG.d.mts → wallet-0cX9Pw2F.d.mts} +1 -1
  79. package/dist/{wallet-w7BnImDG.d.ts → wallet-0cX9Pw2F.d.ts} +1 -1
  80. package/package.json +1 -1
  81. package/src/backend/facilitator-error.ts +355 -0
  82. package/src/backend/index.ts +536 -263
  83. package/src/dx402.ts +123 -8
  84. package/src/index.ts +17 -0
  85. package/src/utils/index.ts +5 -0
  86. package/src/utils/personal-sign.ts +54 -0
@@ -1,273 +1,44 @@
1
- import { e as X402Header, X as X402Version, C as ChainConfig, f as X402PayloadData, F as X402HeaderV1, I as X402PaymentOption, G as X402HeaderV2, s as PaymentTokenMetadata, B as X402HeaderName, p as PaymentHeaders } from '../index-DeJMYEKC.mjs';
1
+ export { D as DEFAULT_PAYMENT_HEADER, P as PAYMENT_HEADER_NAMES, b as buildTokenMetadata, c as caip2ToChain, a as chainToCAIP2, d as convertX402Header, e as createPaymentHeaders, f as createX402Header, g as createX402V1Header, h as createX402V2Header, i as decodeBase64Utf8, j as decodeX402Header, k as detectX402Version, l as encodeBase64Json, m as encodeBase64Utf8, n as encodeX402Header, o as generatePaymentOptions, p as getPaymentHeader, q as isCAIP2Format, r as parseNetworkIdentifier, s as paymentChallengeFrom, v as validateAmount, t as validateRecipient } from '../validation-De3bessL.mjs';
2
+ import '../index-ZH10otHE.mjs';
2
3
 
3
4
  /**
4
- * uvd-x402-sdk - x402 Protocol Utilities
5
+ * uvd-x402-sdk - EIP-191 personal_sign helpers
5
6
  *
6
- * Utilities for working with x402 v1 and v2 protocols.
7
- * Handles version detection, payload encoding, and CAIP-2 conversions.
8
- */
9
-
10
- /**
11
- * Detect x402 version from a response header or body
12
- *
13
- * @param data - The 402 response data (parsed JSON or header value)
14
- * @returns The detected version (1 or 2)
15
- */
16
- declare function detectX402Version(data: unknown): X402Version;
17
- /**
18
- * Convert chain name to CAIP-2 identifier
19
- *
20
- * @param chainName - Chain name (e.g., 'base', 'solana')
21
- * @returns CAIP-2 identifier (e.g., 'eip155:8453', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
22
- */
23
- declare function chainToCAIP2(chainName: string): string;
24
- /**
25
- * Convert CAIP-2 identifier to chain name
26
- *
27
- * @param caip2 - CAIP-2 identifier
28
- * @returns Chain name or null if unknown
29
- */
30
- declare function caip2ToChain(caip2: string): string | null;
31
- /**
32
- * Parse network identifier from either v1 or v2 format
33
- *
34
- * @param network - Network identifier (v1 string or v2 CAIP-2)
35
- * @returns Normalized chain name
36
- */
37
- declare function parseNetworkIdentifier(network: string): string;
38
- /**
39
- * Encode x402 payload as base64 header value
40
- *
41
- * @param header - The x402 header object
42
- * @returns Base64-encoded string
43
- */
44
- declare function encodeX402Header(header: X402Header): string;
45
- /**
46
- * Decode x402 header from base64 string
47
- *
48
- * @param encoded - Base64-encoded header value
49
- * @returns Parsed x402 header
50
- */
51
- declare function decodeX402Header(encoded: string): X402Header;
52
- /**
53
- * Create x402 v1 header
54
- *
55
- * @param network - Chain name (e.g., 'base')
56
- * @param payload - Network-specific payload
57
- * @returns x402 v1 header object
58
- */
59
- declare function createX402V1Header(network: string, payload: X402PayloadData): X402HeaderV1;
60
- /**
61
- * Create x402 v2 header
62
- *
63
- * @param network - CAIP-2 network identifier
64
- * @param payload - Network-specific payload
65
- * @param accepts - Optional array of payment options
66
- * @returns x402 v2 header object
67
- */
68
- declare function createX402V2Header(network: string, payload: X402PayloadData, accepts?: X402PaymentOption[]): X402HeaderV2;
69
- /**
70
- * Create x402 header with automatic version selection
71
- *
72
- * @param chainConfig - Chain configuration
73
- * @param payload - Network-specific payload
74
- * @param version - Version to use (1, 2, or 'auto')
75
- * @returns x402 header object
76
- */
77
- declare function createX402Header(chainConfig: ChainConfig, payload: X402PayloadData, version?: X402Version | 'auto'): X402Header;
78
- /**
79
- * Generate payment options array for multi-network support
80
- *
81
- * @param chainConfigs - Array of chain configurations
82
- * @param amount - Amount in USDC (e.g., "10.00")
83
- * @param facilitator - Optional facilitator URL override
84
- * @returns Array of x402 v2 payment options
85
- */
86
- declare function generatePaymentOptions(chainConfigs: ChainConfig[], amount: string, facilitator?: string): X402PaymentOption[];
87
- /**
88
- * Check if a network string is in CAIP-2 format
7
+ * Generic recover/verify for an EIP-191 `personal_sign` over an arbitrary
8
+ * string message — the shape a wallet produces for `eth_sign`/`personal_sign`
9
+ * and `cast wallet sign <message>`.
89
10
  *
90
- * @param network - Network identifier
91
- * @returns True if CAIP-2 format
11
+ * This is deliberately NOT the ERC-8128 machinery (`verifyRequest`), which
12
+ * verifies an RFC 9421 SIGNED HTTP REQUEST (method;url;headers;content-digest).
13
+ * A challenge/response flow — a service hands out a nonce string, the wallet
14
+ * signs that string, the service recovers the signer — is a different, simpler
15
+ * case that the ERC-8128 path does not cover. Consumers doing wallet-ownership
16
+ * challenges (e.g. MeshRelay's IRC `VERIFY`/`VERIFY-SIG`) needed this and were
17
+ * each reaching for `ethers.verifyMessage` directly; this centralizes it.
92
18
  */
93
- declare function isCAIP2Format(network: string): boolean;
94
19
  /**
95
- * Convert between x402 v1 and v2 header formats
20
+ * Recover the address that produced an EIP-191 `personal_sign` over `message`.
96
21
  *
97
- * @param header - Source header
98
- * @param targetVersion - Target version
99
- * @returns Converted header
22
+ * @param message - the exact string that was signed
23
+ * @param signature - the 0x-prefixed signature
24
+ * @returns the checksummed recovered address
25
+ * @throws if the signature is malformed (propagates ethers' error)
100
26
  */
101
- declare function convertX402Header(header: X402Header, targetVersion: X402Version): X402Header;
27
+ declare function recoverPersonalSignAddress(message: string, signature: string): string;
102
28
  /**
103
- * Read a 402 payment challenge from wherever the seller put it.
104
- *
105
- * x402 allows BOTH transports and sellers pick freely:
106
- *
107
- * - base64 JSON in the `PAYMENT-REQUIRED` (or `X-PAYMENT-REQUIRED`) header
108
- * - JSON in the response body
29
+ * Whether `signature` over `message` was produced by `expected`.
109
30
  *
110
- * Measured against production on 2026-08-20: of 40 live Bazaar resources,
111
- * **36 of 36 that answered 402 carried the challenge in the header, and none in
112
- * the body**. Worse, sellers like Tenjin use the 402 body for a free preview of
113
- * the paid content — so the body is valid JSON that simply has no `accepts`, and
114
- * a body-only reader parses it happily and finds nothing.
115
- *
116
- * Reads the header first because that is where live sellers put it, and falls
117
- * back to the body so the sellers who use it keep working.
118
- *
119
- * Returns `null` when neither transport carries a challenge — a real "no terms
120
- * here", distinct from a challenge we failed to decode.
121
- */
122
- declare function paymentChallengeFrom(headers: {
123
- get(name: string): string | null;
124
- } | Record<string, string>, body?: unknown): Record<string, unknown> | null;
125
-
126
- /**
127
- * uvd-x402-sdk - Token metadata for payment payloads
128
- *
129
- * An EIP-3009 authorization is signed against a token contract, but the encoded
130
- * payload only carries the signature and the transfer fields. The token itself
131
- * is implicit — the server is expected to already know which asset it asked
132
- * for.
133
- *
134
- * That holds when a resource accepts exactly one token per chain. It breaks as
135
- * soon as it accepts several: a EURC payment and a USDC payment on Base produce
136
- * indistinguishable payloads, and the server cannot build the
137
- * `paymentRequirements` (`asset` + `extra`) the facilitator needs to settle.
138
- *
139
- * So the payment can opt into carrying the token with it.
140
- */
141
-
142
- /**
143
- * Build the token metadata block for a payload, resolving the address against
144
- * the chain registry.
31
+ * Compares case-insensitively (recovered addresses are checksummed, linked
32
+ * wallets are often stored lower-cased) and never throws: a malformed
33
+ * signature is a failed verification, not an exception to handle at every
34
+ * call site.
145
35
  *
146
- * @param chainName - Chain the payment was signed for
147
- * @param address - Token contract address from the signed payload
148
- * @returns Metadata block, or undefined if the address is not in the registry
149
- */
150
- declare function buildTokenMetadata(chainName: string, address: string): PaymentTokenMetadata | undefined;
151
-
152
- /**
153
- * uvd-x402-sdk - UTF-8 safe base64
154
- *
155
- * `btoa()` only accepts code points 0-255. Any character above that throws
156
- * `InvalidCharacterError`, and the X-PAYMENT payload is not guaranteed to be
157
- * ASCII: the EIP-712 domain name of USDT on Optimism and Arbitrum is literally
158
- * `USD₮0` (U+20AE). A header carrying that name crashes a plain `btoa()`.
159
- *
160
- * So the JSON is UTF-8 encoded to bytes first, and only then base64'd. Decoding
161
- * reverses it. For ASCII-only input the output is byte-identical to
162
- * `btoa(json)`, which is why swapping this in cannot change any existing header.
163
- *
164
- * `TextEncoder`/`TextDecoder` are available in every browser the SDK targets and
165
- * in Node 11+; `btoa`/`atob` are used for the byte<->base64 step because they
166
- * exist in both environments without pulling in `Buffer`.
167
- */
168
- /**
169
- * Encode a string as base64, handling non-ASCII characters correctly.
170
- *
171
- * @param value - Any UTF-8 string
172
- * @returns Base64-encoded value
173
- */
174
- declare function encodeBase64Utf8(value: string): string;
175
- /**
176
- * Decode a base64 string produced by {@link encodeBase64Utf8}.
177
- *
178
- * @param encoded - Base64-encoded value
179
- * @returns The original UTF-8 string
180
- */
181
- declare function decodeBase64Utf8(encoded: string): string;
182
- /**
183
- * JSON-serialize a value and encode it as UTF-8 safe base64.
184
- *
185
- * This is the encoder for every X-PAYMENT header the SDK emits.
186
- *
187
- * @param value - Value to serialize
188
- * @returns Base64-encoded JSON
189
- */
190
- declare function encodeBase64Json(value: unknown): string;
191
-
192
- /**
193
- * uvd-x402-sdk - Validation and Payment Header Utilities
194
- *
195
- * Functions for validating payment parameters and creating
196
- * payment headers for HTTP requests.
197
- */
198
-
199
- /**
200
- * Validate that a recipient address is present and valid
201
- *
202
- * This function ensures that:
203
- * 1. The recipient is not null, undefined, or empty
204
- * 2. The recipient is not just whitespace
205
- * 3. For EVM, it's a valid checksummed or lowercase 0x address
206
- *
207
- * @param recipient - The recipient address to validate
208
- * @param networkType - Optional network type for format validation
209
- * @throws X402Error with code 'INVALID_RECIPIENT' if validation fails
210
- */
211
- declare function validateRecipient(recipient: string | undefined | null, networkType?: 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'xrpl'): asserts recipient is string;
212
- /**
213
- * Validate payment amount
214
- *
215
- * Ensures the amount is a valid positive number string
216
- *
217
- * @param amount - The amount string to validate
218
- * @throws X402Error with code 'INVALID_AMOUNT' if validation fails
219
- */
220
- declare function validateAmount(amount: string | undefined | null): asserts amount is string;
221
- /**
222
- * Create payment headers object from a base64-encoded payload
223
- *
224
- * Returns an object with both X-PAYMENT and PAYMENT-SIGNATURE headers,
225
- * making it easy to use either header format.
226
- *
227
- * @param paymentHeader - Base64-encoded payment payload
228
- * @returns PaymentHeaders object with both header formats
229
- *
230
- * @example
231
- * ```ts
232
- * const headers = createPaymentHeaders(paymentHeader);
233
- *
234
- * // Use v1 header (most compatible)
235
- * fetch(url, { headers: { 'X-PAYMENT': headers['X-PAYMENT'] } });
236
- *
237
- * // Use v2 header
238
- * fetch(url, { headers: { 'PAYMENT-SIGNATURE': headers['PAYMENT-SIGNATURE'] } });
239
- * ```
240
- */
241
- declare function createPaymentHeaders(paymentHeader: string): PaymentHeaders;
242
- /**
243
- * Get a single payment header by name
244
- *
245
- * @param paymentHeader - Base64-encoded payment payload
246
- * @param headerName - Header name to use ('X-PAYMENT' or 'PAYMENT-SIGNATURE')
247
- * @returns Object with a single header entry
248
- *
249
- * @example
250
- * ```ts
251
- * // Use with fetch spread operator
252
- * fetch(url, {
253
- * headers: {
254
- * 'Content-Type': 'application/json',
255
- * ...getPaymentHeader(result.paymentHeader, 'X-PAYMENT'),
256
- * },
257
- * });
258
- * ```
259
- */
260
- declare function getPaymentHeader(paymentHeader: string, headerName?: X402HeaderName): Record<X402HeaderName, string>;
261
- /**
262
- * Default x402 payment header name
263
- *
264
- * Use 'X-PAYMENT' for maximum compatibility with all facilitators.
265
- * Use 'PAYMENT-SIGNATURE' for x402 v2 compliance.
266
- */
267
- declare const DEFAULT_PAYMENT_HEADER: X402HeaderName;
268
- /**
269
- * All supported x402 payment header names
36
+ * @returns true iff the recovered signer equals `expected`
270
37
  */
271
- declare const PAYMENT_HEADER_NAMES: readonly X402HeaderName[];
38
+ declare function verifyPersonalSign(params: {
39
+ message: string;
40
+ signature: string;
41
+ expected: string;
42
+ }): boolean;
272
43
 
273
- export { DEFAULT_PAYMENT_HEADER, PAYMENT_HEADER_NAMES, buildTokenMetadata, caip2ToChain, chainToCAIP2, convertX402Header, createPaymentHeaders, createX402Header, createX402V1Header, createX402V2Header, decodeBase64Utf8, decodeX402Header, detectX402Version, encodeBase64Json, encodeBase64Utf8, encodeX402Header, generatePaymentOptions, getPaymentHeader, isCAIP2Format, parseNetworkIdentifier, paymentChallengeFrom, validateAmount, validateRecipient };
44
+ export { recoverPersonalSignAddress, verifyPersonalSign };
@@ -1,273 +1,44 @@
1
- import { e as X402Header, X as X402Version, C as ChainConfig, f as X402PayloadData, F as X402HeaderV1, I as X402PaymentOption, G as X402HeaderV2, s as PaymentTokenMetadata, B as X402HeaderName, p as PaymentHeaders } from '../index-DeJMYEKC.js';
1
+ export { D as DEFAULT_PAYMENT_HEADER, P as PAYMENT_HEADER_NAMES, b as buildTokenMetadata, c as caip2ToChain, a as chainToCAIP2, d as convertX402Header, e as createPaymentHeaders, f as createX402Header, g as createX402V1Header, h as createX402V2Header, i as decodeBase64Utf8, j as decodeX402Header, k as detectX402Version, l as encodeBase64Json, m as encodeBase64Utf8, n as encodeX402Header, o as generatePaymentOptions, p as getPaymentHeader, q as isCAIP2Format, r as parseNetworkIdentifier, s as paymentChallengeFrom, v as validateAmount, t as validateRecipient } from '../validation-DsbfDAtV.js';
2
+ import '../index-ZH10otHE.js';
2
3
 
3
4
  /**
4
- * uvd-x402-sdk - x402 Protocol Utilities
5
+ * uvd-x402-sdk - EIP-191 personal_sign helpers
5
6
  *
6
- * Utilities for working with x402 v1 and v2 protocols.
7
- * Handles version detection, payload encoding, and CAIP-2 conversions.
8
- */
9
-
10
- /**
11
- * Detect x402 version from a response header or body
12
- *
13
- * @param data - The 402 response data (parsed JSON or header value)
14
- * @returns The detected version (1 or 2)
15
- */
16
- declare function detectX402Version(data: unknown): X402Version;
17
- /**
18
- * Convert chain name to CAIP-2 identifier
19
- *
20
- * @param chainName - Chain name (e.g., 'base', 'solana')
21
- * @returns CAIP-2 identifier (e.g., 'eip155:8453', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
22
- */
23
- declare function chainToCAIP2(chainName: string): string;
24
- /**
25
- * Convert CAIP-2 identifier to chain name
26
- *
27
- * @param caip2 - CAIP-2 identifier
28
- * @returns Chain name or null if unknown
29
- */
30
- declare function caip2ToChain(caip2: string): string | null;
31
- /**
32
- * Parse network identifier from either v1 or v2 format
33
- *
34
- * @param network - Network identifier (v1 string or v2 CAIP-2)
35
- * @returns Normalized chain name
36
- */
37
- declare function parseNetworkIdentifier(network: string): string;
38
- /**
39
- * Encode x402 payload as base64 header value
40
- *
41
- * @param header - The x402 header object
42
- * @returns Base64-encoded string
43
- */
44
- declare function encodeX402Header(header: X402Header): string;
45
- /**
46
- * Decode x402 header from base64 string
47
- *
48
- * @param encoded - Base64-encoded header value
49
- * @returns Parsed x402 header
50
- */
51
- declare function decodeX402Header(encoded: string): X402Header;
52
- /**
53
- * Create x402 v1 header
54
- *
55
- * @param network - Chain name (e.g., 'base')
56
- * @param payload - Network-specific payload
57
- * @returns x402 v1 header object
58
- */
59
- declare function createX402V1Header(network: string, payload: X402PayloadData): X402HeaderV1;
60
- /**
61
- * Create x402 v2 header
62
- *
63
- * @param network - CAIP-2 network identifier
64
- * @param payload - Network-specific payload
65
- * @param accepts - Optional array of payment options
66
- * @returns x402 v2 header object
67
- */
68
- declare function createX402V2Header(network: string, payload: X402PayloadData, accepts?: X402PaymentOption[]): X402HeaderV2;
69
- /**
70
- * Create x402 header with automatic version selection
71
- *
72
- * @param chainConfig - Chain configuration
73
- * @param payload - Network-specific payload
74
- * @param version - Version to use (1, 2, or 'auto')
75
- * @returns x402 header object
76
- */
77
- declare function createX402Header(chainConfig: ChainConfig, payload: X402PayloadData, version?: X402Version | 'auto'): X402Header;
78
- /**
79
- * Generate payment options array for multi-network support
80
- *
81
- * @param chainConfigs - Array of chain configurations
82
- * @param amount - Amount in USDC (e.g., "10.00")
83
- * @param facilitator - Optional facilitator URL override
84
- * @returns Array of x402 v2 payment options
85
- */
86
- declare function generatePaymentOptions(chainConfigs: ChainConfig[], amount: string, facilitator?: string): X402PaymentOption[];
87
- /**
88
- * Check if a network string is in CAIP-2 format
7
+ * Generic recover/verify for an EIP-191 `personal_sign` over an arbitrary
8
+ * string message — the shape a wallet produces for `eth_sign`/`personal_sign`
9
+ * and `cast wallet sign <message>`.
89
10
  *
90
- * @param network - Network identifier
91
- * @returns True if CAIP-2 format
11
+ * This is deliberately NOT the ERC-8128 machinery (`verifyRequest`), which
12
+ * verifies an RFC 9421 SIGNED HTTP REQUEST (method;url;headers;content-digest).
13
+ * A challenge/response flow — a service hands out a nonce string, the wallet
14
+ * signs that string, the service recovers the signer — is a different, simpler
15
+ * case that the ERC-8128 path does not cover. Consumers doing wallet-ownership
16
+ * challenges (e.g. MeshRelay's IRC `VERIFY`/`VERIFY-SIG`) needed this and were
17
+ * each reaching for `ethers.verifyMessage` directly; this centralizes it.
92
18
  */
93
- declare function isCAIP2Format(network: string): boolean;
94
19
  /**
95
- * Convert between x402 v1 and v2 header formats
20
+ * Recover the address that produced an EIP-191 `personal_sign` over `message`.
96
21
  *
97
- * @param header - Source header
98
- * @param targetVersion - Target version
99
- * @returns Converted header
22
+ * @param message - the exact string that was signed
23
+ * @param signature - the 0x-prefixed signature
24
+ * @returns the checksummed recovered address
25
+ * @throws if the signature is malformed (propagates ethers' error)
100
26
  */
101
- declare function convertX402Header(header: X402Header, targetVersion: X402Version): X402Header;
27
+ declare function recoverPersonalSignAddress(message: string, signature: string): string;
102
28
  /**
103
- * Read a 402 payment challenge from wherever the seller put it.
104
- *
105
- * x402 allows BOTH transports and sellers pick freely:
106
- *
107
- * - base64 JSON in the `PAYMENT-REQUIRED` (or `X-PAYMENT-REQUIRED`) header
108
- * - JSON in the response body
29
+ * Whether `signature` over `message` was produced by `expected`.
109
30
  *
110
- * Measured against production on 2026-08-20: of 40 live Bazaar resources,
111
- * **36 of 36 that answered 402 carried the challenge in the header, and none in
112
- * the body**. Worse, sellers like Tenjin use the 402 body for a free preview of
113
- * the paid content — so the body is valid JSON that simply has no `accepts`, and
114
- * a body-only reader parses it happily and finds nothing.
115
- *
116
- * Reads the header first because that is where live sellers put it, and falls
117
- * back to the body so the sellers who use it keep working.
118
- *
119
- * Returns `null` when neither transport carries a challenge — a real "no terms
120
- * here", distinct from a challenge we failed to decode.
121
- */
122
- declare function paymentChallengeFrom(headers: {
123
- get(name: string): string | null;
124
- } | Record<string, string>, body?: unknown): Record<string, unknown> | null;
125
-
126
- /**
127
- * uvd-x402-sdk - Token metadata for payment payloads
128
- *
129
- * An EIP-3009 authorization is signed against a token contract, but the encoded
130
- * payload only carries the signature and the transfer fields. The token itself
131
- * is implicit — the server is expected to already know which asset it asked
132
- * for.
133
- *
134
- * That holds when a resource accepts exactly one token per chain. It breaks as
135
- * soon as it accepts several: a EURC payment and a USDC payment on Base produce
136
- * indistinguishable payloads, and the server cannot build the
137
- * `paymentRequirements` (`asset` + `extra`) the facilitator needs to settle.
138
- *
139
- * So the payment can opt into carrying the token with it.
140
- */
141
-
142
- /**
143
- * Build the token metadata block for a payload, resolving the address against
144
- * the chain registry.
31
+ * Compares case-insensitively (recovered addresses are checksummed, linked
32
+ * wallets are often stored lower-cased) and never throws: a malformed
33
+ * signature is a failed verification, not an exception to handle at every
34
+ * call site.
145
35
  *
146
- * @param chainName - Chain the payment was signed for
147
- * @param address - Token contract address from the signed payload
148
- * @returns Metadata block, or undefined if the address is not in the registry
149
- */
150
- declare function buildTokenMetadata(chainName: string, address: string): PaymentTokenMetadata | undefined;
151
-
152
- /**
153
- * uvd-x402-sdk - UTF-8 safe base64
154
- *
155
- * `btoa()` only accepts code points 0-255. Any character above that throws
156
- * `InvalidCharacterError`, and the X-PAYMENT payload is not guaranteed to be
157
- * ASCII: the EIP-712 domain name of USDT on Optimism and Arbitrum is literally
158
- * `USD₮0` (U+20AE). A header carrying that name crashes a plain `btoa()`.
159
- *
160
- * So the JSON is UTF-8 encoded to bytes first, and only then base64'd. Decoding
161
- * reverses it. For ASCII-only input the output is byte-identical to
162
- * `btoa(json)`, which is why swapping this in cannot change any existing header.
163
- *
164
- * `TextEncoder`/`TextDecoder` are available in every browser the SDK targets and
165
- * in Node 11+; `btoa`/`atob` are used for the byte<->base64 step because they
166
- * exist in both environments without pulling in `Buffer`.
167
- */
168
- /**
169
- * Encode a string as base64, handling non-ASCII characters correctly.
170
- *
171
- * @param value - Any UTF-8 string
172
- * @returns Base64-encoded value
173
- */
174
- declare function encodeBase64Utf8(value: string): string;
175
- /**
176
- * Decode a base64 string produced by {@link encodeBase64Utf8}.
177
- *
178
- * @param encoded - Base64-encoded value
179
- * @returns The original UTF-8 string
180
- */
181
- declare function decodeBase64Utf8(encoded: string): string;
182
- /**
183
- * JSON-serialize a value and encode it as UTF-8 safe base64.
184
- *
185
- * This is the encoder for every X-PAYMENT header the SDK emits.
186
- *
187
- * @param value - Value to serialize
188
- * @returns Base64-encoded JSON
189
- */
190
- declare function encodeBase64Json(value: unknown): string;
191
-
192
- /**
193
- * uvd-x402-sdk - Validation and Payment Header Utilities
194
- *
195
- * Functions for validating payment parameters and creating
196
- * payment headers for HTTP requests.
197
- */
198
-
199
- /**
200
- * Validate that a recipient address is present and valid
201
- *
202
- * This function ensures that:
203
- * 1. The recipient is not null, undefined, or empty
204
- * 2. The recipient is not just whitespace
205
- * 3. For EVM, it's a valid checksummed or lowercase 0x address
206
- *
207
- * @param recipient - The recipient address to validate
208
- * @param networkType - Optional network type for format validation
209
- * @throws X402Error with code 'INVALID_RECIPIENT' if validation fails
210
- */
211
- declare function validateRecipient(recipient: string | undefined | null, networkType?: 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'xrpl'): asserts recipient is string;
212
- /**
213
- * Validate payment amount
214
- *
215
- * Ensures the amount is a valid positive number string
216
- *
217
- * @param amount - The amount string to validate
218
- * @throws X402Error with code 'INVALID_AMOUNT' if validation fails
219
- */
220
- declare function validateAmount(amount: string | undefined | null): asserts amount is string;
221
- /**
222
- * Create payment headers object from a base64-encoded payload
223
- *
224
- * Returns an object with both X-PAYMENT and PAYMENT-SIGNATURE headers,
225
- * making it easy to use either header format.
226
- *
227
- * @param paymentHeader - Base64-encoded payment payload
228
- * @returns PaymentHeaders object with both header formats
229
- *
230
- * @example
231
- * ```ts
232
- * const headers = createPaymentHeaders(paymentHeader);
233
- *
234
- * // Use v1 header (most compatible)
235
- * fetch(url, { headers: { 'X-PAYMENT': headers['X-PAYMENT'] } });
236
- *
237
- * // Use v2 header
238
- * fetch(url, { headers: { 'PAYMENT-SIGNATURE': headers['PAYMENT-SIGNATURE'] } });
239
- * ```
240
- */
241
- declare function createPaymentHeaders(paymentHeader: string): PaymentHeaders;
242
- /**
243
- * Get a single payment header by name
244
- *
245
- * @param paymentHeader - Base64-encoded payment payload
246
- * @param headerName - Header name to use ('X-PAYMENT' or 'PAYMENT-SIGNATURE')
247
- * @returns Object with a single header entry
248
- *
249
- * @example
250
- * ```ts
251
- * // Use with fetch spread operator
252
- * fetch(url, {
253
- * headers: {
254
- * 'Content-Type': 'application/json',
255
- * ...getPaymentHeader(result.paymentHeader, 'X-PAYMENT'),
256
- * },
257
- * });
258
- * ```
259
- */
260
- declare function getPaymentHeader(paymentHeader: string, headerName?: X402HeaderName): Record<X402HeaderName, string>;
261
- /**
262
- * Default x402 payment header name
263
- *
264
- * Use 'X-PAYMENT' for maximum compatibility with all facilitators.
265
- * Use 'PAYMENT-SIGNATURE' for x402 v2 compliance.
266
- */
267
- declare const DEFAULT_PAYMENT_HEADER: X402HeaderName;
268
- /**
269
- * All supported x402 payment header names
36
+ * @returns true iff the recovered signer equals `expected`
270
37
  */
271
- declare const PAYMENT_HEADER_NAMES: readonly X402HeaderName[];
38
+ declare function verifyPersonalSign(params: {
39
+ message: string;
40
+ signature: string;
41
+ expected: string;
42
+ }): boolean;
272
43
 
273
- export { DEFAULT_PAYMENT_HEADER, PAYMENT_HEADER_NAMES, buildTokenMetadata, caip2ToChain, chainToCAIP2, convertX402Header, createPaymentHeaders, createX402Header, createX402V1Header, createX402V2Header, decodeBase64Utf8, decodeX402Header, detectX402Version, encodeBase64Json, encodeBase64Utf8, encodeX402Header, generatePaymentOptions, getPaymentHeader, isCAIP2Format, parseNetworkIdentifier, paymentChallengeFrom, validateAmount, validateRecipient };
44
+ export { recoverPersonalSignAddress, verifyPersonalSign };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var ethers = require('ethers');
4
+
3
5
  // src/types/index.ts
4
6
  var CAIP2_IDENTIFIERS = {
5
7
  // EVM chains
@@ -1388,6 +1390,19 @@ var PAYMENT_HEADER_NAMES = [
1388
1390
  "X-PAYMENT",
1389
1391
  "PAYMENT-SIGNATURE"
1390
1392
  ];
1393
+ function recoverPersonalSignAddress(message, signature) {
1394
+ return ethers.ethers.verifyMessage(message, signature);
1395
+ }
1396
+ function verifyPersonalSign(params) {
1397
+ const { message, signature, expected } = params;
1398
+ if (!expected) return false;
1399
+ try {
1400
+ const recovered = recoverPersonalSignAddress(message, signature);
1401
+ return recovered.toLowerCase() === expected.toLowerCase();
1402
+ } catch {
1403
+ return false;
1404
+ }
1405
+ }
1391
1406
 
1392
1407
  exports.DEFAULT_PAYMENT_HEADER = DEFAULT_PAYMENT_HEADER;
1393
1408
  exports.PAYMENT_HEADER_NAMES = PAYMENT_HEADER_NAMES;
@@ -1410,7 +1425,9 @@ exports.getPaymentHeader = getPaymentHeader;
1410
1425
  exports.isCAIP2Format = isCAIP2Format;
1411
1426
  exports.parseNetworkIdentifier = parseNetworkIdentifier;
1412
1427
  exports.paymentChallengeFrom = paymentChallengeFrom;
1428
+ exports.recoverPersonalSignAddress = recoverPersonalSignAddress;
1413
1429
  exports.validateAmount = validateAmount;
1414
1430
  exports.validateRecipient = validateRecipient;
1431
+ exports.verifyPersonalSign = verifyPersonalSign;
1415
1432
  //# sourceMappingURL=index.js.map
1416
1433
  //# sourceMappingURL=index.js.map