@inflowpayai/x402 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Jarwin, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @inflowpayai/x402
2
+
3
+ Core types, HTTP client, and shared constants for the [InFlow x402 SDK](https://github.com/inflowpayai/inflow-node/tree/main/docs/x402).
4
+
5
+ This package is a transitive dependency of `@inflowpayai/x402-seller*` and `@inflowpayai/x402-buyer*`. Most integrations don't install it directly.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @inflowpayai/x402 @x402/core
11
+ ```
12
+
13
+ `@x402/core` is a peer dependency. Co-install it on the consumer side so package managers can warn loudly when it's missing.
14
+
15
+ ## What's exported
16
+
17
+ ### Main entry — `@inflowpayai/x402`
18
+
19
+ - `InflowHttpClient` — the shared HTTP client used by every other package in this monorepo. Carries `X-API-KEY` injection, JSON parsing,
20
+ per-request timeout, retry on transient statuses (`429`, `502`, `503`, `504`) with exponential backoff capped at three attempts, and error
21
+ mapping into `InflowApiError`.
22
+ - `resolveBaseUrl(options)` — returns the API base URL for an `Environment` (`'production' | 'sandbox'`) or a `baseUrl` override.
23
+ - `InflowApiError`, `X402VersionMismatchError` — typed errors raised by the client.
24
+ - Constants — `X402_VERSION`, `HEADERS`, `SCHEMES`, `NETWORKS`, `CONTRACTS`, `EXTRA_KEYS`, `PAYLOAD_KEYS`, `ASSET_TRANSFER_METHODS`.
25
+ - Wire-shape types — `PaymentRequirements`, `PaymentRequired`, `SettleResponse`, `VerifyResponse`, `ResourceInfo`, `PaymentScheme`, `InstrumentType`.
26
+ - InFlow-specific types — `X402ConfigResponse`, `X402AssetInfo`, `X402WalletInfo`, `PaymentMethodInfo`,
27
+ `X402FacilitatorSupportedResponse`, `X402BuyerSupportedResponse`, `X402SupportedKind`, `InflowPaymentPayload`, `BalancePayloadData`,
28
+ `ExactPayloadData`, `Permit2PayloadData`, `InstrumentPayloadData`.
29
+ - Narrowing helpers — `isBalancePayload`, `isExactPayload`, `isPermit2Payload`, `isInstrumentPayload`.
30
+ - `readHeader(headers, name)` — case-insensitive header read for WHATWG `Headers`, Node `IncomingHttpHeaders`-style records, or plain
31
+ `Record<string, string | string[] | undefined>`.
32
+
33
+ ### `@inflowpayai/x402/extensions`
34
+
35
+ - `ExtensionHandler<TDecl, TPayloadEntry>` — pluggable handler contract.
36
+ - `PAYMENT_IDENTIFIER` — handler for the `payment-identifier` extension.
37
+ - `validatePaymentId(id)` / `generatePaymentId(prefix?)` — format validation and generation.
38
+ - `getExtension<TDecl>(extensions, handler)` / `setExtension<TDecl>(extensions, handler, value)` — typed accessor
39
+ helpers for `PaymentRequired.extensions` / `PaymentPayload.extensions`.
40
+ - `EXTENSION_REGISTRY` — registry of every handler the SDK ships with, keyed by extension name.
41
+
42
+ ### `@inflowpayai/x402/extras`
43
+
44
+ - `getExtra<T>(extra, key)` / `setExtra<T>(extra, key, value)` — open-key analogs of the extension helpers, for `PaymentRequirements.extra`,
45
+ `PaymentMethodInfo.extra`, and similar bag fields.
46
+
47
+ ### `@inflowpayai/x402/security`
48
+
49
+ - `timingSafeEqualStrings(a, b)` — constant-time string equality.
50
+
51
+ ## Example — `InflowHttpClient`
52
+
53
+ ```ts
54
+ import { InflowHttpClient, InflowApiError } from '@inflowpayai/x402';
55
+
56
+ const http = new InflowHttpClient({
57
+ apiKey: process.env.INFLOW_API_KEY!,
58
+ environment: 'sandbox',
59
+ });
60
+
61
+ try {
62
+ const config = await http.get('/v1/x402/config');
63
+ console.log(config);
64
+ } catch (err) {
65
+ if (err instanceof InflowApiError) {
66
+ console.error(`[${err.requestId ?? '-'}] ${err.code} (${err.httpStatus})`);
67
+ } else {
68
+ throw err;
69
+ }
70
+ }
71
+ ```
72
+
73
+ ## See also
74
+
75
+ - [@inflowpayai/x402-seller](../x402-seller) — framework-agnostic seller core
76
+ - [@inflowpayai/x402-buyer](../x402-buyer) — framework-agnostic buyer core
77
+ - [Product overview](../../docs/x402/README.md)
78
+ - [Architecture](../../docs/x402/architecture.md) — InFlow vs. foundation responsibilities, request lifecycle, conflict precedence
79
+ - [Wire-format mapping](../../docs/x402/protocol-mapping.md) — types, headers, network rules, decimals
80
+ - [Extensions](../../docs/x402/extensions.md) — `payment-identifier` end-to-end
81
+
82
+ ## License
83
+
84
+ MIT.
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ // src/extensions/payment-identifier.ts
6
+ var EXTENSION_PAYMENT_IDENTIFIER = "payment-identifier";
7
+ var PAYMENT_ID_MIN_LENGTH = 16;
8
+ var PAYMENT_ID_MAX_LENGTH = 128;
9
+ var PAYMENT_ID_REGEX = /^[a-zA-Z0-9_-]+$/u;
10
+ var PAYMENT_ID_PREFIX_REGEX = /^[a-zA-Z0-9_-]*$/u;
11
+ var PAYMENT_ID_DEFAULT_PREFIX = "pay_";
12
+ function validatePaymentId(id) {
13
+ if (typeof id !== "string") return false;
14
+ if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) return false;
15
+ return PAYMENT_ID_REGEX.test(id);
16
+ }
17
+ function generatePaymentId(prefix = PAYMENT_ID_DEFAULT_PREFIX) {
18
+ if (typeof prefix !== "string" || !PAYMENT_ID_PREFIX_REGEX.test(prefix)) {
19
+ throw new Error(`generatePaymentId: prefix "${prefix}" contains characters outside ${PAYMENT_ID_REGEX.source}`);
20
+ }
21
+ const suffix = crypto.randomBytes(16).toString("hex");
22
+ const id = `${prefix}${suffix}`;
23
+ if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) {
24
+ throw new Error(
25
+ `generatePaymentId: result length ${id.length} is outside [${PAYMENT_ID_MIN_LENGTH}, ${PAYMENT_ID_MAX_LENGTH}]`
26
+ );
27
+ }
28
+ return id;
29
+ }
30
+ var PAYMENT_IDENTIFIER = {
31
+ name: EXTENSION_PAYMENT_IDENTIFIER,
32
+ buildDeclaration() {
33
+ return { required: false };
34
+ },
35
+ readDeclaration(decl) {
36
+ if (decl === null || typeof decl !== "object") return null;
37
+ const required = decl.required;
38
+ if (typeof required !== "boolean") return null;
39
+ return { required };
40
+ },
41
+ buildPayloadEntry(_declaration, context) {
42
+ const id = context.providedPaymentId;
43
+ if (id === void 0) return null;
44
+ if (!validatePaymentId(id)) return null;
45
+ return { paymentId: id };
46
+ }
47
+ };
48
+
49
+ // src/extensions/access.ts
50
+ function getExtension(extensions, handler) {
51
+ if (extensions === void 0) return void 0;
52
+ const raw = extensions[handler.name];
53
+ if (raw === void 0) return void 0;
54
+ return handler.readDeclaration(raw) ?? void 0;
55
+ }
56
+ function setExtension(extensions, handler, value) {
57
+ return { ...extensions ?? {}, [handler.name]: value };
58
+ }
59
+
60
+ // src/extensions/index.ts
61
+ var ALL_EXTENSIONS = [PAYMENT_IDENTIFIER];
62
+ var EXTENSION_REGISTRY = new Map(
63
+ ALL_EXTENSIONS.map((h) => [h.name, h])
64
+ );
65
+
66
+ exports.EXTENSION_PAYMENT_IDENTIFIER = EXTENSION_PAYMENT_IDENTIFIER;
67
+ exports.EXTENSION_REGISTRY = EXTENSION_REGISTRY;
68
+ exports.PAYMENT_IDENTIFIER = PAYMENT_IDENTIFIER;
69
+ exports.PAYMENT_ID_DEFAULT_PREFIX = PAYMENT_ID_DEFAULT_PREFIX;
70
+ exports.PAYMENT_ID_MAX_LENGTH = PAYMENT_ID_MAX_LENGTH;
71
+ exports.PAYMENT_ID_MIN_LENGTH = PAYMENT_ID_MIN_LENGTH;
72
+ exports.PAYMENT_ID_REGEX = PAYMENT_ID_REGEX;
73
+ exports.generatePaymentId = generatePaymentId;
74
+ exports.getExtension = getExtension;
75
+ exports.setExtension = setExtension;
76
+ exports.validatePaymentId = validatePaymentId;
77
+ //# sourceMappingURL=index.cjs.map
78
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/extensions/payment-identifier.ts","../../src/extensions/access.ts","../../src/extensions/index.ts"],"names":["randomBytes"],"mappings":"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","file":"index.cjs","sourcesContent":["import { randomBytes } from 'node:crypto';\n\nimport type { ExtensionHandler } from './types.js';\n\n/** Extension name on the wire — the key in `extensions[]` maps. */\nexport const EXTENSION_PAYMENT_IDENTIFIER = 'payment-identifier' as const;\n\nexport const PAYMENT_ID_MIN_LENGTH = 16;\nexport const PAYMENT_ID_MAX_LENGTH = 128;\n\n/** Regex a valid payment identifier must match. Mirrors the x402 `payment-identifier` extension spec. */\nexport const PAYMENT_ID_REGEX = /^[a-zA-Z0-9_-]+$/u;\n\n/**\n * Regex a {@link generatePaymentId} prefix must match — same character class as {@link PAYMENT_ID_REGEX}, but allows the\n * empty string.\n */\nconst PAYMENT_ID_PREFIX_REGEX = /^[a-zA-Z0-9_-]*$/u;\n\n/**\n * Default prefix used by {@link generatePaymentId}. Mirrors the format produced by InFlow's automatic\n * transaction-id-derived identifiers (`pay_<32 hex chars>`).\n */\nexport const PAYMENT_ID_DEFAULT_PREFIX = 'pay_';\n\n/** Declaration shape attached to `PaymentRequired.extensions['payment-identifier']`. */\nexport interface PaymentIdentifierDeclaration {\n /**\n * When `true`, the payload's `extensions['payment-identifier'].paymentId` is mandatory; settlement fails without it.\n * When `false`, the field is optional and may be omitted.\n */\n required: boolean;\n}\n\n/** Payload-entry shape attached to `PaymentPayload.extensions['payment-identifier']`. */\nexport interface PaymentIdentifierPayloadEntry {\n /** The identifier value, satisfying {@link validatePaymentId}. */\n paymentId: string;\n}\n\n/**\n * Validate a payment-identifier string against the extension spec.\n *\n * @param id - Candidate identifier. Returns `false` for any non-string input.\n * @returns `true` when `id` is a string of length 16–128 containing only `a–z`, `A–Z`, `0–9`, `_`, and `-`. `false`\n * otherwise.\n */\nexport function validatePaymentId(id: unknown): id is string {\n if (typeof id !== 'string') return false;\n if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) return false;\n return PAYMENT_ID_REGEX.test(id);\n}\n\n/**\n * Generate a new payment identifier.\n *\n * @param prefix - String prefix prepended to a random 32-character hex suffix. Defaults to `'pay_'`. Must satisfy\n * `^[a-zA-Z0-9_-]*$` and yield a total length of 16–128 when combined with the suffix.\n * @returns A string of the form `<prefix><32 hex chars>` (lowercase).\n * @throws {Error} When `prefix` contains characters not allowed by {@link PAYMENT_ID_REGEX} or the resulting identifier\n * falls outside the 16–128-character bound.\n */\nexport function generatePaymentId(prefix: string = PAYMENT_ID_DEFAULT_PREFIX): string {\n if (typeof prefix !== 'string' || !PAYMENT_ID_PREFIX_REGEX.test(prefix)) {\n throw new Error(`generatePaymentId: prefix \"${prefix}\" contains characters outside ${PAYMENT_ID_REGEX.source}`);\n }\n const suffix = randomBytes(16).toString('hex');\n const id = `${prefix}${suffix}`;\n if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) {\n throw new Error(\n `generatePaymentId: result length ${id.length} is outside [${PAYMENT_ID_MIN_LENGTH}, ${PAYMENT_ID_MAX_LENGTH}]`,\n );\n }\n return id;\n}\n\n/**\n * Handler for the x402 `payment-identifier` extension. Used by the seller (`inflowAccepts`) and the buyer (signer flows\n * that compose external `x402Client` signers).\n */\nexport const PAYMENT_IDENTIFIER: ExtensionHandler<PaymentIdentifierDeclaration, PaymentIdentifierPayloadEntry> = {\n name: EXTENSION_PAYMENT_IDENTIFIER,\n buildDeclaration(): PaymentIdentifierDeclaration {\n return { required: false };\n },\n readDeclaration(decl: unknown): PaymentIdentifierDeclaration | null {\n if (decl === null || typeof decl !== 'object') return null;\n const required = (decl as { required?: unknown }).required;\n if (typeof required !== 'boolean') return null;\n return { required };\n },\n buildPayloadEntry(_declaration, context): PaymentIdentifierPayloadEntry | null {\n const id = context.providedPaymentId;\n if (id === undefined) return null;\n if (!validatePaymentId(id)) return null;\n return { paymentId: id };\n },\n};\n","import type { ExtensionHandler } from './types.js';\n\n/**\n * Read a typed extension entry from an `extensions` map.\n *\n * @typeParam TDecl - Shape of the parsed declaration the handler returns.\n * @param extensions - The `extensions` record from `PaymentRequired` (or any equivalent shape). `undefined` is treated\n * as an empty map.\n * @param handler - The {@link ExtensionHandler} that knows how to parse the entry for its own `name`.\n * @returns The parsed declaration, or `undefined` if the entry is missing or didn't match the handler's expected shape.\n */\nexport function getExtension<TDecl>(\n extensions: Readonly<Record<string, unknown>> | undefined,\n handler: ExtensionHandler<TDecl, unknown>,\n): TDecl | undefined {\n if (extensions === undefined) return undefined;\n const raw = extensions[handler.name];\n if (raw === undefined) return undefined;\n return handler.readDeclaration(raw) ?? undefined;\n}\n\n/**\n * Return a new `extensions` map with the handler's entry set to `value`. Never mutates the input.\n *\n * @typeParam TDecl - Shape of the declaration being written.\n * @param extensions - The existing `extensions` record, or `undefined` to start from empty.\n * @param handler - The handler whose `name` keys the entry.\n * @param value - The declaration value to write.\n * @returns A new record with `value` set under `handler.name`.\n */\nexport function setExtension<TDecl>(\n extensions: Readonly<Record<string, unknown>> | undefined,\n handler: ExtensionHandler<TDecl, unknown>,\n value: TDecl,\n): Record<string, unknown> {\n return { ...(extensions ?? {}), [handler.name]: value };\n}\n","import type { ExtensionHandler } from './types.js';\nimport { PAYMENT_IDENTIFIER } from './payment-identifier.js';\n\nexport type { DeclarationContext, ExtensionHandler, SignContext } from './types.js';\nexport { getExtension, setExtension } from './access.js';\nexport {\n EXTENSION_PAYMENT_IDENTIFIER,\n PAYMENT_ID_DEFAULT_PREFIX,\n PAYMENT_ID_MAX_LENGTH,\n PAYMENT_ID_MIN_LENGTH,\n PAYMENT_ID_REGEX,\n PAYMENT_IDENTIFIER,\n generatePaymentId,\n validatePaymentId,\n} from './payment-identifier.js';\nexport type { PaymentIdentifierDeclaration, PaymentIdentifierPayloadEntry } from './payment-identifier.js';\n\n// Source list for EXTENSION_REGISTRY below. Kept module-local: there's no public reason for consumers to iterate\n// \"all extensions\" — they look up handlers by name via EXTENSION_REGISTRY, or by importing the named handler module\n// directly. Add new extension handlers here when adding a handler module.\nconst ALL_EXTENSIONS: readonly ExtensionHandler<unknown, unknown>[] = [PAYMENT_IDENTIFIER];\n\n/**\n * Lookup table keyed by extension name. Used by the seller (`inflowAccepts`) and the buyer signer to dispatch declared\n * extensions to their handlers. Names without a registered handler are forwarded verbatim by the callers so out-of-band\n * extensions still reach the wire.\n */\nexport const EXTENSION_REGISTRY: ReadonlyMap<string, ExtensionHandler<unknown, unknown>> = new Map(\n ALL_EXTENSIONS.map((h) => [h.name, h]),\n);\n"]}
@@ -0,0 +1,32 @@
1
+ import { a as ExtensionHandler } from '../payment-identifier-BNYznClf.cjs';
2
+ export { D as DeclarationContext, E as EXTENSION_PAYMENT_IDENTIFIER, P as PAYMENT_IDENTIFIER, b as PAYMENT_ID_DEFAULT_PREFIX, c as PAYMENT_ID_MAX_LENGTH, d as PAYMENT_ID_MIN_LENGTH, e as PAYMENT_ID_REGEX, f as PaymentIdentifierDeclaration, g as PaymentIdentifierPayloadEntry, S as SignContext, h as generatePaymentId, v as validatePaymentId } from '../payment-identifier-BNYznClf.cjs';
3
+
4
+ /**
5
+ * Read a typed extension entry from an `extensions` map.
6
+ *
7
+ * @typeParam TDecl - Shape of the parsed declaration the handler returns.
8
+ * @param extensions - The `extensions` record from `PaymentRequired` (or any equivalent shape). `undefined` is treated
9
+ * as an empty map.
10
+ * @param handler - The {@link ExtensionHandler} that knows how to parse the entry for its own `name`.
11
+ * @returns The parsed declaration, or `undefined` if the entry is missing or didn't match the handler's expected shape.
12
+ */
13
+ declare function getExtension<TDecl>(extensions: Readonly<Record<string, unknown>> | undefined, handler: ExtensionHandler<TDecl, unknown>): TDecl | undefined;
14
+ /**
15
+ * Return a new `extensions` map with the handler's entry set to `value`. Never mutates the input.
16
+ *
17
+ * @typeParam TDecl - Shape of the declaration being written.
18
+ * @param extensions - The existing `extensions` record, or `undefined` to start from empty.
19
+ * @param handler - The handler whose `name` keys the entry.
20
+ * @param value - The declaration value to write.
21
+ * @returns A new record with `value` set under `handler.name`.
22
+ */
23
+ declare function setExtension<TDecl>(extensions: Readonly<Record<string, unknown>> | undefined, handler: ExtensionHandler<TDecl, unknown>, value: TDecl): Record<string, unknown>;
24
+
25
+ /**
26
+ * Lookup table keyed by extension name. Used by the seller (`inflowAccepts`) and the buyer signer to dispatch declared
27
+ * extensions to their handlers. Names without a registered handler are forwarded verbatim by the callers so out-of-band
28
+ * extensions still reach the wire.
29
+ */
30
+ declare const EXTENSION_REGISTRY: ReadonlyMap<string, ExtensionHandler<unknown, unknown>>;
31
+
32
+ export { EXTENSION_REGISTRY, ExtensionHandler, getExtension, setExtension };
@@ -0,0 +1,32 @@
1
+ import { a as ExtensionHandler } from '../payment-identifier-BNYznClf.js';
2
+ export { D as DeclarationContext, E as EXTENSION_PAYMENT_IDENTIFIER, P as PAYMENT_IDENTIFIER, b as PAYMENT_ID_DEFAULT_PREFIX, c as PAYMENT_ID_MAX_LENGTH, d as PAYMENT_ID_MIN_LENGTH, e as PAYMENT_ID_REGEX, f as PaymentIdentifierDeclaration, g as PaymentIdentifierPayloadEntry, S as SignContext, h as generatePaymentId, v as validatePaymentId } from '../payment-identifier-BNYznClf.js';
3
+
4
+ /**
5
+ * Read a typed extension entry from an `extensions` map.
6
+ *
7
+ * @typeParam TDecl - Shape of the parsed declaration the handler returns.
8
+ * @param extensions - The `extensions` record from `PaymentRequired` (or any equivalent shape). `undefined` is treated
9
+ * as an empty map.
10
+ * @param handler - The {@link ExtensionHandler} that knows how to parse the entry for its own `name`.
11
+ * @returns The parsed declaration, or `undefined` if the entry is missing or didn't match the handler's expected shape.
12
+ */
13
+ declare function getExtension<TDecl>(extensions: Readonly<Record<string, unknown>> | undefined, handler: ExtensionHandler<TDecl, unknown>): TDecl | undefined;
14
+ /**
15
+ * Return a new `extensions` map with the handler's entry set to `value`. Never mutates the input.
16
+ *
17
+ * @typeParam TDecl - Shape of the declaration being written.
18
+ * @param extensions - The existing `extensions` record, or `undefined` to start from empty.
19
+ * @param handler - The handler whose `name` keys the entry.
20
+ * @param value - The declaration value to write.
21
+ * @returns A new record with `value` set under `handler.name`.
22
+ */
23
+ declare function setExtension<TDecl>(extensions: Readonly<Record<string, unknown>> | undefined, handler: ExtensionHandler<TDecl, unknown>, value: TDecl): Record<string, unknown>;
24
+
25
+ /**
26
+ * Lookup table keyed by extension name. Used by the seller (`inflowAccepts`) and the buyer signer to dispatch declared
27
+ * extensions to their handlers. Names without a registered handler are forwarded verbatim by the callers so out-of-band
28
+ * extensions still reach the wire.
29
+ */
30
+ declare const EXTENSION_REGISTRY: ReadonlyMap<string, ExtensionHandler<unknown, unknown>>;
31
+
32
+ export { EXTENSION_REGISTRY, ExtensionHandler, getExtension, setExtension };
@@ -0,0 +1,66 @@
1
+ import { randomBytes } from 'crypto';
2
+
3
+ // src/extensions/payment-identifier.ts
4
+ var EXTENSION_PAYMENT_IDENTIFIER = "payment-identifier";
5
+ var PAYMENT_ID_MIN_LENGTH = 16;
6
+ var PAYMENT_ID_MAX_LENGTH = 128;
7
+ var PAYMENT_ID_REGEX = /^[a-zA-Z0-9_-]+$/u;
8
+ var PAYMENT_ID_PREFIX_REGEX = /^[a-zA-Z0-9_-]*$/u;
9
+ var PAYMENT_ID_DEFAULT_PREFIX = "pay_";
10
+ function validatePaymentId(id) {
11
+ if (typeof id !== "string") return false;
12
+ if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) return false;
13
+ return PAYMENT_ID_REGEX.test(id);
14
+ }
15
+ function generatePaymentId(prefix = PAYMENT_ID_DEFAULT_PREFIX) {
16
+ if (typeof prefix !== "string" || !PAYMENT_ID_PREFIX_REGEX.test(prefix)) {
17
+ throw new Error(`generatePaymentId: prefix "${prefix}" contains characters outside ${PAYMENT_ID_REGEX.source}`);
18
+ }
19
+ const suffix = randomBytes(16).toString("hex");
20
+ const id = `${prefix}${suffix}`;
21
+ if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) {
22
+ throw new Error(
23
+ `generatePaymentId: result length ${id.length} is outside [${PAYMENT_ID_MIN_LENGTH}, ${PAYMENT_ID_MAX_LENGTH}]`
24
+ );
25
+ }
26
+ return id;
27
+ }
28
+ var PAYMENT_IDENTIFIER = {
29
+ name: EXTENSION_PAYMENT_IDENTIFIER,
30
+ buildDeclaration() {
31
+ return { required: false };
32
+ },
33
+ readDeclaration(decl) {
34
+ if (decl === null || typeof decl !== "object") return null;
35
+ const required = decl.required;
36
+ if (typeof required !== "boolean") return null;
37
+ return { required };
38
+ },
39
+ buildPayloadEntry(_declaration, context) {
40
+ const id = context.providedPaymentId;
41
+ if (id === void 0) return null;
42
+ if (!validatePaymentId(id)) return null;
43
+ return { paymentId: id };
44
+ }
45
+ };
46
+
47
+ // src/extensions/access.ts
48
+ function getExtension(extensions, handler) {
49
+ if (extensions === void 0) return void 0;
50
+ const raw = extensions[handler.name];
51
+ if (raw === void 0) return void 0;
52
+ return handler.readDeclaration(raw) ?? void 0;
53
+ }
54
+ function setExtension(extensions, handler, value) {
55
+ return { ...extensions ?? {}, [handler.name]: value };
56
+ }
57
+
58
+ // src/extensions/index.ts
59
+ var ALL_EXTENSIONS = [PAYMENT_IDENTIFIER];
60
+ var EXTENSION_REGISTRY = new Map(
61
+ ALL_EXTENSIONS.map((h) => [h.name, h])
62
+ );
63
+
64
+ export { EXTENSION_PAYMENT_IDENTIFIER, EXTENSION_REGISTRY, PAYMENT_IDENTIFIER, PAYMENT_ID_DEFAULT_PREFIX, PAYMENT_ID_MAX_LENGTH, PAYMENT_ID_MIN_LENGTH, PAYMENT_ID_REGEX, generatePaymentId, getExtension, setExtension, validatePaymentId };
65
+ //# sourceMappingURL=index.js.map
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/extensions/payment-identifier.ts","../../src/extensions/access.ts","../../src/extensions/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { randomBytes } from 'node:crypto';\n\nimport type { ExtensionHandler } from './types.js';\n\n/** Extension name on the wire — the key in `extensions[]` maps. */\nexport const EXTENSION_PAYMENT_IDENTIFIER = 'payment-identifier' as const;\n\nexport const PAYMENT_ID_MIN_LENGTH = 16;\nexport const PAYMENT_ID_MAX_LENGTH = 128;\n\n/** Regex a valid payment identifier must match. Mirrors the x402 `payment-identifier` extension spec. */\nexport const PAYMENT_ID_REGEX = /^[a-zA-Z0-9_-]+$/u;\n\n/**\n * Regex a {@link generatePaymentId} prefix must match — same character class as {@link PAYMENT_ID_REGEX}, but allows the\n * empty string.\n */\nconst PAYMENT_ID_PREFIX_REGEX = /^[a-zA-Z0-9_-]*$/u;\n\n/**\n * Default prefix used by {@link generatePaymentId}. Mirrors the format produced by InFlow's automatic\n * transaction-id-derived identifiers (`pay_<32 hex chars>`).\n */\nexport const PAYMENT_ID_DEFAULT_PREFIX = 'pay_';\n\n/** Declaration shape attached to `PaymentRequired.extensions['payment-identifier']`. */\nexport interface PaymentIdentifierDeclaration {\n /**\n * When `true`, the payload's `extensions['payment-identifier'].paymentId` is mandatory; settlement fails without it.\n * When `false`, the field is optional and may be omitted.\n */\n required: boolean;\n}\n\n/** Payload-entry shape attached to `PaymentPayload.extensions['payment-identifier']`. */\nexport interface PaymentIdentifierPayloadEntry {\n /** The identifier value, satisfying {@link validatePaymentId}. */\n paymentId: string;\n}\n\n/**\n * Validate a payment-identifier string against the extension spec.\n *\n * @param id - Candidate identifier. Returns `false` for any non-string input.\n * @returns `true` when `id` is a string of length 16–128 containing only `a–z`, `A–Z`, `0–9`, `_`, and `-`. `false`\n * otherwise.\n */\nexport function validatePaymentId(id: unknown): id is string {\n if (typeof id !== 'string') return false;\n if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) return false;\n return PAYMENT_ID_REGEX.test(id);\n}\n\n/**\n * Generate a new payment identifier.\n *\n * @param prefix - String prefix prepended to a random 32-character hex suffix. Defaults to `'pay_'`. Must satisfy\n * `^[a-zA-Z0-9_-]*$` and yield a total length of 16–128 when combined with the suffix.\n * @returns A string of the form `<prefix><32 hex chars>` (lowercase).\n * @throws {Error} When `prefix` contains characters not allowed by {@link PAYMENT_ID_REGEX} or the resulting identifier\n * falls outside the 16–128-character bound.\n */\nexport function generatePaymentId(prefix: string = PAYMENT_ID_DEFAULT_PREFIX): string {\n if (typeof prefix !== 'string' || !PAYMENT_ID_PREFIX_REGEX.test(prefix)) {\n throw new Error(`generatePaymentId: prefix \"${prefix}\" contains characters outside ${PAYMENT_ID_REGEX.source}`);\n }\n const suffix = randomBytes(16).toString('hex');\n const id = `${prefix}${suffix}`;\n if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) {\n throw new Error(\n `generatePaymentId: result length ${id.length} is outside [${PAYMENT_ID_MIN_LENGTH}, ${PAYMENT_ID_MAX_LENGTH}]`,\n );\n }\n return id;\n}\n\n/**\n * Handler for the x402 `payment-identifier` extension. Used by the seller (`inflowAccepts`) and the buyer (signer flows\n * that compose external `x402Client` signers).\n */\nexport const PAYMENT_IDENTIFIER: ExtensionHandler<PaymentIdentifierDeclaration, PaymentIdentifierPayloadEntry> = {\n name: EXTENSION_PAYMENT_IDENTIFIER,\n buildDeclaration(): PaymentIdentifierDeclaration {\n return { required: false };\n },\n readDeclaration(decl: unknown): PaymentIdentifierDeclaration | null {\n if (decl === null || typeof decl !== 'object') return null;\n const required = (decl as { required?: unknown }).required;\n if (typeof required !== 'boolean') return null;\n return { required };\n },\n buildPayloadEntry(_declaration, context): PaymentIdentifierPayloadEntry | null {\n const id = context.providedPaymentId;\n if (id === undefined) return null;\n if (!validatePaymentId(id)) return null;\n return { paymentId: id };\n },\n};\n","import type { ExtensionHandler } from './types.js';\n\n/**\n * Read a typed extension entry from an `extensions` map.\n *\n * @typeParam TDecl - Shape of the parsed declaration the handler returns.\n * @param extensions - The `extensions` record from `PaymentRequired` (or any equivalent shape). `undefined` is treated\n * as an empty map.\n * @param handler - The {@link ExtensionHandler} that knows how to parse the entry for its own `name`.\n * @returns The parsed declaration, or `undefined` if the entry is missing or didn't match the handler's expected shape.\n */\nexport function getExtension<TDecl>(\n extensions: Readonly<Record<string, unknown>> | undefined,\n handler: ExtensionHandler<TDecl, unknown>,\n): TDecl | undefined {\n if (extensions === undefined) return undefined;\n const raw = extensions[handler.name];\n if (raw === undefined) return undefined;\n return handler.readDeclaration(raw) ?? undefined;\n}\n\n/**\n * Return a new `extensions` map with the handler's entry set to `value`. Never mutates the input.\n *\n * @typeParam TDecl - Shape of the declaration being written.\n * @param extensions - The existing `extensions` record, or `undefined` to start from empty.\n * @param handler - The handler whose `name` keys the entry.\n * @param value - The declaration value to write.\n * @returns A new record with `value` set under `handler.name`.\n */\nexport function setExtension<TDecl>(\n extensions: Readonly<Record<string, unknown>> | undefined,\n handler: ExtensionHandler<TDecl, unknown>,\n value: TDecl,\n): Record<string, unknown> {\n return { ...(extensions ?? {}), [handler.name]: value };\n}\n","import type { ExtensionHandler } from './types.js';\nimport { PAYMENT_IDENTIFIER } from './payment-identifier.js';\n\nexport type { DeclarationContext, ExtensionHandler, SignContext } from './types.js';\nexport { getExtension, setExtension } from './access.js';\nexport {\n EXTENSION_PAYMENT_IDENTIFIER,\n PAYMENT_ID_DEFAULT_PREFIX,\n PAYMENT_ID_MAX_LENGTH,\n PAYMENT_ID_MIN_LENGTH,\n PAYMENT_ID_REGEX,\n PAYMENT_IDENTIFIER,\n generatePaymentId,\n validatePaymentId,\n} from './payment-identifier.js';\nexport type { PaymentIdentifierDeclaration, PaymentIdentifierPayloadEntry } from './payment-identifier.js';\n\n// Source list for EXTENSION_REGISTRY below. Kept module-local: there's no public reason for consumers to iterate\n// \"all extensions\" — they look up handlers by name via EXTENSION_REGISTRY, or by importing the named handler module\n// directly. Add new extension handlers here when adding a handler module.\nconst ALL_EXTENSIONS: readonly ExtensionHandler<unknown, unknown>[] = [PAYMENT_IDENTIFIER];\n\n/**\n * Lookup table keyed by extension name. Used by the seller (`inflowAccepts`) and the buyer signer to dispatch declared\n * extensions to their handlers. Names without a registered handler are forwarded verbatim by the callers so out-of-band\n * extensions still reach the wire.\n */\nexport const EXTENSION_REGISTRY: ReadonlyMap<string, ExtensionHandler<unknown, unknown>> = new Map(\n ALL_EXTENSIONS.map((h) => [h.name, h]),\n);\n"]}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ // src/extras/access.ts
4
+ function getExtra(extra, key) {
5
+ if (extra === void 0) return void 0;
6
+ const value = extra[key];
7
+ if (value === void 0) return void 0;
8
+ return value;
9
+ }
10
+ function setExtra(extra, key, value) {
11
+ return { ...extra ?? {}, [key]: value };
12
+ }
13
+
14
+ exports.getExtra = getExtra;
15
+ exports.setExtra = setExtra;
16
+ //# sourceMappingURL=index.cjs.map
17
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/extras/access.ts"],"names":[],"mappings":";;;AAUO,SAAS,QAAA,CACd,OACA,GAAA,EACe;AACf,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,MAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,MAAA;AAChC,EAAA,OAAO,KAAA;AACT;AAWO,SAAS,QAAA,CACd,KAAA,EACA,GAAA,EACA,KAAA,EACyB;AACzB,EAAA,OAAO,EAAE,GAAI,KAAA,IAAS,IAAK,CAAC,GAAG,GAAG,KAAA,EAAM;AAC1C","file":"index.cjs","sourcesContent":["/**\n * Read a typed entry from an `extra` map (the open-ended record carried on `PaymentRequirements.extra`,\n * `PaymentMethodInfo.extra`, and similar).\n *\n * @typeParam T - Caller-supplied expected type of the value. The function does **not** validate at runtime; callers\n * must narrow defensively.\n * @param extra - The `extra` record, or `undefined`.\n * @param key - Key to read.\n * @returns The raw value cast to `T`, or `undefined` if absent.\n */\nexport function getExtra<T = unknown>(\n extra: Readonly<Record<string, unknown>> | undefined,\n key: string,\n): T | undefined {\n if (extra === undefined) return undefined;\n const value = extra[key];\n if (value === undefined) return undefined;\n return value as T;\n}\n\n/**\n * Return a new `extra` map with `key` set to `value`. Never mutates the input.\n *\n * @typeParam T - Type of the value being written.\n * @param extra - The existing `extra` record, or `undefined` to start from empty.\n * @param key - Key to write.\n * @param value - Value to associate with `key`.\n * @returns A new record with `value` set at `key`.\n */\nexport function setExtra<T>(\n extra: Readonly<Record<string, unknown>> | undefined,\n key: string,\n value: T,\n): Record<string, unknown> {\n return { ...(extra ?? {}), [key]: value };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Read a typed entry from an `extra` map (the open-ended record carried on `PaymentRequirements.extra`,
3
+ * `PaymentMethodInfo.extra`, and similar).
4
+ *
5
+ * @typeParam T - Caller-supplied expected type of the value. The function does **not** validate at runtime; callers
6
+ * must narrow defensively.
7
+ * @param extra - The `extra` record, or `undefined`.
8
+ * @param key - Key to read.
9
+ * @returns The raw value cast to `T`, or `undefined` if absent.
10
+ */
11
+ declare function getExtra<T = unknown>(extra: Readonly<Record<string, unknown>> | undefined, key: string): T | undefined;
12
+ /**
13
+ * Return a new `extra` map with `key` set to `value`. Never mutates the input.
14
+ *
15
+ * @typeParam T - Type of the value being written.
16
+ * @param extra - The existing `extra` record, or `undefined` to start from empty.
17
+ * @param key - Key to write.
18
+ * @param value - Value to associate with `key`.
19
+ * @returns A new record with `value` set at `key`.
20
+ */
21
+ declare function setExtra<T>(extra: Readonly<Record<string, unknown>> | undefined, key: string, value: T): Record<string, unknown>;
22
+
23
+ export { getExtra, setExtra };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Read a typed entry from an `extra` map (the open-ended record carried on `PaymentRequirements.extra`,
3
+ * `PaymentMethodInfo.extra`, and similar).
4
+ *
5
+ * @typeParam T - Caller-supplied expected type of the value. The function does **not** validate at runtime; callers
6
+ * must narrow defensively.
7
+ * @param extra - The `extra` record, or `undefined`.
8
+ * @param key - Key to read.
9
+ * @returns The raw value cast to `T`, or `undefined` if absent.
10
+ */
11
+ declare function getExtra<T = unknown>(extra: Readonly<Record<string, unknown>> | undefined, key: string): T | undefined;
12
+ /**
13
+ * Return a new `extra` map with `key` set to `value`. Never mutates the input.
14
+ *
15
+ * @typeParam T - Type of the value being written.
16
+ * @param extra - The existing `extra` record, or `undefined` to start from empty.
17
+ * @param key - Key to write.
18
+ * @param value - Value to associate with `key`.
19
+ * @returns A new record with `value` set at `key`.
20
+ */
21
+ declare function setExtra<T>(extra: Readonly<Record<string, unknown>> | undefined, key: string, value: T): Record<string, unknown>;
22
+
23
+ export { getExtra, setExtra };
@@ -0,0 +1,14 @@
1
+ // src/extras/access.ts
2
+ function getExtra(extra, key) {
3
+ if (extra === void 0) return void 0;
4
+ const value = extra[key];
5
+ if (value === void 0) return void 0;
6
+ return value;
7
+ }
8
+ function setExtra(extra, key, value) {
9
+ return { ...extra ?? {}, [key]: value };
10
+ }
11
+
12
+ export { getExtra, setExtra };
13
+ //# sourceMappingURL=index.js.map
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/extras/access.ts"],"names":[],"mappings":";AAUO,SAAS,QAAA,CACd,OACA,GAAA,EACe;AACf,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,MAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,MAAA;AAChC,EAAA,OAAO,KAAA;AACT;AAWO,SAAS,QAAA,CACd,KAAA,EACA,GAAA,EACA,KAAA,EACyB;AACzB,EAAA,OAAO,EAAE,GAAI,KAAA,IAAS,IAAK,CAAC,GAAG,GAAG,KAAA,EAAM;AAC1C","file":"index.js","sourcesContent":["/**\n * Read a typed entry from an `extra` map (the open-ended record carried on `PaymentRequirements.extra`,\n * `PaymentMethodInfo.extra`, and similar).\n *\n * @typeParam T - Caller-supplied expected type of the value. The function does **not** validate at runtime; callers\n * must narrow defensively.\n * @param extra - The `extra` record, or `undefined`.\n * @param key - Key to read.\n * @returns The raw value cast to `T`, or `undefined` if absent.\n */\nexport function getExtra<T = unknown>(\n extra: Readonly<Record<string, unknown>> | undefined,\n key: string,\n): T | undefined {\n if (extra === undefined) return undefined;\n const value = extra[key];\n if (value === undefined) return undefined;\n return value as T;\n}\n\n/**\n * Return a new `extra` map with `key` set to `value`. Never mutates the input.\n *\n * @typeParam T - Type of the value being written.\n * @param extra - The existing `extra` record, or `undefined` to start from empty.\n * @param key - Key to write.\n * @param value - Value to associate with `key`.\n * @returns A new record with `value` set at `key`.\n */\nexport function setExtra<T>(\n extra: Readonly<Record<string, unknown>> | undefined,\n key: string,\n value: T,\n): Record<string, unknown> {\n return { ...(extra ?? {}), [key]: value };\n}\n"]}