@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 +21 -0
- package/README.md +84 -0
- package/dist/extensions/index.cjs +78 -0
- package/dist/extensions/index.cjs.map +1 -0
- package/dist/extensions/index.d.cts +32 -0
- package/dist/extensions/index.d.ts +32 -0
- package/dist/extensions/index.js +66 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extras/index.cjs +17 -0
- package/dist/extras/index.cjs.map +1 -0
- package/dist/extras/index.d.cts +23 -0
- package/dist/extras/index.d.ts +23 -0
- package/dist/extras/index.js +14 -0
- package/dist/extras/index.js.map +1 -0
- package/dist/index.cjs +421 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +571 -0
- package/dist/index.d.ts +571 -0
- package/dist/index.js +401 -0
- package/dist/index.js.map +1 -0
- package/dist/payment-identifier-BNYznClf.d.cts +103 -0
- package/dist/payment-identifier-BNYznClf.d.ts +103 -0
- package/dist/security/index.cjs +17 -0
- package/dist/security/index.cjs.map +1 -0
- package/dist/security/index.d.cts +14 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/index.js +15 -0
- package/dist/security/index.js.map +1 -0
- package/package.json +97 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
// src/constants.ts
|
|
6
|
+
var X402_VERSION = 2;
|
|
7
|
+
var HEADERS = {
|
|
8
|
+
PAYMENT_REQUIRED: "PAYMENT-REQUIRED",
|
|
9
|
+
PAYMENT_RESPONSE: "PAYMENT-RESPONSE",
|
|
10
|
+
PAYMENT_SIGNATURE: "PAYMENT-SIGNATURE"
|
|
11
|
+
};
|
|
12
|
+
var SCHEMES = {
|
|
13
|
+
BALANCE: "balance",
|
|
14
|
+
EXACT: "exact",
|
|
15
|
+
INSTRUMENT: "instrument"
|
|
16
|
+
};
|
|
17
|
+
var CONTRACTS = {
|
|
18
|
+
PERMIT2_PROXY: "0x402085c248EeA27D92E8b30b2C58ed07f9E20001",
|
|
19
|
+
PERMIT2: "0x000000000022D473030F116dDEE9F6B43aC78BA3"
|
|
20
|
+
};
|
|
21
|
+
var NETWORKS = {
|
|
22
|
+
INFLOW: "inflow:1"
|
|
23
|
+
};
|
|
24
|
+
var EXTRA_KEYS = {
|
|
25
|
+
ASSET_TRANSFER_METHOD: "assetTransferMethod",
|
|
26
|
+
FEE_PAYER: "feePayer",
|
|
27
|
+
NAME: "name",
|
|
28
|
+
PERMIT2_PROXY: "permit2Proxy",
|
|
29
|
+
VERSION: "version"
|
|
30
|
+
};
|
|
31
|
+
var PAYLOAD_KEYS = {
|
|
32
|
+
TRANSACTION_ID: "transactionId"
|
|
33
|
+
};
|
|
34
|
+
var ASSET_TRANSFER_METHODS = {
|
|
35
|
+
EIP3009: "eip3009",
|
|
36
|
+
PERMIT2: "permit2",
|
|
37
|
+
SOLANA: "solana"
|
|
38
|
+
};
|
|
39
|
+
function readHeader(headers, name) {
|
|
40
|
+
const target = name.toLowerCase();
|
|
41
|
+
if (typeof Headers !== "undefined" && headers instanceof Headers) {
|
|
42
|
+
return headers.get(name) ?? void 0;
|
|
43
|
+
}
|
|
44
|
+
const record = headers;
|
|
45
|
+
for (const key of Object.keys(record)) {
|
|
46
|
+
if (key.toLowerCase() !== target) continue;
|
|
47
|
+
const value = record[key];
|
|
48
|
+
if (value === void 0) return void 0;
|
|
49
|
+
if (typeof value === "string") return value;
|
|
50
|
+
return value[0];
|
|
51
|
+
}
|
|
52
|
+
return void 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/environment.ts
|
|
56
|
+
var URLS = {
|
|
57
|
+
production: "https://api.inflowpay.ai",
|
|
58
|
+
sandbox: "https://sandbox.inflowpay.ai"
|
|
59
|
+
};
|
|
60
|
+
function resolveBaseUrl(options = {}) {
|
|
61
|
+
if (options.baseUrl !== void 0 && options.baseUrl !== "") {
|
|
62
|
+
return options.baseUrl.replace(/\/+$/, "");
|
|
63
|
+
}
|
|
64
|
+
return URLS[options.environment ?? "production"];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/errors.ts
|
|
68
|
+
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set(["authorization", "cookie", "set-cookie", "x-api-key"]);
|
|
69
|
+
function sanitizeHeaders(raw) {
|
|
70
|
+
if (raw === void 0) return void 0;
|
|
71
|
+
const out = {};
|
|
72
|
+
const append = (name, value) => {
|
|
73
|
+
if (value === void 0) return;
|
|
74
|
+
if (SENSITIVE_HEADER_NAMES.has(name.toLowerCase())) return;
|
|
75
|
+
out[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
|
|
76
|
+
};
|
|
77
|
+
if (typeof Headers !== "undefined" && raw instanceof Headers) {
|
|
78
|
+
raw.forEach((value, name) => append(name, value));
|
|
79
|
+
} else {
|
|
80
|
+
const record = raw;
|
|
81
|
+
for (const name of Object.keys(record)) {
|
|
82
|
+
append(name, record[name]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return Object.freeze(out);
|
|
86
|
+
}
|
|
87
|
+
var InflowApiError = class _InflowApiError extends Error {
|
|
88
|
+
/** {@inheritDoc InflowApiErrorInit.code} */
|
|
89
|
+
code;
|
|
90
|
+
/** {@inheritDoc InflowApiErrorInit.httpStatus} */
|
|
91
|
+
httpStatus;
|
|
92
|
+
/** {@inheritDoc InflowApiErrorInit.endpoint} */
|
|
93
|
+
endpoint;
|
|
94
|
+
/** {@inheritDoc InflowApiErrorInit.requestId} */
|
|
95
|
+
requestId;
|
|
96
|
+
/** {@inheritDoc InflowApiErrorInit.body} */
|
|
97
|
+
body;
|
|
98
|
+
/** {@inheritDoc InflowApiErrorInit.headers} */
|
|
99
|
+
headers;
|
|
100
|
+
/**
|
|
101
|
+
* @param message - Human-readable message. Callers should prefer the factory {@link InflowApiError.from} which
|
|
102
|
+
* composes a standard message shape including endpoint, status, code, and request ID.
|
|
103
|
+
* @param init - Structured fields carried on the resulting instance.
|
|
104
|
+
*/
|
|
105
|
+
constructor(message, init) {
|
|
106
|
+
super(message, init.cause === void 0 ? void 0 : { cause: init.cause });
|
|
107
|
+
this.name = "InflowApiError";
|
|
108
|
+
this.code = init.code;
|
|
109
|
+
this.httpStatus = init.httpStatus;
|
|
110
|
+
this.endpoint = init.endpoint;
|
|
111
|
+
if (init.requestId !== void 0) this.requestId = init.requestId;
|
|
112
|
+
if (init.body !== void 0) this.body = init.body;
|
|
113
|
+
const headers = sanitizeHeaders(init.headers);
|
|
114
|
+
if (headers !== void 0) this.headers = headers;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Compose an {@link InflowApiError} with a standard message shape.
|
|
118
|
+
*
|
|
119
|
+
* Format: `[<requestId>] <endpoint>: <httpStatus> <code> — <bodyMessage>`, where `<requestId>` is omitted when
|
|
120
|
+
* missing and `<bodyMessage>` falls back to a generic `request failed` when the body had no `message` field.
|
|
121
|
+
*/
|
|
122
|
+
static from(init) {
|
|
123
|
+
const prefix = init.requestId !== void 0 ? `[${init.requestId}] ` : "";
|
|
124
|
+
const bodyMessage = extractBodyMessage(init.body) ?? "request failed";
|
|
125
|
+
const message = `${prefix}${init.endpoint}: ${init.httpStatus} ${init.code} \u2014 ${bodyMessage}`;
|
|
126
|
+
return new _InflowApiError(message, init);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
function extractBodyMessage(body) {
|
|
130
|
+
if (body !== null && typeof body === "object" && "message" in body) {
|
|
131
|
+
const raw = body.message;
|
|
132
|
+
if (typeof raw === "string" && raw.length > 0) return raw;
|
|
133
|
+
}
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
136
|
+
var X402VersionMismatchError = class extends Error {
|
|
137
|
+
/** Version reported by the server (or `unknown` when the field was absent). */
|
|
138
|
+
receivedVersion;
|
|
139
|
+
/** Endpoint or context that produced the mismatched payload. */
|
|
140
|
+
endpoint;
|
|
141
|
+
/**
|
|
142
|
+
* @param receivedVersion - The `x402Version` value the response carried, or the string `'unknown'` when the field was
|
|
143
|
+
* missing or not a number.
|
|
144
|
+
* @param endpoint - The endpoint path or context the SDK was processing when it saw the version field, used in the
|
|
145
|
+
* generated message.
|
|
146
|
+
*/
|
|
147
|
+
constructor(receivedVersion, endpoint) {
|
|
148
|
+
super(`Expected x402Version ${X402_VERSION}; got ${receivedVersion} on ${endpoint}`);
|
|
149
|
+
this.name = "X402VersionMismatchError";
|
|
150
|
+
this.receivedVersion = receivedVersion;
|
|
151
|
+
this.endpoint = endpoint;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// src/http-client.ts
|
|
156
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
157
|
+
var MAX_RETRIES = 3;
|
|
158
|
+
var RETRY_BASE_DELAY_MS = 200;
|
|
159
|
+
var RETRY_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
160
|
+
var REQUEST_ID_HEADER = "x-request-id";
|
|
161
|
+
var SDK_USER_AGENT = "@inflowpayai/x402 (node)";
|
|
162
|
+
var TIMEOUT_REASON = Object.freeze({ inflowTimeout: true });
|
|
163
|
+
var InflowHttpClient = class {
|
|
164
|
+
/** Resolved base URL (no trailing slash). */
|
|
165
|
+
baseUrl;
|
|
166
|
+
apiKey;
|
|
167
|
+
defaultTimeoutMs;
|
|
168
|
+
fetchImpl;
|
|
169
|
+
/**
|
|
170
|
+
* @param options - {@link InflowClientOptions} or {@link InflowAnonymousClientOptions}. The authed form requires
|
|
171
|
+
* `apiKey` to be a non-empty string; the anonymous form omits it entirely and sends no `X-API-KEY` header.
|
|
172
|
+
* Anonymous mode is used only by `createUnauthenticatedInflowFacilitator` in `@inflowpayai/x402-seller`.
|
|
173
|
+
* @throws {Error} When `apiKey` is present but empty. (Server-side codes are mapped to {@link InflowApiError}; this is
|
|
174
|
+
* a local precondition failure.)
|
|
175
|
+
*/
|
|
176
|
+
constructor(options) {
|
|
177
|
+
if (options.apiKey !== void 0) {
|
|
178
|
+
if (typeof options.apiKey !== "string") {
|
|
179
|
+
throw new Error("InflowHttpClient: `apiKey` must be a non-empty string when provided.");
|
|
180
|
+
}
|
|
181
|
+
const trimmed = options.apiKey.trim();
|
|
182
|
+
if (trimmed.length === 0) {
|
|
183
|
+
throw new Error("InflowHttpClient: `apiKey` must be a non-empty string when provided.");
|
|
184
|
+
}
|
|
185
|
+
this.apiKey = trimmed;
|
|
186
|
+
} else {
|
|
187
|
+
this.apiKey = void 0;
|
|
188
|
+
}
|
|
189
|
+
this.baseUrl = resolveBaseUrl({
|
|
190
|
+
...options.environment !== void 0 ? { environment: options.environment } : {},
|
|
191
|
+
...options.baseUrl !== void 0 ? { baseUrl: options.baseUrl } : {}
|
|
192
|
+
});
|
|
193
|
+
this.defaultTimeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
194
|
+
const f = options.fetch ?? globalThis.fetch;
|
|
195
|
+
this.fetchImpl = f.bind(globalThis);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Issue a `GET` to `path` (relative to {@link InflowHttpClient.baseUrl}) and parse the JSON body.
|
|
199
|
+
*
|
|
200
|
+
* @typeParam T - Expected shape of the parsed body. Not validated at runtime; callers are responsible for narrowing.
|
|
201
|
+
* @param path - Path including leading slash, e.g. `'/v1/x402/config'`.
|
|
202
|
+
* @param options - Per-call overrides.
|
|
203
|
+
* @returns Parsed JSON body cast to `T`.
|
|
204
|
+
* @throws {@link InflowApiError} On any non-2xx response or terminal network error.
|
|
205
|
+
*/
|
|
206
|
+
async get(path, options = {}) {
|
|
207
|
+
return this.request("GET", path, void 0, options);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Issue a `POST` to `path` with a JSON body and parse the JSON response.
|
|
211
|
+
*
|
|
212
|
+
* @typeParam T - Expected shape of the parsed body.
|
|
213
|
+
* @param path - Path including leading slash.
|
|
214
|
+
* @param body - Value serialized via `JSON.stringify`. Pass `undefined` to send an empty body.
|
|
215
|
+
* @param options - Per-call overrides.
|
|
216
|
+
* @returns Parsed JSON body cast to `T`.
|
|
217
|
+
* @throws {@link InflowApiError} On any non-2xx response or terminal network error.
|
|
218
|
+
*/
|
|
219
|
+
async post(path, body, options = {}) {
|
|
220
|
+
return this.request("POST", path, body, options);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Lower-level entry point. Prefer {@link InflowHttpClient.get} / {@link InflowHttpClient.post} unless the verb is one
|
|
224
|
+
* neither covers.
|
|
225
|
+
*
|
|
226
|
+
* @typeParam T - Expected shape of the parsed body.
|
|
227
|
+
* @param method - HTTP verb.
|
|
228
|
+
* @param path - Path including leading slash.
|
|
229
|
+
* @param body - Optional value serialized via `JSON.stringify`.
|
|
230
|
+
* @param options - Per-call overrides.
|
|
231
|
+
* @returns Parsed JSON body cast to `T`.
|
|
232
|
+
*/
|
|
233
|
+
async request(method, path, body, options = {}) {
|
|
234
|
+
const url = `${this.baseUrl}${path}`;
|
|
235
|
+
const maxRetries = Math.min(options.retries ?? MAX_RETRIES, MAX_RETRIES);
|
|
236
|
+
const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;
|
|
237
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
238
|
+
try {
|
|
239
|
+
const response = await this.sendOnce(method, url, body, options.headers, options.signal, timeoutMs);
|
|
240
|
+
if (response.status >= 200 && response.status < 300) {
|
|
241
|
+
return response.body;
|
|
242
|
+
}
|
|
243
|
+
const error = buildApiError(path, response);
|
|
244
|
+
if (RETRY_STATUSES.has(response.status) && attempt < maxRetries) {
|
|
245
|
+
await delay(backoffMs(attempt));
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
throw error;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (err instanceof InflowApiError) throw err;
|
|
251
|
+
if (isRetryableNetworkError(err) && attempt < maxRetries) {
|
|
252
|
+
await delay(backoffMs(attempt));
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
throw buildNetworkError(path, err);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async sendOnce(method, url, body, extraHeaders, callerSignal, timeoutMs) {
|
|
260
|
+
const controller = new AbortController();
|
|
261
|
+
const timeoutId = setTimeout(() => controller.abort(TIMEOUT_REASON), timeoutMs);
|
|
262
|
+
const onAbort = () => controller.abort(callerSignal?.reason);
|
|
263
|
+
if (callerSignal !== void 0) {
|
|
264
|
+
if (callerSignal.aborted) controller.abort(callerSignal.reason);
|
|
265
|
+
else callerSignal.addEventListener("abort", onAbort, { once: true });
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const headers = {
|
|
269
|
+
...this.apiKey !== void 0 ? { "X-API-KEY": this.apiKey } : {},
|
|
270
|
+
Accept: "application/json",
|
|
271
|
+
"User-Agent": SDK_USER_AGENT,
|
|
272
|
+
...extraHeaders ?? {}
|
|
273
|
+
};
|
|
274
|
+
let serialized;
|
|
275
|
+
if (body !== void 0) {
|
|
276
|
+
headers["Content-Type"] = "application/json";
|
|
277
|
+
serialized = JSON.stringify(body);
|
|
278
|
+
}
|
|
279
|
+
const response = await this.fetchImpl(url, {
|
|
280
|
+
method,
|
|
281
|
+
headers,
|
|
282
|
+
...serialized !== void 0 ? { body: serialized } : {},
|
|
283
|
+
signal: controller.signal
|
|
284
|
+
});
|
|
285
|
+
const text = await response.text();
|
|
286
|
+
const parsed = parseJsonOrText(text, response.headers.get("content-type"));
|
|
287
|
+
return { status: response.status, headers: response.headers, body: parsed };
|
|
288
|
+
} finally {
|
|
289
|
+
clearTimeout(timeoutId);
|
|
290
|
+
if (callerSignal !== void 0) callerSignal.removeEventListener("abort", onAbort);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
function parseJsonOrText(text, contentType) {
|
|
295
|
+
if (text.length === 0) return void 0;
|
|
296
|
+
if (contentType !== null && contentType.includes("application/json")) {
|
|
297
|
+
try {
|
|
298
|
+
return JSON.parse(text);
|
|
299
|
+
} catch {
|
|
300
|
+
return text;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (text.startsWith("{") || text.startsWith("[")) {
|
|
304
|
+
try {
|
|
305
|
+
return JSON.parse(text);
|
|
306
|
+
} catch {
|
|
307
|
+
return text;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return text;
|
|
311
|
+
}
|
|
312
|
+
function buildApiError(path, response) {
|
|
313
|
+
const requestId = readHeader(response.headers, REQUEST_ID_HEADER);
|
|
314
|
+
const code = extractCode(response.body);
|
|
315
|
+
return InflowApiError.from({
|
|
316
|
+
code,
|
|
317
|
+
httpStatus: response.status,
|
|
318
|
+
endpoint: path,
|
|
319
|
+
...requestId !== void 0 ? { requestId } : {},
|
|
320
|
+
body: response.body,
|
|
321
|
+
headers: response.headers
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
function buildNetworkError(path, cause) {
|
|
325
|
+
const isTimeout = isTimeoutReason(cause);
|
|
326
|
+
const reason = isTimeout ? "request timed out" : cause instanceof Error ? cause.message : String(cause);
|
|
327
|
+
return new InflowApiError(`${path}: network error \u2014 ${reason}`, {
|
|
328
|
+
code: isTimeout ? "TIMEOUT" : "NETWORK_ERROR",
|
|
329
|
+
httpStatus: 0,
|
|
330
|
+
endpoint: path,
|
|
331
|
+
cause
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
function isTimeoutReason(value) {
|
|
335
|
+
if (value === TIMEOUT_REASON) return true;
|
|
336
|
+
if (typeof value === "object" && value !== null && "cause" in value) {
|
|
337
|
+
if (value.cause === TIMEOUT_REASON) return true;
|
|
338
|
+
}
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
function extractCode(body) {
|
|
342
|
+
if (body !== null && typeof body === "object" && "code" in body) {
|
|
343
|
+
const raw = body.code;
|
|
344
|
+
if (typeof raw === "string" && raw.length > 0) return raw;
|
|
345
|
+
}
|
|
346
|
+
return "UNEXPECTED_ERROR";
|
|
347
|
+
}
|
|
348
|
+
function isRetryableNetworkError(err) {
|
|
349
|
+
if (!(err instanceof Error)) return false;
|
|
350
|
+
if (err.name === "AbortError") {
|
|
351
|
+
return isTimeoutReason(err);
|
|
352
|
+
}
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
function backoffMs(attempt) {
|
|
356
|
+
const base = RETRY_BASE_DELAY_MS * 2 ** attempt;
|
|
357
|
+
const jitter = Math.floor(Math.random() * (base / 4));
|
|
358
|
+
return base + jitter;
|
|
359
|
+
}
|
|
360
|
+
function delay(ms) {
|
|
361
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
362
|
+
}
|
|
363
|
+
var PAYMENT_ID_MIN_LENGTH = 16;
|
|
364
|
+
var PAYMENT_ID_MAX_LENGTH = 128;
|
|
365
|
+
var PAYMENT_ID_REGEX = /^[a-zA-Z0-9_-]+$/u;
|
|
366
|
+
var PAYMENT_ID_PREFIX_REGEX = /^[a-zA-Z0-9_-]*$/u;
|
|
367
|
+
var PAYMENT_ID_DEFAULT_PREFIX = "pay_";
|
|
368
|
+
function validatePaymentId(id) {
|
|
369
|
+
if (typeof id !== "string") return false;
|
|
370
|
+
if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) return false;
|
|
371
|
+
return PAYMENT_ID_REGEX.test(id);
|
|
372
|
+
}
|
|
373
|
+
function generatePaymentId(prefix = PAYMENT_ID_DEFAULT_PREFIX) {
|
|
374
|
+
if (typeof prefix !== "string" || !PAYMENT_ID_PREFIX_REGEX.test(prefix)) {
|
|
375
|
+
throw new Error(`generatePaymentId: prefix "${prefix}" contains characters outside ${PAYMENT_ID_REGEX.source}`);
|
|
376
|
+
}
|
|
377
|
+
const suffix = crypto.randomBytes(16).toString("hex");
|
|
378
|
+
const id = `${prefix}${suffix}`;
|
|
379
|
+
if (id.length < PAYMENT_ID_MIN_LENGTH || id.length > PAYMENT_ID_MAX_LENGTH) {
|
|
380
|
+
throw new Error(
|
|
381
|
+
`generatePaymentId: result length ${id.length} is outside [${PAYMENT_ID_MIN_LENGTH}, ${PAYMENT_ID_MAX_LENGTH}]`
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
return id;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// src/types.ts
|
|
388
|
+
function isBalancePayload(p) {
|
|
389
|
+
return p.accepted.scheme === "balance";
|
|
390
|
+
}
|
|
391
|
+
function isExactPayload(p) {
|
|
392
|
+
return p.accepted.scheme === "exact" && typeof p.payload.authorization === "object";
|
|
393
|
+
}
|
|
394
|
+
function isPermit2Payload(p) {
|
|
395
|
+
return p.accepted.scheme === "exact" && typeof p.payload.permit2Authorization === "object";
|
|
396
|
+
}
|
|
397
|
+
function isInstrumentPayload(p) {
|
|
398
|
+
return p.accepted.scheme === "instrument";
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
exports.ASSET_TRANSFER_METHODS = ASSET_TRANSFER_METHODS;
|
|
402
|
+
exports.CONTRACTS = CONTRACTS;
|
|
403
|
+
exports.EXTRA_KEYS = EXTRA_KEYS;
|
|
404
|
+
exports.HEADERS = HEADERS;
|
|
405
|
+
exports.InflowApiError = InflowApiError;
|
|
406
|
+
exports.InflowHttpClient = InflowHttpClient;
|
|
407
|
+
exports.NETWORKS = NETWORKS;
|
|
408
|
+
exports.PAYLOAD_KEYS = PAYLOAD_KEYS;
|
|
409
|
+
exports.SCHEMES = SCHEMES;
|
|
410
|
+
exports.X402VersionMismatchError = X402VersionMismatchError;
|
|
411
|
+
exports.X402_VERSION = X402_VERSION;
|
|
412
|
+
exports.generatePaymentId = generatePaymentId;
|
|
413
|
+
exports.isBalancePayload = isBalancePayload;
|
|
414
|
+
exports.isExactPayload = isExactPayload;
|
|
415
|
+
exports.isInstrumentPayload = isInstrumentPayload;
|
|
416
|
+
exports.isPermit2Payload = isPermit2Payload;
|
|
417
|
+
exports.readHeader = readHeader;
|
|
418
|
+
exports.resolveBaseUrl = resolveBaseUrl;
|
|
419
|
+
exports.validatePaymentId = validatePaymentId;
|
|
420
|
+
//# sourceMappingURL=index.cjs.map
|
|
421
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/environment.ts","../src/errors.ts","../src/http-client.ts","../src/extensions/payment-identifier.ts","../src/types.ts"],"names":["randomBytes"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * X402 protocol version emitted on every outbound SDK request and required on every inbound response. Responses\n * advertising a different version are rejected at the boundary with {@link X402VersionMismatchError}.\n */\nexport const X402_VERSION = 2 as const;\n\n/**\n * V2 spec header names. Emitted verbatim on the write path; read via {@link readHeader} (case-insensitive). Header\n * values use the standard base64 alphabet (`A-Z`, `a-z`, `0-9`, `+`, `/`) with `=` padding — not base64url.\n */\nexport const HEADERS = {\n PAYMENT_REQUIRED: 'PAYMENT-REQUIRED',\n PAYMENT_RESPONSE: 'PAYMENT-RESPONSE',\n PAYMENT_SIGNATURE: 'PAYMENT-SIGNATURE',\n} as const;\n\n/**\n * Payment-scheme identifiers carried in `PaymentRequirements.scheme` and `PaymentPayload.accepted.scheme`.\n *\n * `INSTRUMENT` is a reserved value: it is present in the type union for forward compatibility, and the SDK rejects it\n * at runtime with a typed error if reached.\n */\nexport const SCHEMES = {\n BALANCE: 'balance',\n EXACT: 'exact',\n INSTRUMENT: 'instrument',\n} as const;\n\n/**\n * Canonical Permit2Proxy and Permit2 addresses. Identical on every supported EVM chain (CREATE2-deployed). Use for the\n * buyer-side verification fallback when `PaymentRequirements.extra.permit2Proxy` is absent.\n */\nexport const CONTRACTS = {\n PERMIT2_PROXY: '0x402085c248EeA27D92E8b30b2C58ed07f9E20001',\n PERMIT2: '0x000000000022D473030F116dDEE9F6B43aC78BA3',\n} as const;\n\n/**\n * Reserved network identifiers. CAIP-2 shaped `<namespace>:<reference>`. Only InFlow's internal ledger is enumerated;\n * on-chain network ids (`eip155:8453`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`, …) are sourced at runtime from\n * `X402ConfigResponse.assets[*].network` and `wallets[*].network`.\n */\nexport const NETWORKS = {\n INFLOW: 'inflow:1',\n} as const;\n\n/** Well-known keys read from `PaymentRequirements.extra` and `PaymentMethodInfo.extra`. */\nexport const EXTRA_KEYS = {\n ASSET_TRANSFER_METHOD: 'assetTransferMethod',\n FEE_PAYER: 'feePayer',\n NAME: 'name',\n PERMIT2_PROXY: 'permit2Proxy',\n VERSION: 'version',\n} as const;\n\n/** Well-known keys read from `PaymentPayload.payload`. */\nexport const PAYLOAD_KEYS = {\n TRANSACTION_ID: 'transactionId',\n} as const;\n\n/** Values that can appear in `PaymentRequirements.extra.assetTransferMethod`. */\nexport const ASSET_TRANSFER_METHODS = {\n EIP3009: 'eip3009',\n PERMIT2: 'permit2',\n SOLANA: 'solana',\n} as const;\n\n/**\n * Header bag accepted by {@link readHeader}. Covers WHATWG `Headers`, Node's `IncomingHttpHeaders`-style records (where\n * values may be string arrays or undefined), and plain string-valued records.\n */\nexport type HeaderBag = Headers | Record<string, string | readonly string[] | undefined>;\n\n/**\n * Read a single header value case-insensitively. Returns `undefined` when the header is absent. For Node-style headers\n * whose value is an array, returns the first element.\n *\n * @param headers - The header bag to read from.\n * @param name - The header name. Matched case-insensitively against the keys in `headers`.\n * @returns The header value, or `undefined` if missing.\n */\nexport function readHeader(headers: HeaderBag, name: string): string | undefined {\n const target = name.toLowerCase();\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n return headers.get(name) ?? undefined;\n }\n const record = headers as Record<string, string | readonly string[] | undefined>;\n for (const key of Object.keys(record)) {\n if (key.toLowerCase() !== target) continue;\n const value = record[key];\n if (value === undefined) return undefined;\n if (typeof value === 'string') return value;\n return value[0];\n }\n return undefined;\n}\n","/** Public InFlow environments addressable by the SDK without an explicit `baseUrl` override. */\nexport type Environment = 'production' | 'sandbox';\n\nconst URLS: Readonly<Record<Environment, string>> = {\n production: 'https://api.inflowpay.ai',\n sandbox: 'https://sandbox.inflowpay.ai',\n};\n\n/** Options consumed by {@link resolveBaseUrl}. */\nexport interface ResolveBaseUrlOptions {\n /** Selects one of the public environments. Defaults to `'production'`. */\n environment?: Environment;\n /** Override the environment-derived URL entirely. Trailing slashes are stripped. Takes precedence over `environment`. */\n baseUrl?: string;\n}\n\n/**\n * Resolve the InFlow API base URL the SDK will issue requests against.\n *\n * @param options - {@link ResolveBaseUrlOptions}. `baseUrl` wins over `environment`. With neither set, falls back to the\n * production URL.\n * @returns The base URL with any trailing slashes stripped, suitable for appending request paths.\n */\nexport function resolveBaseUrl(options: ResolveBaseUrlOptions = {}): string {\n if (options.baseUrl !== undefined && options.baseUrl !== '') {\n return options.baseUrl.replace(/\\/+$/, '');\n }\n return URLS[options.environment ?? 'production'];\n}\n","import { X402_VERSION } from './constants.js';\n\n/**\n * Header names whose values must be stripped before storing on {@link InflowApiError.headers}. Comparison is\n * case-insensitive.\n */\nconst SENSITIVE_HEADER_NAMES: ReadonlySet<string> = new Set(['authorization', 'cookie', 'set-cookie', 'x-api-key']);\n\n/**\n * Strip sensitive header values from a raw header bag and return a frozen record of the remaining headers, keyed by\n * their original lowercased name.\n */\nfunction sanitizeHeaders(\n raw: Headers | Record<string, string | readonly string[] | undefined> | undefined,\n): Readonly<Record<string, string>> | undefined {\n if (raw === undefined) return undefined;\n const out: Record<string, string> = {};\n const append = (name: string, value: string | readonly string[] | undefined): void => {\n if (value === undefined) return;\n if (SENSITIVE_HEADER_NAMES.has(name.toLowerCase())) return;\n out[name.toLowerCase()] = Array.isArray(value) ? value.join(', ') : (value as string);\n };\n if (typeof Headers !== 'undefined' && raw instanceof Headers) {\n raw.forEach((value, name) => append(name, value));\n } else {\n const record = raw as Record<string, string | readonly string[] | undefined>;\n for (const name of Object.keys(record)) {\n append(name, record[name]);\n }\n }\n return Object.freeze(out);\n}\n\n/**\n * Constructor parameters for {@link InflowApiError}. Every field except `message` corresponds to an attribute carried on\n * the resulting error instance.\n */\nexport interface InflowApiErrorInit {\n /**\n * Application-level error code extracted from the response body's `code` field. Falls back to `'UNEXPECTED_ERROR'`\n * when the body did not carry a code. Specific values consumers may branch on include `INSUFFICIENT_FUNDS`,\n * `PARAMETER_REQUIRED`, `PARAMETER_INVALID`, `BLOCKCHAIN_NOT_FOUND`, and `USER_NOT_FOUND`.\n */\n code: string;\n /** HTTP status of the failing response. */\n httpStatus: number;\n /** Endpoint path (relative to the base URL) that produced the failure. */\n endpoint: string;\n /**\n * Server-issued correlation ID, read from `X-Request-Id` on the response. `undefined` when the server did not emit\n * one.\n */\n requestId?: string;\n /** Underlying error (e.g. a `fetch` rejection) when this wraps another. */\n cause?: unknown;\n /** Parsed JSON body when the response was JSON; raw text otherwise. */\n body?: unknown;\n /** Response headers with sensitive entries (`authorization`, `cookie`, `set-cookie`, `x-api-key`) stripped. */\n headers?: Headers | Record<string, string | readonly string[] | undefined>;\n}\n\n/**\n * Error thrown by every {@link InflowHttpClient} call on a non-2xx response. Carries the server-issued correlation ID\n * when available and the (sanitized) response body and headers for diagnostics.\n */\nexport class InflowApiError extends Error {\n /** {@inheritDoc InflowApiErrorInit.code} */\n readonly code: string;\n /** {@inheritDoc InflowApiErrorInit.httpStatus} */\n readonly httpStatus: number;\n /** {@inheritDoc InflowApiErrorInit.endpoint} */\n readonly endpoint: string;\n /** {@inheritDoc InflowApiErrorInit.requestId} */\n readonly requestId?: string;\n /** {@inheritDoc InflowApiErrorInit.body} */\n readonly body?: unknown;\n /** {@inheritDoc InflowApiErrorInit.headers} */\n readonly headers?: Readonly<Record<string, string>>;\n\n /**\n * @param message - Human-readable message. Callers should prefer the factory {@link InflowApiError.from} which\n * composes a standard message shape including endpoint, status, code, and request ID.\n * @param init - Structured fields carried on the resulting instance.\n */\n constructor(message: string, init: InflowApiErrorInit) {\n super(message, init.cause === undefined ? undefined : { cause: init.cause });\n this.name = 'InflowApiError';\n this.code = init.code;\n this.httpStatus = init.httpStatus;\n this.endpoint = init.endpoint;\n if (init.requestId !== undefined) this.requestId = init.requestId;\n if (init.body !== undefined) this.body = init.body;\n const headers = sanitizeHeaders(init.headers);\n if (headers !== undefined) this.headers = headers;\n }\n\n /**\n * Compose an {@link InflowApiError} with a standard message shape.\n *\n * Format: `[<requestId>] <endpoint>: <httpStatus> <code> — <bodyMessage>`, where `<requestId>` is omitted when\n * missing and `<bodyMessage>` falls back to a generic `request failed` when the body had no `message` field.\n */\n static from(init: InflowApiErrorInit): InflowApiError {\n const prefix = init.requestId !== undefined ? `[${init.requestId}] ` : '';\n const bodyMessage = extractBodyMessage(init.body) ?? 'request failed';\n const message = `${prefix}${init.endpoint}: ${init.httpStatus} ${init.code} — ${bodyMessage}`;\n return new InflowApiError(message, init);\n }\n}\n\nfunction extractBodyMessage(body: unknown): string | undefined {\n if (body !== null && typeof body === 'object' && 'message' in body) {\n const raw = body.message;\n if (typeof raw === 'string' && raw.length > 0) return raw;\n }\n return undefined;\n}\n\n/**\n * Thrown when a response advertises an `x402Version` other than the SDK's supported version ({@link X402_VERSION} = 2).\n * The SDK does not attempt version negotiation: only V2 is supported and any other value is a hard error so consumers\n * see the mismatch at the boundary instead of as a silent decode failure deeper in.\n */\nexport class X402VersionMismatchError extends Error {\n /** Version reported by the server (or `unknown` when the field was absent). */\n readonly receivedVersion: number | 'unknown';\n /** Endpoint or context that produced the mismatched payload. */\n readonly endpoint: string;\n\n /**\n * @param receivedVersion - The `x402Version` value the response carried, or the string `'unknown'` when the field was\n * missing or not a number.\n * @param endpoint - The endpoint path or context the SDK was processing when it saw the version field, used in the\n * generated message.\n */\n constructor(receivedVersion: number | 'unknown', endpoint: string) {\n super(`Expected x402Version ${X402_VERSION}; got ${receivedVersion} on ${endpoint}`);\n this.name = 'X402VersionMismatchError';\n this.receivedVersion = receivedVersion;\n this.endpoint = endpoint;\n }\n}\n","import { readHeader } from './constants.js';\nimport type { Environment } from './environment.js';\nimport { resolveBaseUrl } from './environment.js';\nimport { InflowApiError } from './errors.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_RETRIES = 3;\nconst RETRY_BASE_DELAY_MS = 200;\nconst RETRY_STATUSES: ReadonlySet<number> = new Set([429, 502, 503, 504]);\nconst REQUEST_ID_HEADER = 'x-request-id';\nconst SDK_USER_AGENT = '@inflowpayai/x402 (node)';\n\n/**\n * Sentinel object passed to `AbortController.abort()` when the SDK-internal timeout fires. Identity-compared in\n * {@link isRetryableNetworkError} and {@link buildNetworkError} to distinguish a timeout from caller-driven aborts and\n * arbitrary network failures, without relying on string matching the `.message`.\n */\nconst TIMEOUT_REASON: { readonly inflowTimeout: true } = Object.freeze({ inflowTimeout: true });\n\n/**\n * Options accepted by {@link InflowHttpClient}'s constructor and shared by higher-level facilitator and signer clients\n * in the seller and buyer packages.\n */\nexport interface InflowClientOptions {\n /** InFlow API key sent on every request as `X-API-KEY`. */\n apiKey: string;\n /** Selects one of the public environments. Defaults to `'production'`. */\n environment?: Environment;\n /** Override the environment-derived URL. Takes precedence over `environment`. */\n baseUrl?: string;\n /**\n * Per-request timeout, milliseconds. Defaults to 30 000. The timer covers the whole `fetch` plus body read; on expiry\n * the request is aborted and an `InflowApiError` with `code: 'TIMEOUT'` is thrown.\n */\n timeoutMs?: number;\n /**\n * Optional `fetch` implementation. Defaults to `globalThis.fetch`. Useful for routing through a corporate proxy,\n * attaching OpenTelemetry instrumentation, or stubbing at the SDK boundary in tests. The injected function must\n * conform to the WHATWG fetch API.\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Options accepted by {@link InflowHttpClient} when constructed without an API key. Only used by the seller-side\n * `createUnauthenticatedInflowFacilitator` factory; buyer-side flows and the seller client never construct anonymous\n * transports. Sends no `X-API-KEY` header on outbound requests.\n */\nexport interface InflowAnonymousClientOptions {\n /** Marker field — must be omitted or `undefined`. */\n apiKey?: undefined;\n /** Selects one of the public environments. Defaults to `'production'`. */\n environment?: Environment;\n /** Override the environment-derived URL. Takes precedence over `environment`. */\n baseUrl?: string;\n /** Per-request timeout, milliseconds. Defaults to 30 000. */\n timeoutMs?: number;\n /** Optional `fetch` implementation. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\n/** Per-call overrides accepted by {@link InflowHttpClient}'s request methods. */\nexport interface RequestOptions {\n /**\n * Maximum retry attempts on transient failures (HTTP 429, 502, 503, 504, and network errors). Capped at 3. Pass `0`\n * to disable retries — used by the buyer signer's polling loop, where the outer poller controls retry semantics.\n */\n retries?: number;\n /** Override the client-level `timeoutMs` for this call. */\n timeoutMs?: number;\n /** Additional headers merged on top of the SDK's standard headers. */\n headers?: Record<string, string>;\n /**\n * AbortSignal for caller-driven cancellation. Composes with the request-internal timeout signal; whichever fires\n * first aborts the request.\n */\n signal?: AbortSignal;\n}\n\ninterface ParsedResponse {\n status: number;\n headers: Headers;\n body: unknown;\n}\n\n/**\n * HTTP client used by every other package in this monorepo to talk to `api.inflowpay.ai`. Carries `apiKey` injection,\n * retry on transient statuses (429, 502, 503, 504) with exponential backoff capped at three attempts, request timeout,\n * JSON parsing, and error mapping into {@link InflowApiError}.\n *\n * Construct one instance per `(apiKey, environment)` pair and share it across requests.\n */\nexport class InflowHttpClient {\n /** Resolved base URL (no trailing slash). */\n readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly defaultTimeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n /**\n * @param options - {@link InflowClientOptions} or {@link InflowAnonymousClientOptions}. The authed form requires\n * `apiKey` to be a non-empty string; the anonymous form omits it entirely and sends no `X-API-KEY` header.\n * Anonymous mode is used only by `createUnauthenticatedInflowFacilitator` in `@inflowpayai/x402-seller`.\n * @throws {Error} When `apiKey` is present but empty. (Server-side codes are mapped to {@link InflowApiError}; this is\n * a local precondition failure.)\n */\n constructor(options: InflowClientOptions | InflowAnonymousClientOptions) {\n if (options.apiKey !== undefined) {\n if (typeof options.apiKey !== 'string') {\n throw new Error('InflowHttpClient: `apiKey` must be a non-empty string when provided.');\n }\n const trimmed = options.apiKey.trim();\n if (trimmed.length === 0) {\n throw new Error('InflowHttpClient: `apiKey` must be a non-empty string when provided.');\n }\n this.apiKey = trimmed;\n } else {\n this.apiKey = undefined;\n }\n this.baseUrl = resolveBaseUrl({\n ...(options.environment !== undefined ? { environment: options.environment } : {}),\n ...(options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {}),\n });\n this.defaultTimeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const f = options.fetch ?? globalThis.fetch;\n this.fetchImpl = f.bind(globalThis);\n }\n\n /**\n * Issue a `GET` to `path` (relative to {@link InflowHttpClient.baseUrl}) and parse the JSON body.\n *\n * @typeParam T - Expected shape of the parsed body. Not validated at runtime; callers are responsible for narrowing.\n * @param path - Path including leading slash, e.g. `'/v1/x402/config'`.\n * @param options - Per-call overrides.\n * @returns Parsed JSON body cast to `T`.\n * @throws {@link InflowApiError} On any non-2xx response or terminal network error.\n */\n async get<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return this.request<T>('GET', path, undefined, options);\n }\n\n /**\n * Issue a `POST` to `path` with a JSON body and parse the JSON response.\n *\n * @typeParam T - Expected shape of the parsed body.\n * @param path - Path including leading slash.\n * @param body - Value serialized via `JSON.stringify`. Pass `undefined` to send an empty body.\n * @param options - Per-call overrides.\n * @returns Parsed JSON body cast to `T`.\n * @throws {@link InflowApiError} On any non-2xx response or terminal network error.\n */\n async post<T>(path: string, body: unknown, options: RequestOptions = {}): Promise<T> {\n return this.request<T>('POST', path, body, options);\n }\n\n /**\n * Lower-level entry point. Prefer {@link InflowHttpClient.get} / {@link InflowHttpClient.post} unless the verb is one\n * neither covers.\n *\n * @typeParam T - Expected shape of the parsed body.\n * @param method - HTTP verb.\n * @param path - Path including leading slash.\n * @param body - Optional value serialized via `JSON.stringify`.\n * @param options - Per-call overrides.\n * @returns Parsed JSON body cast to `T`.\n */\n async request<T>(method: string, path: string, body: unknown, options: RequestOptions = {}): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const maxRetries = Math.min(options.retries ?? MAX_RETRIES, MAX_RETRIES);\n const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;\n\n // Single-exit loop: the function either returns a parsed body on\n // 2xx or throws an InflowApiError. The retry budget is consumed\n // inline; when it's exhausted the catch / branch falls through to\n // the final throw, so there's no unreachable \"fallback\" throw\n // after the loop.\n for (let attempt = 0; ; attempt += 1) {\n try {\n const response = await this.sendOnce(method, url, body, options.headers, options.signal, timeoutMs);\n if (response.status >= 200 && response.status < 300) {\n return response.body as T;\n }\n const error = buildApiError(path, response);\n if (RETRY_STATUSES.has(response.status) && attempt < maxRetries) {\n await delay(backoffMs(attempt));\n continue;\n }\n throw error;\n } catch (err) {\n if (err instanceof InflowApiError) throw err;\n if (isRetryableNetworkError(err) && attempt < maxRetries) {\n await delay(backoffMs(attempt));\n continue;\n }\n throw buildNetworkError(path, err);\n }\n }\n }\n\n private async sendOnce(\n method: string,\n url: string,\n body: unknown,\n extraHeaders: Record<string, string> | undefined,\n callerSignal: AbortSignal | undefined,\n timeoutMs: number,\n ): Promise<ParsedResponse> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(TIMEOUT_REASON), timeoutMs);\n const onAbort = (): void => controller.abort(callerSignal?.reason);\n if (callerSignal !== undefined) {\n if (callerSignal.aborted) controller.abort(callerSignal.reason);\n else callerSignal.addEventListener('abort', onAbort, { once: true });\n }\n try {\n const headers: Record<string, string> = {\n ...(this.apiKey !== undefined ? { 'X-API-KEY': this.apiKey } : {}),\n Accept: 'application/json',\n 'User-Agent': SDK_USER_AGENT,\n ...(extraHeaders ?? {}),\n };\n let serialized: string | undefined;\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n serialized = JSON.stringify(body);\n }\n const response = await this.fetchImpl(url, {\n method,\n headers,\n ...(serialized !== undefined ? { body: serialized } : {}),\n signal: controller.signal,\n });\n const text = await response.text();\n const parsed = parseJsonOrText(text, response.headers.get('content-type'));\n return { status: response.status, headers: response.headers, body: parsed };\n } finally {\n clearTimeout(timeoutId);\n if (callerSignal !== undefined) callerSignal.removeEventListener('abort', onAbort);\n }\n }\n}\n\nfunction parseJsonOrText(text: string, contentType: string | null): unknown {\n if (text.length === 0) return undefined;\n if (contentType !== null && contentType.includes('application/json')) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n // Best-effort JSON parse for servers that omit content-type.\n if (text.startsWith('{') || text.startsWith('[')) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n\nfunction buildApiError(path: string, response: ParsedResponse): InflowApiError {\n const requestId = readHeader(response.headers, REQUEST_ID_HEADER);\n const code = extractCode(response.body);\n return InflowApiError.from({\n code,\n httpStatus: response.status,\n endpoint: path,\n ...(requestId !== undefined ? { requestId } : {}),\n body: response.body,\n headers: response.headers,\n });\n}\n\nfunction buildNetworkError(path: string, cause: unknown): InflowApiError {\n const isTimeout = isTimeoutReason(cause);\n const reason = isTimeout ? 'request timed out' : cause instanceof Error ? cause.message : String(cause);\n return new InflowApiError(`${path}: network error — ${reason}`, {\n code: isTimeout ? 'TIMEOUT' : 'NETWORK_ERROR',\n httpStatus: 0,\n endpoint: path,\n cause,\n });\n}\n\n/**\n * Identity check for the internal timeout sentinel. Looks at the raw `cause` value, and at `err.cause` when the runtime\n * has wrapped the abort reason in a `DOMException` / `AbortError`. The latter shape is what Node 20+ surfaces from\n * `fetch` when the controller fires.\n */\nfunction isTimeoutReason(value: unknown): boolean {\n if (value === TIMEOUT_REASON) return true;\n if (typeof value === 'object' && value !== null && 'cause' in value) {\n if (value.cause === TIMEOUT_REASON) return true;\n }\n return false;\n}\n\nfunction extractCode(body: unknown): string {\n if (body !== null && typeof body === 'object' && 'code' in body) {\n const raw = body.code;\n if (typeof raw === 'string' && raw.length > 0) return raw;\n }\n return 'UNEXPECTED_ERROR';\n}\n\nfunction isRetryableNetworkError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n // Timeouts and connection-reset / unreachable errors are retryable;\n // abort triggered by the caller's own signal is not. Identity-compare\n // the abort `cause` against TIMEOUT_REASON instead of relying on the\n // error's `.message` (which the runtime can rewrite between versions).\n if (err.name === 'AbortError') {\n return isTimeoutReason(err);\n }\n return true;\n}\n\nfunction backoffMs(attempt: number): number {\n // 200 ms, 400 ms, 800 ms with a small jitter so concurrent callers don't\n // resynchronise.\n const base = RETRY_BASE_DELAY_MS * 2 ** attempt;\n const jitter = Math.floor(Math.random() * (base / 4));\n return base + jitter;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","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","// V2 wire-shape types and InFlow-specific response/request shapes.\n//\n// `network` is typed as `string` throughout (not `@x402/core`'s\n// `${string}:${string}` template literal). Every InFlow value — both\n// CAIP-2 chain ids (`eip155:8453`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`, …) and the\n// `'inflow:1'` ledger literal — is CAIP-2 shaped, but the SDK declines\n// to narrow the type so consumer code can route opaque network strings\n// without TS-level pattern checks.\n\nimport type { ResourceInfo, VerifyResponse } from '@x402/core/types';\n\nexport type { ResourceInfo, VerifyResponse };\n\n/**\n * Payment-scheme identifier carried on the wire. `'exact'` covers EIP-3009 and Permit2 EVM transfers as well as non-EVM\n * signed transfers; `'balance'` covers InFlow internal balance transfers; `'instrument'` is reserved.\n *\n * The `(string & {})` branch keeps editor autocomplete focused on the known values while still accepting any string at\n * runtime, so consumers can interoperate with future schemes the SDK hasn't yet enumerated.\n */\nexport type PaymentScheme = 'exact' | 'balance' | 'instrument' | (string & {});\n\n/** Funding-source type carried in `instrument`-scheme payloads and extras. Reserved for future use. */\nexport type InstrumentType = 'card' | 'bank' | (string & {});\n\n/**\n * A single entry in `PaymentRequired.accepts[]`. Describes one acceptable way for a buyer to pay the protected\n * resource: a scheme, a network, the payee address, the asset (when applicable), the atomic-unit amount, and\n * scheme-specific extras.\n */\nexport interface PaymentRequirements {\n /** Payment scheme — `'exact'`, `'balance'`, or `'instrument'`. */\n scheme: PaymentScheme;\n /**\n * CAIP-2 network identifier. `'eip155:8453'` and `'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'` for blockchain networks;\n * `'inflow:1'` for InFlow's internal ledger (balance and reserved instrument schemes).\n */\n network: string;\n /** On-chain contract address or mint. Empty string when not applicable. */\n asset: string;\n /** Amount in atomic units of `asset` (or the method's own decimal scale). */\n amount: string;\n /** Recipient — wallet address for blockchain schemes, seller UUID for balance/instrument. */\n payTo: string;\n /** Maximum lifetime (seconds) the requirement is valid for. */\n maxTimeoutSeconds: number;\n /**\n * Scheme-specific extras (EIP-712 domain, asset transfer method, fee payer, etc.). Optional on the wire — the server\n * omits it when no extras apply (e.g. some `balance`-scheme entries). Use the typed accessors in\n * `@inflowpayai/x402/extras` for safe reads under `noUncheckedIndexedAccess`.\n */\n extra?: Record<string, unknown>;\n}\n\n/** The 402-response body. Sent by the seller as a base64 JSON encoding in the `PAYMENT-REQUIRED` header. */\nexport interface PaymentRequired {\n /** Protocol version — always `2`. */\n x402Version: number;\n /** Optional human-readable error context attached by the seller. */\n error?: string;\n /** Information about the protected resource. */\n resource: ResourceInfo;\n /** The set of acceptable payment options. The buyer chooses one. */\n accepts: PaymentRequirements[];\n /** Per-response extension declarations, keyed by extension name. */\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Inner payload shape for the `'balance'` scheme. Balance payments are not cryptographically signed because settlement\n * is an internal ledger transfer rather than a verifiable on-chain action.\n */\nexport interface BalancePayloadData {\n /** InFlow transaction UUID — the only field carried on the wire. */\n transactionId: string;\n}\n\n/**\n * EIP-3009 (`transferWithAuthorization`) wire shape of the `'exact'` scheme. The Permit2 variant lives on\n * {@link Permit2PayloadData}.\n */\nexport interface ExactPayloadData {\n /** EIP-3009 `TransferWithAuthorization` typed-data message. */\n authorization: {\n /** Payer address; signs `authorization`. */\n from: string;\n /** Recipient (the seller's `payTo`). */\n to: string;\n /** Atomic-unit amount (decimal string). */\n value: string;\n /** Unix-seconds lower bound for facilitator submission. */\n validAfter: string;\n /** Unix-seconds upper bound (matches `maxTimeoutSeconds`). */\n validBefore: string;\n /** 32-byte hex; the payer must not have used it before. */\n nonce: string;\n };\n /** 65-byte EIP-712 ECDSA signature over `authorization`. */\n signature: string;\n}\n\n/** Inner payload shape for the `'instrument'` scheme. Reserved. */\nexport interface InstrumentPayloadData {\n transactionId: string;\n signature: string;\n instrumentId?: string;\n instrumentType?: InstrumentType;\n}\n\n/**\n * Permit2 variant of the `'exact'` scheme inner payload. See the [x402 EVM exact scheme\n * spec](https://github.com/coinbase/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md). `spender` must be the\n * canonical x402ExactPermit2Proxy (see {@link CONTRACTS}); the InFlow facilitator rejects custom spenders.\n */\nexport interface Permit2PayloadData {\n signature: string;\n permit2Authorization: {\n permitted: { token: string; amount: string };\n from: string;\n spender: string;\n nonce: string;\n deadline: string;\n witness: { to: string; validAfter: string; extra: string };\n };\n}\n\n/**\n * Discriminated union of known inner-payload shapes. The catch-all `Record<string, unknown>` branch keeps the type open\n * for forward- compatible schemes the SDK hasn't yet enumerated.\n */\nexport type InflowPaymentPayloadData =\n | BalancePayloadData\n | ExactPayloadData\n | Permit2PayloadData\n | InstrumentPayloadData\n | Record<string, unknown>;\n\n/**\n * The signed payment envelope a buyer sends to the seller in the `PAYMENT-SIGNATURE` header (base64 JSON). Narrow on\n * `accepted.scheme` to discriminate `payload`.\n */\nexport interface InflowPaymentPayload {\n /** Protocol version — always `2`. */\n x402Version: number;\n /** The {@link PaymentRequirements} the buyer chose. */\n accepted: PaymentRequirements;\n /** Scheme-specific signed (or pseudo-signed) inner payload. */\n payload: InflowPaymentPayloadData;\n /** Per-payload extension data, keyed by extension name. */\n extensions?: Record<string, unknown>;\n /** Optional resource info echoed back by the buyer. */\n resource?: ResourceInfo;\n}\n\n/** Narrows to the `'balance'` scheme branch. */\nexport function isBalancePayload(p: InflowPaymentPayload): p is InflowPaymentPayload & { payload: BalancePayloadData } {\n return p.accepted.scheme === 'balance';\n}\n\n/**\n * Narrows to the EIP-3009 variant of the `'exact'` scheme. The two `'exact'` variants split on transfer method — use\n * alongside {@link isPermit2Payload}.\n */\nexport function isExactPayload(p: InflowPaymentPayload): p is InflowPaymentPayload & { payload: ExactPayloadData } {\n return p.accepted.scheme === 'exact' && typeof (p.payload as { authorization?: unknown }).authorization === 'object';\n}\n\n/**\n * Narrows to the Permit2 variant of the `'exact'` scheme. The two `'exact'` variants split on transfer method — use\n * alongside {@link isExactPayload}.\n */\nexport function isPermit2Payload(p: InflowPaymentPayload): p is InflowPaymentPayload & { payload: Permit2PayloadData } {\n return (\n p.accepted.scheme === 'exact' &&\n typeof (p.payload as { permit2Authorization?: unknown }).permit2Authorization === 'object'\n );\n}\n\n/** Narrows to the reserved `'instrument'` scheme branch. Returns `false` for all production traffic today. */\nexport function isInstrumentPayload(\n p: InflowPaymentPayload,\n): p is InflowPaymentPayload & { payload: InstrumentPayloadData } {\n return p.accepted.scheme === 'instrument';\n}\n\n/**\n * Settlement-result envelope returned by the facilitator after a settle call. `network` is CAIP-2 for blockchain\n * settlements and `'inflow:1'` for balance settlements.\n *\n * `transaction` is always present: a non-empty on-chain hash (or settlement reference for `'balance'`) on success, the\n * empty string on failure. Check `success` before treating the value as a real reference.\n */\nexport interface SettleResponse {\n success: boolean;\n errorReason?: string;\n errorMessage?: string;\n payer?: string;\n /** On-chain hash on success, empty string on failure. Always present. */\n transaction: string;\n network: string;\n amount?: string;\n /** Per-extension entries returned by the facilitator. */\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Per-`(scheme, network)` capability advertised by a facilitator. The optional `extra` map carries scheme- or\n * operator-specific metadata; the SDK does not interpret it.\n */\nexport interface X402SupportedKind {\n network: string;\n scheme: PaymentScheme;\n x402Version: number;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Facilitator-wide capability response. Returned by `GET /v1/x402/supported`.\n *\n * `signers` carries the operator wallet addresses that sign settlement on the facilitator side, used by sellers for\n * trust verification of the settlement source. `extensions` enumerates the facilitator-wide extension names so\n * `inflowAccepts` can dispatch to the right handlers.\n */\nexport interface X402FacilitatorSupportedResponse {\n kinds: X402SupportedKind[];\n extensions?: string[];\n signers?: Record<string, string[]>;\n}\n\n/**\n * Buyer-facing capability response. Returned by `GET /v1/transactions/x402-supported`. Deliberately narrower than\n * {@link X402FacilitatorSupportedResponse}: facilitator-wide extension declarations and operator signer addresses have\n * no actionable meaning on the buyer side and are intentionally omitted.\n */\nexport interface X402BuyerSupportedResponse {\n kinds: X402SupportedKind[];\n}\n\n/**\n * On-chain asset metadata, per `(blockchain, currency)` pair. Read from `X402ConfigResponse.assets[]` by\n * `inflowAccepts` when constructing `'exact'`-scheme entries.\n */\nexport interface X402AssetInfo {\n /**\n * Default transfer method for this asset. `'eip3009'` and `'permit2'` for EVM assets; `'solana'` for Solana. The\n * `(string & {})` branch leaves room for forward-compatible methods the SDK hasn't enumerated yet (e.g.\n * `'erc7710'`).\n */\n assetTransferMethod?: 'eip3009' | 'permit2' | 'solana' | (string & {});\n /** Contract address (EVM) or mint (Solana). */\n assetId: string;\n /** Blockchain enum name as serialized in the config response. Opaque to the SDK. */\n blockchain: string;\n /** Currency code — e.g. `'USDC'`, `'USDT'`, `'PYUSD'`. */\n currency: string;\n /** On-chain decimal places for this asset (e.g. `6` for USDC on Base). */\n decimals: number;\n /** CAIP-2 network identifier (e.g. `'eip155:8453'`). Opaque to the SDK. */\n network: string;\n /**\n * Permit2 spender address the facilitator will sign settlements through. Present on EVM assets that support Permit2;\n * absent when the canonical x402ExactPermit2Proxy isn't deployed on the chain. Buyers should verify this equals\n * {@link CONTRACTS.PERMIT2_PROXY} before signing.\n */\n permit2Proxy?: string;\n /** EIP-712 domain name. Present only for EVM assets. */\n tokenName?: string;\n /** EIP-712 domain version. Present only for EVM assets. */\n tokenVersion?: string;\n}\n\n/**\n * Receiving-wallet metadata, per blockchain. Read from `X402ConfigResponse.wallets[]` by `inflowAccepts` to fill the\n * `payTo` field on `'exact'`-scheme entries.\n */\nexport interface X402WalletInfo {\n /** Chain-native address (EVM hex or Solana base58); used as `payTo` on `'exact'` entries. */\n address: string;\n /** Blockchain enum name — joins to `X402AssetInfo.blockchain`. Opaque to the SDK. */\n blockchain: string;\n /** Solana-only fee-payer address. */\n feePayer?: string;\n /** CAIP-2 network identifier (e.g. `'eip155:8453'`); matches `X402AssetInfo.network`. */\n network: string;\n}\n\n/**\n * Non-blockchain payment method metadata. Read from `X402ConfigResponse.paymentMethods[]` by `inflowAccepts` when\n * constructing `'balance'` and (reserved) `'instrument'` entries.\n */\nexport interface PaymentMethodInfo {\n /** Scheme this method handles — `'balance'` today, `'instrument'` reserved. */\n scheme: PaymentScheme;\n /** Network identifier for the method. `'inflow:1'` for `'balance'`; CAIP-2 for any future on-chain method. */\n network: string;\n /** Recipient identifier — the seller UUID for `'balance'` / `'instrument'`. */\n payTo: string;\n /** Per-method decimal scale. */\n decimals: number;\n /** Method-specific extras. Optional on the wire. */\n extra?: Record<string, unknown>;\n}\n\n/**\n * Stateless seller config response. Returned by `GET /v1/x402/config`. The seller middleware consumes this to construct\n * `PaymentRequired.accepts[]` at request time without per-route hard-coding.\n */\nexport interface X402ConfigResponse {\n /** Per-`(blockchain, currency)` on-chain asset metadata. */\n assets: X402AssetInfo[];\n /** Non-blockchain methods — `'balance'` and (reserved) `'instrument'`. */\n paymentMethods: PaymentMethodInfo[];\n /** Seller UUID — also the `payTo` value for non-blockchain schemes. */\n sellerId: string;\n /** Facilitator capabilities mirrored on the seller's config response. */\n supported: X402SupportedKind[];\n /** Per-blockchain receiving wallets. */\n wallets: X402WalletInfo[];\n}\n"]}
|