@inflowpayai/x402-seller 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 +110 -0
- package/dist/index.cjs +400 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +208 -0
- package/dist/index.d.ts +208 -0
- package/dist/index.js +393 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
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,110 @@
|
|
|
1
|
+
# @inflowpayai/x402-seller
|
|
2
|
+
|
|
3
|
+
Seller-side InFlow primitives that plug into the foundation V2 middleware (`paymentMiddlewareFromConfig` from `@x402/express` or
|
|
4
|
+
`@x402/hono`). This package does **not** ship a middleware itself — sellers use the foundation's directly and pass InFlow's facilitator
|
|
5
|
+
client into its `facilitatorClients` array.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @inflowpayai/x402-seller @x402/express @x402/core
|
|
11
|
+
# …or @x402/hono in place of @x402/express
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`@inflowpayai/x402` is a runtime dependency (bundled via workspace); `@x402/core` is a peer dependency.
|
|
15
|
+
|
|
16
|
+
## What's exported
|
|
17
|
+
|
|
18
|
+
- `createInflowFacilitator(options)` — synchronous factory. Returns a foundation `FacilitatorClient` (`verify` / `settle` /
|
|
19
|
+
`getSupported`). `options.apiKey` is required at the type level so an env-var omission can't silently degrade to facilitator-mode.
|
|
20
|
+
- `createUnauthenticatedInflowFacilitator(options)` — sibling factory returning the same `FacilitatorClient` shape but sending no
|
|
21
|
+
`X-API-KEY` header. The explicit escape hatch for facilitator-only deployments (self-hosted, public-facilitator mode, test harnesses).
|
|
22
|
+
- `createInflowSellerClient(options)` — async factory. Returns an `InflowSellerClient` (`config` / `refreshConfig` / `refreshSupported`
|
|
23
|
+
/ `getSignerAddresses`). Primes the config + supported caches in parallel before resolving; 60-minute TTL.
|
|
24
|
+
- `inflowAccepts(client, options)` — async helper. Returns a foundation `PaymentOption[]` ready to splat into a route's `accepts` field. The
|
|
25
|
+
prices are pre-resolved to `AssetAmount` form (asset contract address + atomic-unit amount).
|
|
26
|
+
- `inflowSchemeRegistrations(client)` — async helper. Reads the seller's `/v1/x402/config` and returns one passthrough
|
|
27
|
+
`SchemeRegistration` per `(scheme, network)` pair the server can emit. Pass these as the third argument to
|
|
28
|
+
`paymentMiddlewareFromConfig`; the foundation refuses to boot without registrations covering every advertised scheme.
|
|
29
|
+
- `X402PriceParseError` — typed error thrown by `inflowAccepts` when a price string doesn't parse.
|
|
30
|
+
|
|
31
|
+
### Price formats
|
|
32
|
+
|
|
33
|
+
`PriceSpec.amount` accepts three forms (all support up to 8 decimal places):
|
|
34
|
+
|
|
35
|
+
| Form | Example | Resolved currency |
|
|
36
|
+
| ------------------------------------ | ---------------------------------------- | ------------------------------------ |
|
|
37
|
+
| `$<integer>(.<decimals>)?` | `'$0.01'`, `'$10.00000001'` | `USD` |
|
|
38
|
+
| `<integer>(.<decimals>)? <CURRENCY>` | `'0.01 USDC'`, `'1 USDT'`, `'0.5 PYUSD'` | from the suffix |
|
|
39
|
+
| `<integer>(.<decimals>)?` (bare) | `'0.01'` | from `PriceSpec.currency` (required) |
|
|
40
|
+
|
|
41
|
+
If both `amount` and `currency` carry a currency and they disagree, the `currency` field wins. `'USD'` is a wildcard that matches any
|
|
42
|
+
stablecoin asset the seller has configured.
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { paymentMiddlewareFromConfig } from '@x402/express';
|
|
48
|
+
import express from 'express';
|
|
49
|
+
import { registerExactEvmScheme } from '@x402/evm/exact/client';
|
|
50
|
+
import {
|
|
51
|
+
createInflowFacilitator,
|
|
52
|
+
createInflowSellerClient,
|
|
53
|
+
inflowAccepts,
|
|
54
|
+
inflowSchemeRegistrations,
|
|
55
|
+
} from '@inflowpayai/x402-seller';
|
|
56
|
+
|
|
57
|
+
const apiKey = process.env.INFLOW_API_KEY!;
|
|
58
|
+
const inflow = createInflowFacilitator({ environment: 'sandbox', apiKey });
|
|
59
|
+
const client = await createInflowSellerClient({ environment: 'sandbox', apiKey });
|
|
60
|
+
|
|
61
|
+
const app = express();
|
|
62
|
+
app.use(express.json());
|
|
63
|
+
app.use(
|
|
64
|
+
paymentMiddlewareFromConfig(
|
|
65
|
+
{
|
|
66
|
+
'GET /api/widgets': {
|
|
67
|
+
accepts: await inflowAccepts(client, { price: '$0.01' }),
|
|
68
|
+
},
|
|
69
|
+
'POST /api/upload': {
|
|
70
|
+
accepts: await inflowAccepts(client, {
|
|
71
|
+
price: '0.10 USDC',
|
|
72
|
+
schemes: ['balance', 'exact'],
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
[inflow],
|
|
77
|
+
[...(await inflowSchemeRegistrations(client)), registerExactEvmScheme()],
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
app.listen(3000);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Multi-facilitator
|
|
84
|
+
|
|
85
|
+
Pass multiple facilitator clients in the array — first claimer of a `(scheme, network)` pair via `getSupported()` wins routing (foundation's
|
|
86
|
+
declaration-order resolution):
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
paymentMiddlewareFromConfig(
|
|
90
|
+
{
|
|
91
|
+
/* routes */
|
|
92
|
+
},
|
|
93
|
+
[
|
|
94
|
+
inflow, // claims (balance, inflow), (exact, eip155:8453), …
|
|
95
|
+
cdp, // claims whatever inflow doesn't
|
|
96
|
+
partnerFacilitator,
|
|
97
|
+
],
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## See also
|
|
102
|
+
|
|
103
|
+
- [@inflowpayai/x402](../x402) — protocol types, HTTP client, constants
|
|
104
|
+
- [Product overview](../../docs/x402/README.md)
|
|
105
|
+
- [Architecture](../../docs/x402/architecture.md) — InFlow vs. foundation responsibilities, `inflowAccepts` algorithm, conflict precedence
|
|
106
|
+
- [Wire-format mapping](../../docs/x402/protocol-mapping.md) — types, headers, network rules, price formats
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var x402 = require('@inflowpayai/x402');
|
|
4
|
+
var extensions = require('@inflowpayai/x402/extensions');
|
|
5
|
+
|
|
6
|
+
// src/facilitator.ts
|
|
7
|
+
var SUPPORTED_PATH = "/v1/x402/supported";
|
|
8
|
+
var VERIFY_PATH = "/v1/x402/verify";
|
|
9
|
+
var SETTLE_PATH = "/v1/x402/settle";
|
|
10
|
+
var PERMIT2_ALLOWANCE_REQUIRED_HTTP_STATUS = 412;
|
|
11
|
+
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
12
|
+
function newEntry() {
|
|
13
|
+
return { value: void 0, expiresAt: 0, inFlight: void 0 };
|
|
14
|
+
}
|
|
15
|
+
function createInflowFacilitator(options) {
|
|
16
|
+
const http = new x402.InflowHttpClient(options);
|
|
17
|
+
const supportedCache = newEntry();
|
|
18
|
+
return buildFacilitator(http, supportedCache);
|
|
19
|
+
}
|
|
20
|
+
function createUnauthenticatedInflowFacilitator(options) {
|
|
21
|
+
const http = new x402.InflowHttpClient({
|
|
22
|
+
environment: options.environment,
|
|
23
|
+
...options.baseUrl !== void 0 ? { baseUrl: options.baseUrl } : {}
|
|
24
|
+
});
|
|
25
|
+
const supportedCache = newEntry();
|
|
26
|
+
return buildFacilitator(http, supportedCache);
|
|
27
|
+
}
|
|
28
|
+
function asFacilitatorClient(client) {
|
|
29
|
+
return client;
|
|
30
|
+
}
|
|
31
|
+
function buildFacilitator(http, supportedCache) {
|
|
32
|
+
async function fetchSupported() {
|
|
33
|
+
const fresh = await http.get(SUPPORTED_PATH);
|
|
34
|
+
supportedCache.value = fresh;
|
|
35
|
+
supportedCache.expiresAt = Date.now() + CACHE_TTL_MS;
|
|
36
|
+
return fresh;
|
|
37
|
+
}
|
|
38
|
+
function getSupportedCached() {
|
|
39
|
+
if (supportedCache.value !== void 0 && Date.now() < supportedCache.expiresAt) {
|
|
40
|
+
return Promise.resolve(supportedCache.value);
|
|
41
|
+
}
|
|
42
|
+
if (supportedCache.inFlight !== void 0) return supportedCache.inFlight;
|
|
43
|
+
const inFlight = fetchSupported().finally(() => {
|
|
44
|
+
supportedCache.inFlight = void 0;
|
|
45
|
+
});
|
|
46
|
+
supportedCache.inFlight = inFlight;
|
|
47
|
+
return inFlight;
|
|
48
|
+
}
|
|
49
|
+
const shape = {
|
|
50
|
+
getSupported: () => getSupportedCached(),
|
|
51
|
+
async verify(paymentPayload, paymentRequirements) {
|
|
52
|
+
try {
|
|
53
|
+
return await http.post(
|
|
54
|
+
VERIFY_PATH,
|
|
55
|
+
{
|
|
56
|
+
x402Version: x402.X402_VERSION,
|
|
57
|
+
paymentPayload: ensurePaymentIdentifier(paymentPayload),
|
|
58
|
+
paymentRequirements
|
|
59
|
+
},
|
|
60
|
+
{ retries: 0 }
|
|
61
|
+
);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (err instanceof x402.InflowApiError && err.httpStatus === PERMIT2_ALLOWANCE_REQUIRED_HTTP_STATUS && isVerifyResponseShape(err.body)) {
|
|
64
|
+
return err.body;
|
|
65
|
+
}
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async settle(paymentPayload, paymentRequirements) {
|
|
70
|
+
return http.post(
|
|
71
|
+
SETTLE_PATH,
|
|
72
|
+
{
|
|
73
|
+
x402Version: x402.X402_VERSION,
|
|
74
|
+
paymentPayload: ensurePaymentIdentifier(paymentPayload),
|
|
75
|
+
paymentRequirements
|
|
76
|
+
},
|
|
77
|
+
{ retries: 0 }
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return asFacilitatorClient(shape);
|
|
82
|
+
}
|
|
83
|
+
function isVerifyResponseShape(body) {
|
|
84
|
+
return typeof body === "object" && body !== null && "isValid" in body && "invalidReason" in body;
|
|
85
|
+
}
|
|
86
|
+
function ensurePaymentIdentifier(payload) {
|
|
87
|
+
const existing = payload.extensions?.[extensions.EXTENSION_PAYMENT_IDENTIFIER];
|
|
88
|
+
if (existing !== void 0 && existing !== null && typeof existing === "object") {
|
|
89
|
+
const { paymentId: paymentId2 } = existing;
|
|
90
|
+
if (typeof paymentId2 === "string" && extensions.validatePaymentId(paymentId2)) {
|
|
91
|
+
return payload;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const paymentId = extensions.generatePaymentId();
|
|
95
|
+
return {
|
|
96
|
+
...payload,
|
|
97
|
+
extensions: {
|
|
98
|
+
...payload.extensions ?? {},
|
|
99
|
+
[extensions.EXTENSION_PAYMENT_IDENTIFIER]: { paymentId }
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
var CONFIG_PATH = "/v1/x402/config";
|
|
104
|
+
var SUPPORTED_PATH2 = "/v1/x402/supported";
|
|
105
|
+
var CACHE_TTL_MS2 = 60 * 60 * 1e3;
|
|
106
|
+
function newEntry2() {
|
|
107
|
+
return { value: void 0, expiresAt: 0, inFlight: void 0 };
|
|
108
|
+
}
|
|
109
|
+
async function createInflowSellerClient(options) {
|
|
110
|
+
const http = new x402.InflowHttpClient(options);
|
|
111
|
+
const configCache = newEntry2();
|
|
112
|
+
const supportedCache = newEntry2();
|
|
113
|
+
async function fetchConfig() {
|
|
114
|
+
const fresh = await http.get(CONFIG_PATH);
|
|
115
|
+
configCache.value = fresh;
|
|
116
|
+
configCache.expiresAt = Date.now() + CACHE_TTL_MS2;
|
|
117
|
+
return fresh;
|
|
118
|
+
}
|
|
119
|
+
async function fetchSupported() {
|
|
120
|
+
const fresh = await http.get(SUPPORTED_PATH2);
|
|
121
|
+
supportedCache.value = fresh;
|
|
122
|
+
supportedCache.expiresAt = Date.now() + CACHE_TTL_MS2;
|
|
123
|
+
return fresh;
|
|
124
|
+
}
|
|
125
|
+
function getCached(entry, fetcher) {
|
|
126
|
+
if (entry.value !== void 0 && Date.now() < entry.expiresAt) {
|
|
127
|
+
return Promise.resolve(entry.value);
|
|
128
|
+
}
|
|
129
|
+
if (entry.inFlight !== void 0) return entry.inFlight;
|
|
130
|
+
const inFlight = fetcher().finally(() => {
|
|
131
|
+
entry.inFlight = void 0;
|
|
132
|
+
});
|
|
133
|
+
entry.inFlight = inFlight;
|
|
134
|
+
return inFlight;
|
|
135
|
+
}
|
|
136
|
+
function refresh(entry, fetcher) {
|
|
137
|
+
if (entry.inFlight !== void 0) return entry.inFlight;
|
|
138
|
+
const inFlight = fetcher().finally(() => {
|
|
139
|
+
entry.inFlight = void 0;
|
|
140
|
+
});
|
|
141
|
+
entry.inFlight = inFlight;
|
|
142
|
+
return inFlight;
|
|
143
|
+
}
|
|
144
|
+
function resolveSigners(signers, network) {
|
|
145
|
+
if (signers === void 0) return [];
|
|
146
|
+
const exact = signers[network];
|
|
147
|
+
if (exact !== void 0) return exact;
|
|
148
|
+
const colonIndex = network.indexOf(":");
|
|
149
|
+
if (colonIndex <= 0) return [];
|
|
150
|
+
const wildcard = signers[`${network.slice(0, colonIndex)}:*`];
|
|
151
|
+
return wildcard ?? [];
|
|
152
|
+
}
|
|
153
|
+
const client = {
|
|
154
|
+
config: () => getCached(configCache, fetchConfig),
|
|
155
|
+
refreshConfig: () => refresh(configCache, fetchConfig),
|
|
156
|
+
refreshSupported: () => refresh(supportedCache, fetchSupported),
|
|
157
|
+
async getSignerAddresses(network) {
|
|
158
|
+
const supported = await getCached(supportedCache, fetchSupported);
|
|
159
|
+
return resolveSigners(supported.signers, network);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
await Promise.all([fetchConfig(), fetchSupported()]);
|
|
163
|
+
return client;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/errors.ts
|
|
167
|
+
var X402PriceParseError = class extends Error {
|
|
168
|
+
/** The original input that failed parsing. */
|
|
169
|
+
input;
|
|
170
|
+
/** @param input - The {@link PriceSpec.amount} value that failed parsing. */
|
|
171
|
+
constructor(input) {
|
|
172
|
+
super(
|
|
173
|
+
`Invalid price "${input}"; expected "$<dollars>(.<decimals>)?", "<amount> <CURRENCY>", or bare "<amount>" (up to 8 decimal places).`
|
|
174
|
+
);
|
|
175
|
+
this.name = "X402PriceParseError";
|
|
176
|
+
this.input = input;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/inflow-accepts.ts
|
|
181
|
+
var DEFAULT_MAX_TIMEOUT_SECONDS = 300;
|
|
182
|
+
var PRICE_USD_REGEX = /^\$(\d+)(?:\.(\d{1,8}))?$/u;
|
|
183
|
+
var PRICE_WITH_CURRENCY_REGEX = /^(\d+)(?:\.(\d{1,8}))?\s+([A-Z][A-Z0-9_]*)$/u;
|
|
184
|
+
var PRICE_BARE_REGEX = /^(\d+)(?:\.(\d{1,8}))?$/u;
|
|
185
|
+
async function inflowAccepts(client, options) {
|
|
186
|
+
const maxTimeoutSeconds = options.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;
|
|
187
|
+
const priceSpec = normalizePrice(options.price);
|
|
188
|
+
const { amount: parsedAmount, currency: targetCurrency } = parsePriceSpec(priceSpec);
|
|
189
|
+
const config = await client.config();
|
|
190
|
+
const entries = [];
|
|
191
|
+
for (const wallet of config.wallets) {
|
|
192
|
+
const assets = config.assets.filter(
|
|
193
|
+
(a) => a.blockchain === wallet.blockchain && currencyMatches(a.currency, targetCurrency)
|
|
194
|
+
);
|
|
195
|
+
for (const asset of assets) {
|
|
196
|
+
const methods = resolveTransferMethods(asset);
|
|
197
|
+
for (const method of methods) {
|
|
198
|
+
if (!includeEntry(options, x402.SCHEMES.EXACT, asset.network)) continue;
|
|
199
|
+
entries.push(
|
|
200
|
+
buildOnChainOption({
|
|
201
|
+
wallet,
|
|
202
|
+
asset,
|
|
203
|
+
method,
|
|
204
|
+
amount: factorParsed(parsedAmount, asset.decimals, priceSpec.amount),
|
|
205
|
+
maxTimeoutSeconds
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const method of config.paymentMethods) {
|
|
212
|
+
if (!includeEntry(options, method.scheme, method.network)) continue;
|
|
213
|
+
for (const currency of resolveCurrencies(config, targetCurrency)) {
|
|
214
|
+
entries.push(
|
|
215
|
+
buildPaymentMethodOption({
|
|
216
|
+
method,
|
|
217
|
+
currency,
|
|
218
|
+
amount: factorParsed(parsedAmount, method.decimals, priceSpec.amount),
|
|
219
|
+
maxTimeoutSeconds
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return entries;
|
|
225
|
+
}
|
|
226
|
+
function resolveCurrencies(config, target) {
|
|
227
|
+
if (target !== "USD") return [target];
|
|
228
|
+
const seen = /* @__PURE__ */ new Set();
|
|
229
|
+
const out = [];
|
|
230
|
+
for (const a of config.assets) {
|
|
231
|
+
if (!seen.has(a.currency)) {
|
|
232
|
+
seen.add(a.currency);
|
|
233
|
+
out.push(a.currency);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
function buildOnChainOption(args) {
|
|
239
|
+
const { wallet, asset, method, amount, maxTimeoutSeconds } = args;
|
|
240
|
+
const extra = {};
|
|
241
|
+
if (asset.tokenName !== void 0) extra[x402.EXTRA_KEYS.NAME] = asset.tokenName;
|
|
242
|
+
if (asset.tokenVersion !== void 0) extra[x402.EXTRA_KEYS.VERSION] = asset.tokenVersion;
|
|
243
|
+
if (method !== void 0) extra[x402.EXTRA_KEYS.ASSET_TRANSFER_METHOD] = method;
|
|
244
|
+
if (method === x402.ASSET_TRANSFER_METHODS.PERMIT2 && asset.permit2Proxy !== void 0) {
|
|
245
|
+
extra[x402.EXTRA_KEYS.PERMIT2_PROXY] = asset.permit2Proxy;
|
|
246
|
+
}
|
|
247
|
+
if (wallet.feePayer !== void 0) {
|
|
248
|
+
extra[x402.EXTRA_KEYS.FEE_PAYER] = wallet.feePayer;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
scheme: x402.SCHEMES.EXACT,
|
|
252
|
+
// CAIP-2 string — narrower than the foundation `Network` template
|
|
253
|
+
// literal type would assume from the assignment site, so cast at the
|
|
254
|
+
// construction boundary.
|
|
255
|
+
network: asset.network,
|
|
256
|
+
payTo: wallet.address,
|
|
257
|
+
price: { asset: asset.assetId, amount },
|
|
258
|
+
maxTimeoutSeconds,
|
|
259
|
+
extra
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function buildPaymentMethodOption(args) {
|
|
263
|
+
const { method, currency, amount, maxTimeoutSeconds } = args;
|
|
264
|
+
const base = {
|
|
265
|
+
scheme: method.scheme,
|
|
266
|
+
// CAIP-2 string (`'inflow:1'` for the InFlow balance ledger).
|
|
267
|
+
network: method.network,
|
|
268
|
+
payTo: method.payTo,
|
|
269
|
+
// The currency name keys the InFlow ledger that gets debited.
|
|
270
|
+
price: { asset: currency, amount },
|
|
271
|
+
maxTimeoutSeconds
|
|
272
|
+
};
|
|
273
|
+
if (method.extra !== void 0 && Object.keys(method.extra).length > 0) {
|
|
274
|
+
base.extra = { ...method.extra };
|
|
275
|
+
}
|
|
276
|
+
return base;
|
|
277
|
+
}
|
|
278
|
+
function resolveTransferMethods(asset) {
|
|
279
|
+
return [asset.assetTransferMethod];
|
|
280
|
+
}
|
|
281
|
+
function includeEntry(options, scheme, network) {
|
|
282
|
+
if (options.schemes !== void 0 && !options.schemes.includes(scheme)) return false;
|
|
283
|
+
if (options.networks !== void 0 && !options.networks.includes(network)) return false;
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
function currencyMatches(assetCurrency, target) {
|
|
287
|
+
if (target === "USD") return true;
|
|
288
|
+
return assetCurrency === target;
|
|
289
|
+
}
|
|
290
|
+
function normalizePrice(input) {
|
|
291
|
+
return typeof input === "string" ? { amount: input } : input;
|
|
292
|
+
}
|
|
293
|
+
function parsePriceAmount(input) {
|
|
294
|
+
let match = PRICE_USD_REGEX.exec(input);
|
|
295
|
+
if (match !== null) {
|
|
296
|
+
return {
|
|
297
|
+
integer: stripLeadingZeros(match[1] ?? "0"),
|
|
298
|
+
fraction: match[2] ?? "",
|
|
299
|
+
embeddedCurrency: "USD"
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
match = PRICE_WITH_CURRENCY_REGEX.exec(input);
|
|
303
|
+
if (match !== null) {
|
|
304
|
+
return {
|
|
305
|
+
integer: stripLeadingZeros(match[1] ?? "0"),
|
|
306
|
+
fraction: match[2] ?? "",
|
|
307
|
+
embeddedCurrency: match[3]
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
match = PRICE_BARE_REGEX.exec(input);
|
|
311
|
+
if (match !== null) {
|
|
312
|
+
return {
|
|
313
|
+
integer: stripLeadingZeros(match[1] ?? "0"),
|
|
314
|
+
fraction: match[2] ?? "",
|
|
315
|
+
embeddedCurrency: void 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
throw new X402PriceParseError(input);
|
|
319
|
+
}
|
|
320
|
+
function parsePriceSpec(price) {
|
|
321
|
+
const amount = parsePriceAmount(price.amount);
|
|
322
|
+
const resolvedCurrency = price.currency ?? amount.embeddedCurrency;
|
|
323
|
+
if (resolvedCurrency === void 0) {
|
|
324
|
+
throw new X402PriceParseError(`${price.amount} (no currency in amount and no currency field supplied)`);
|
|
325
|
+
}
|
|
326
|
+
return { amount, currency: resolvedCurrency };
|
|
327
|
+
}
|
|
328
|
+
function factorParsed(parsed, decimals, rawForErrorMessage) {
|
|
329
|
+
const fractionPlaces = parsed.fraction.length;
|
|
330
|
+
const combined = stripLeadingZeros(`${parsed.integer}${parsed.fraction}`);
|
|
331
|
+
if (decimals === fractionPlaces) return combined;
|
|
332
|
+
if (decimals > fractionPlaces) {
|
|
333
|
+
return `${combined}${"0".repeat(decimals - fractionPlaces)}`;
|
|
334
|
+
}
|
|
335
|
+
const drop = fractionPlaces - decimals;
|
|
336
|
+
const trimmed = combined.slice(0, -drop);
|
|
337
|
+
const dropped = combined.slice(-drop);
|
|
338
|
+
if (!/^0*$/u.test(dropped)) {
|
|
339
|
+
throw new X402PriceParseError(
|
|
340
|
+
`${rawForErrorMessage} (cannot be expressed in ${decimals.toString()} decimals without truncation)`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
return trimmed.length === 0 ? "0" : trimmed;
|
|
344
|
+
}
|
|
345
|
+
function stripLeadingZeros(s) {
|
|
346
|
+
const stripped = s.replace(/^0+/u, "");
|
|
347
|
+
return stripped.length === 0 ? "0" : stripped;
|
|
348
|
+
}
|
|
349
|
+
async function inflowSchemeRegistrations(client) {
|
|
350
|
+
const config = await client.config();
|
|
351
|
+
const registrations = [];
|
|
352
|
+
const seen = /* @__PURE__ */ new Set();
|
|
353
|
+
function add(scheme, network) {
|
|
354
|
+
const key = `${scheme}|${network}`;
|
|
355
|
+
if (seen.has(key)) return;
|
|
356
|
+
seen.add(key);
|
|
357
|
+
registrations.push({
|
|
358
|
+
// Boundary cast to the foundation's `${string}:${string}` Network
|
|
359
|
+
// type. Every value passing through (CAIP-2 chain ids and
|
|
360
|
+
// `'inflow:1'`) is CAIP-2 shaped at runtime.
|
|
361
|
+
network,
|
|
362
|
+
server: inflowPassthroughScheme(scheme)
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
for (const asset of config.assets) {
|
|
366
|
+
add(x402.SCHEMES.EXACT, asset.network);
|
|
367
|
+
}
|
|
368
|
+
for (const method of config.paymentMethods) {
|
|
369
|
+
add(method.scheme, method.network);
|
|
370
|
+
}
|
|
371
|
+
return registrations;
|
|
372
|
+
}
|
|
373
|
+
function inflowPassthroughScheme(scheme) {
|
|
374
|
+
return {
|
|
375
|
+
scheme,
|
|
376
|
+
parsePrice(price, _network) {
|
|
377
|
+
if (typeof price !== "object" || price === null || !("asset" in price) || !("amount" in price)) {
|
|
378
|
+
return Promise.reject(
|
|
379
|
+
new Error(
|
|
380
|
+
`inflowPassthroughScheme: parsePrice expected AssetAmount-form price (use inflowAccepts to build PaymentOption.price); got ${JSON.stringify(price)}`
|
|
381
|
+
)
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
const out = price.extra !== void 0 ? { asset: price.asset, amount: price.amount, extra: price.extra } : { asset: price.asset, amount: price.amount };
|
|
385
|
+
return Promise.resolve(out);
|
|
386
|
+
},
|
|
387
|
+
enhancePaymentRequirements(paymentRequirements, _supportedKind, _facilitatorExtensions) {
|
|
388
|
+
return Promise.resolve(paymentRequirements);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
exports.X402PriceParseError = X402PriceParseError;
|
|
394
|
+
exports.createInflowFacilitator = createInflowFacilitator;
|
|
395
|
+
exports.createInflowSellerClient = createInflowSellerClient;
|
|
396
|
+
exports.createUnauthenticatedInflowFacilitator = createUnauthenticatedInflowFacilitator;
|
|
397
|
+
exports.inflowAccepts = inflowAccepts;
|
|
398
|
+
exports.inflowSchemeRegistrations = inflowSchemeRegistrations;
|
|
399
|
+
//# sourceMappingURL=index.cjs.map
|
|
400
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/facilitator.ts","../src/seller-client.ts","../src/errors.ts","../src/inflow-accepts.ts","../src/scheme-registrations.ts"],"names":["InflowHttpClient","X402_VERSION","InflowApiError","EXTENSION_PAYMENT_IDENTIFIER","paymentId","validatePaymentId","generatePaymentId","SUPPORTED_PATH","CACHE_TTL_MS","newEntry","SCHEMES","EXTRA_KEYS","ASSET_TRANSFER_METHODS"],"mappings":"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","file":"index.cjs","sourcesContent":["import { InflowApiError, InflowHttpClient, X402_VERSION } from '@inflowpayai/x402';\nimport type {\n InflowPaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n X402FacilitatorSupportedResponse,\n} from '@inflowpayai/x402';\nimport { EXTENSION_PAYMENT_IDENTIFIER, generatePaymentId, validatePaymentId } from '@inflowpayai/x402/extensions';\nimport type { FacilitatorClient } from '@x402/core/server';\n\nimport type { InflowFacilitatorOptions, InflowUnauthenticatedFacilitatorOptions } from './types.js';\n\nconst SUPPORTED_PATH = '/v1/x402/supported';\nconst VERIFY_PATH = '/v1/x402/verify';\nconst SETTLE_PATH = '/v1/x402/settle';\n\n/**\n * Spec-defined error code paired with HTTP 412 Precondition Failed when the Permit2 allowance check fails. See\n * {@link https://github.com/coinbase/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md\n * x402 EVM exact scheme} for\n * the contract. The SDK normalises the 412 into an `isValid: false` VerifyResponse so callers see a single shape and\n * can branch on `invalidReason`.\n */\nconst PERMIT2_ALLOWANCE_REQUIRED_HTTP_STATUS = 412 as const;\n\n/** TTL for the cached `getSupported()` response (milliseconds). */\nconst CACHE_TTL_MS = 60 * 60 * 1000;\n\n/**\n * State for a single cached value. Tracks the value, its expiry timestamp, and any in-flight refresh so concurrent\n * callers share a single request.\n */\ninterface CacheEntry<T> {\n value: T | undefined;\n expiresAt: number;\n inFlight: Promise<T> | undefined;\n}\n\nfunction newEntry<T>(): CacheEntry<T> {\n return { value: undefined, expiresAt: 0, inFlight: undefined };\n}\n\n/**\n * Construct an authed InFlow facilitator. The returned object satisfies the foundation V2 `FacilitatorClient` contract\n * from `@x402/core` (`verify` / `settle` / `getSupported` only) and drops directly into the foundation middleware's\n * `facilitatorClients` array (`@x402/express`, `@x402/hono`) — first claimer of a `(scheme, network)` in declaration\n * order wins verify/settle routing.\n *\n * Seller-authed endpoints (`/v1/x402/config`, `getSignerAddresses`) live on the separate\n * {@link createInflowSellerClient} factory; this client carries the seller's API key only for `verify` / `settle` /\n * `getSupported`, where it enables server-side `payTo`-against-wallets validation.\n *\n * `getSupported()` is cached lazily in-memory for 60 minutes after the first call; concurrent callers share an\n * in-flight refresh. There is no priming step — the foundation middleware calls `getSupported()` once at\n * `x402ResourceServer.initialize()` and the cache is populated then.\n *\n * @param options - {@link InflowFacilitatorOptions}.\n * @returns A foundation `FacilitatorClient`.\n */\nexport function createInflowFacilitator(options: InflowFacilitatorOptions): FacilitatorClient {\n const http = new InflowHttpClient(options);\n const supportedCache: CacheEntry<X402FacilitatorSupportedResponse> = newEntry();\n\n return buildFacilitator(http, supportedCache);\n}\n\n/**\n * Anonymous sibling of {@link createInflowFacilitator} — same caches and contract, no `X-API-KEY` header. For\n * facilitator-only deployments (self-hosted, public-facilitator mode, test harnesses).\n */\nexport function createUnauthenticatedInflowFacilitator(\n options: InflowUnauthenticatedFacilitatorOptions,\n): FacilitatorClient {\n const http = new InflowHttpClient({\n environment: options.environment,\n ...(options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {}),\n });\n const supportedCache: CacheEntry<X402FacilitatorSupportedResponse> = newEntry();\n\n return buildFacilitator(http, supportedCache);\n}\n\n/**\n * Internal shape that mirrors `FacilitatorClient` but uses the SDK's widened types (`network: string` instead of the\n * foundation's CAIP-2 template literal). Wire-equivalent at runtime; only the TypeScript bounds differ.\n * {@link asFacilitatorClient} re-narrows once at the boundary so the `verify` / `settle` / `getSupported` signatures\n * still appear typed at the call site.\n */\ninterface InflowFacilitatorShape {\n getSupported: () => Promise<X402FacilitatorSupportedResponse>;\n verify: (paymentPayload: InflowPaymentPayload, paymentRequirements: PaymentRequirements) => Promise<VerifyResponse>;\n settle: (paymentPayload: InflowPaymentPayload, paymentRequirements: PaymentRequirements) => Promise<SettleResponse>;\n}\n\n/**\n * Single, explicit cast point between the SDK's widened types and the foundation `FacilitatorClient`. Passing anything\n * other than a fully shaped `InflowFacilitatorShape` to this helper fails at compile time, so additions to\n * `FacilitatorClient` upstream surface here rather than disappearing into an `as unknown as` site.\n */\nfunction asFacilitatorClient(client: InflowFacilitatorShape): FacilitatorClient {\n return client as unknown as FacilitatorClient;\n}\n\n/**\n * Shared implementation for the authed and anonymous factories. Caches `getSupported()` lazily with in-flight sharing;\n * verify and settle pass straight through to the seller-side facilitator endpoints.\n */\nfunction buildFacilitator(\n http: InflowHttpClient,\n supportedCache: CacheEntry<X402FacilitatorSupportedResponse>,\n): FacilitatorClient {\n async function fetchSupported(): Promise<X402FacilitatorSupportedResponse> {\n const fresh = await http.get<X402FacilitatorSupportedResponse>(SUPPORTED_PATH);\n supportedCache.value = fresh;\n supportedCache.expiresAt = Date.now() + CACHE_TTL_MS;\n return fresh;\n }\n\n function getSupportedCached(): Promise<X402FacilitatorSupportedResponse> {\n if (supportedCache.value !== undefined && Date.now() < supportedCache.expiresAt) {\n return Promise.resolve(supportedCache.value);\n }\n if (supportedCache.inFlight !== undefined) return supportedCache.inFlight;\n const inFlight = fetchSupported().finally(() => {\n supportedCache.inFlight = undefined;\n });\n supportedCache.inFlight = inFlight;\n return inFlight;\n }\n\n const shape: InflowFacilitatorShape = {\n getSupported: () => getSupportedCached(),\n async verify(paymentPayload, paymentRequirements) {\n // Transport-level retries are disabled: `/verify` and `/settle` are\n // idempotent only via the `payment-identifier` extension (server-side\n // X402PaymentIdCache). A 5xx-burst retry without an identifier could\n // re-debit or re-broadcast.\n try {\n return await http.post<VerifyResponse>(\n VERIFY_PATH,\n {\n x402Version: X402_VERSION,\n paymentPayload: ensurePaymentIdentifier(paymentPayload),\n paymentRequirements,\n },\n { retries: 0 },\n );\n } catch (err) {\n // The facilitator emits HTTP 412 with the standard VerifyResponse\n // body when Permit2 reports an allowance gap\n // (`invalidReason: PERMIT2_ALLOWANCE_REQUIRED`). The SDK normalises\n // the non-2xx into the same isValid:false VerifyResponse shape the\n // caller already handles for every other invalid case, so callers\n // get a single, branchable surface.\n if (\n err instanceof InflowApiError &&\n err.httpStatus === PERMIT2_ALLOWANCE_REQUIRED_HTTP_STATUS &&\n isVerifyResponseShape(err.body)\n ) {\n return err.body;\n }\n throw err;\n }\n },\n async settle(paymentPayload, paymentRequirements) {\n return http.post<SettleResponse>(\n SETTLE_PATH,\n {\n x402Version: X402_VERSION,\n paymentPayload: ensurePaymentIdentifier(paymentPayload),\n paymentRequirements,\n },\n { retries: 0 },\n );\n },\n };\n return asFacilitatorClient(shape);\n}\n\n/**\n * Structural check for the body the InFlow facilitator returns alongside a 412 verify response. Defensive — if the\n * runtime ever emits a different 412 body shape, the caller sees the original {@link InflowApiError} instead of a\n * misleading verify-style result.\n */\nfunction isVerifyResponseShape(body: unknown): body is VerifyResponse {\n return typeof body === 'object' && body !== null && 'isValid' in body && 'invalidReason' in body;\n}\n\n/**\n * Returns a payload that carries a valid `payment-identifier` extension entry. If the buyer already supplied one\n * (server-signed InFlow payloads always do; foundation buyers may), it is preserved unchanged. Otherwise a fresh\n * `pay_<32-hex>` identifier is generated so settle/verify retries land in the server's idempotency cache.\n */\nfunction ensurePaymentIdentifier(payload: InflowPaymentPayload): InflowPaymentPayload {\n const existing = payload.extensions?.[EXTENSION_PAYMENT_IDENTIFIER];\n if (existing !== undefined && existing !== null && typeof existing === 'object') {\n const { paymentId } = existing as { paymentId?: unknown };\n if (typeof paymentId === 'string' && validatePaymentId(paymentId)) {\n return payload;\n }\n }\n const paymentId = generatePaymentId();\n return {\n ...payload,\n extensions: {\n ...(payload.extensions ?? {}),\n [EXTENSION_PAYMENT_IDENTIFIER]: { paymentId },\n },\n };\n}\n","import { InflowHttpClient } from '@inflowpayai/x402';\nimport type { Environment, X402ConfigResponse, X402FacilitatorSupportedResponse } from '@inflowpayai/x402';\n\nconst CONFIG_PATH = '/v1/x402/config';\nconst SUPPORTED_PATH = '/v1/x402/supported';\n\n/** TTL for cached `config()` and supported responses (milliseconds). */\nconst CACHE_TTL_MS = 60 * 60 * 1000;\n\n/**\n * Constructor options for {@link createInflowSellerClient}.\n *\n * `apiKey` is required at the type level. `/v1/x402/config` is a seller-authed endpoint — there's no facilitator-mode\n * equivalent — so an unauthenticated seller client has no useful surface to expose.\n */\nexport interface InflowSellerClientOptions {\n /** Selects one of the public environments. */\n environment: Environment;\n /** InFlow API key sent on every request as `X-API-KEY`. Required. */\n apiKey: string;\n /** Override the environment-derived URL. Takes precedence over `environment`. */\n baseUrl?: string;\n}\n\n/**\n * Seller-authed InFlow client. Wraps the `/v1/x402/config` and `/v1/x402/supported` endpoints and surfaces\n * signer-address discovery on top of `getSupported()`. Drives {@link inflowAccepts} and any operator- facing\n * introspection.\n *\n * Construct via {@link createInflowSellerClient}. The factory primes both caches in parallel before resolving, so\n * methods on the returned instance hit in-memory data for the lifetime of the 60-minute TTL.\n *\n * @see createInflowSellerClient\n */\nexport interface InflowSellerClient {\n /**\n * Fetch the seller config (assets, wallets, payment methods, sellerId). Cached for 60 minutes after the factory's\n * prime call.\n *\n * @returns The current `X402ConfigResponse` (re-exported from `@inflowpayai/x402`).\n */\n config(): Promise<X402ConfigResponse>;\n /**\n * Force a refetch of `GET /v1/x402/config` and replace the cached value.\n *\n * @returns The freshly fetched `X402ConfigResponse` (re-exported from `@inflowpayai/x402`).\n */\n refreshConfig(): Promise<X402ConfigResponse>;\n /**\n * Force a refetch of `GET /v1/x402/supported` and replace the cached value.\n *\n * @returns The freshly fetched `X402FacilitatorSupportedResponse` (re-exported from `@inflowpayai/x402`).\n */\n refreshSupported(): Promise<X402FacilitatorSupportedResponse>;\n /**\n * Signer addresses advertised by the facilitator for the given network.\n *\n * Lookup is exact-match on `network` first; if no entry exists and the input is CAIP-2 shaped\n * (`<namespace>:<reference>`), it falls back to a `<namespace>:*` wildcard key so external facilitators that follow\n * the V2 spec's wildcard form interop. Returns `[]` when nothing matches.\n *\n * @param network - CAIP-2 string (e.g. `'eip155:8453'` or `'inflow:1'`).\n * @returns The configured signer addresses, or `[]` when none match.\n */\n getSignerAddresses(network: string): Promise<readonly string[]>;\n}\n\n/**\n * State for a single cached value. Tracks the value, its expiry timestamp, and any in-flight refresh so concurrent\n * callers share a single request.\n */\ninterface CacheEntry<T> {\n value: T | undefined;\n expiresAt: number;\n inFlight: Promise<T> | undefined;\n}\n\nfunction newEntry<T>(): CacheEntry<T> {\n return { value: undefined, expiresAt: 0, inFlight: undefined };\n}\n\n/**\n * Construct an {@link InflowSellerClient}.\n *\n * The factory primes the config and `getSupported()` caches in parallel before resolving, so the first downstream call\n * ({@link inflowAccepts}, `getSignerAddresses`, etc.) is synchronous against in-memory data. Cost: one round trip at\n * startup; benefit: synchronous downstream use.\n *\n * @param options - {@link InflowSellerClientOptions}.\n * @returns A promise resolving to a primed {@link InflowSellerClient}.\n */\nexport async function createInflowSellerClient(options: InflowSellerClientOptions): Promise<InflowSellerClient> {\n const http = new InflowHttpClient(options);\n\n const configCache: CacheEntry<X402ConfigResponse> = newEntry();\n const supportedCache: CacheEntry<X402FacilitatorSupportedResponse> = newEntry();\n\n async function fetchConfig(): Promise<X402ConfigResponse> {\n const fresh = await http.get<X402ConfigResponse>(CONFIG_PATH);\n configCache.value = fresh;\n configCache.expiresAt = Date.now() + CACHE_TTL_MS;\n return fresh;\n }\n\n async function fetchSupported(): Promise<X402FacilitatorSupportedResponse> {\n const fresh = await http.get<X402FacilitatorSupportedResponse>(SUPPORTED_PATH);\n supportedCache.value = fresh;\n supportedCache.expiresAt = Date.now() + CACHE_TTL_MS;\n return fresh;\n }\n\n /**\n * Cache-or-fetch with in-flight sharing: while a refresh is happening, any concurrent caller awaits the same promise\n * instead of issuing a duplicate request.\n */\n function getCached<T>(entry: CacheEntry<T>, fetcher: () => Promise<T>): Promise<T> {\n if (entry.value !== undefined && Date.now() < entry.expiresAt) {\n return Promise.resolve(entry.value);\n }\n if (entry.inFlight !== undefined) return entry.inFlight;\n const inFlight = fetcher().finally(() => {\n entry.inFlight = undefined;\n });\n entry.inFlight = inFlight;\n return inFlight;\n }\n\n /**\n * Reissues the fetch and atomically swaps in the new value on success. The previously cached value is held until the\n * refresh resolves, so concurrent readers never see a torn cache or a forced re-fetch on transient failures.\n */\n function refresh<T>(entry: CacheEntry<T>, fetcher: () => Promise<T>): Promise<T> {\n if (entry.inFlight !== undefined) return entry.inFlight;\n const inFlight = fetcher().finally(() => {\n entry.inFlight = undefined;\n });\n entry.inFlight = inFlight;\n return inFlight;\n }\n\n function resolveSigners(signers: Record<string, string[]> | undefined, network: string): readonly string[] {\n if (signers === undefined) return [];\n const exact = signers[network];\n if (exact !== undefined) return exact;\n // CAIP-2 wildcard fallback: `<namespace>:*`. The input must contain ':'.\n const colonIndex = network.indexOf(':');\n if (colonIndex <= 0) return [];\n const wildcard = signers[`${network.slice(0, colonIndex)}:*`];\n return wildcard ?? [];\n }\n\n const client: InflowSellerClient = {\n config: () => getCached(configCache, fetchConfig),\n refreshConfig: () => refresh(configCache, fetchConfig),\n refreshSupported: () => refresh(supportedCache, fetchSupported),\n async getSignerAddresses(network: string): Promise<readonly string[]> {\n const supported = await getCached(supportedCache, fetchSupported);\n return resolveSigners(supported.signers, network);\n },\n };\n\n // Prime both caches in parallel so the first user-facing call is sync\n // against in-memory data.\n await Promise.all([fetchConfig(), fetchSupported()]);\n return client;\n}\n","/**\n * Thrown by `inflowAccepts` when a price string doesn't match any accepted form. See {@link PriceSpec.amount} for the\n * grammar.\n */\nexport class X402PriceParseError extends Error {\n /** The original input that failed parsing. */\n readonly input: string;\n /** @param input - The {@link PriceSpec.amount} value that failed parsing. */\n constructor(input: string) {\n super(\n `Invalid price \"${input}\"; expected \"$<dollars>(.<decimals>)?\", ` +\n `\"<amount> <CURRENCY>\", or bare \"<amount>\" (up to 8 decimal places).`,\n );\n this.name = 'X402PriceParseError';\n this.input = input;\n }\n}\n","import { ASSET_TRANSFER_METHODS, EXTRA_KEYS, SCHEMES } from '@inflowpayai/x402';\nimport type { PaymentMethodInfo, PaymentScheme, X402AssetInfo, X402WalletInfo } from '@inflowpayai/x402';\nimport type { PaymentOption } from '@x402/core/http';\n\nimport { X402PriceParseError } from './errors.js';\nimport type { InflowSellerClient } from './seller-client.js';\n\nconst DEFAULT_MAX_TIMEOUT_SECONDS = 300;\n\n/** `'$X(.Y)?'` form — implies USD. Up to 8 decimal places. */\nconst PRICE_USD_REGEX = /^\\$(\\d+)(?:\\.(\\d{1,8}))?$/u;\n\n/** `'X(.Y)? CURRENCY'` form — currency from suffix. */\nconst PRICE_WITH_CURRENCY_REGEX = /^(\\d+)(?:\\.(\\d{1,8}))?\\s+([A-Z][A-Z0-9_]*)$/u;\n\n/** `'X(.Y)?'` bare form — currency must come from `PriceSpec.currency`. */\nconst PRICE_BARE_REGEX = /^(\\d+)(?:\\.(\\d{1,8}))?$/u;\n\n/** Price spec accepted by {@link inflowAccepts}. */\nexport interface PriceSpec {\n /**\n * Amount string. Three accepted forms (all supporting up to 8 decimal places):\n *\n * - `'$<integer>(.<decimals>)?'` — implies USD (e.g. `'$0.01'`, `'$10.00000001'`).\n * - `'<integer>(.<decimals>)? <CURRENCY>'` — currency from suffix (e.g. `'0.01 USDC'`, `'0.5 USDT'`, `'1 USD'`).\n * - `'<integer>(.<decimals>)?'` — bare numeric; the {@link PriceSpec.currency} field is required in this case.\n */\n amount: string;\n /**\n * Currency override. When set, takes precedence over any currency embedded in {@link PriceSpec.amount}. Required when\n * `amount` is in bare numeric form. `'USD'` is a wildcard that matches any stablecoin the seller has configured.\n */\n currency?: 'USD' | 'USDC' | 'USDT' | 'PYUSD' | (string & {});\n}\n\n/** Options accepted by {@link inflowAccepts}. */\nexport interface InflowAcceptsOptions {\n /**\n * Price for the protected resource. Either a {@link PriceSpec} or a string in any of the three forms accepted by\n * {@link PriceSpec.amount}.\n */\n price: PriceSpec | string;\n /**\n * Maximum lifetime (seconds) attached to each emitted entry. Defaults to `300` — matches the server-side\n * `X402Constants.INFLOW_MAX_TIMEOUT_SECONDS` constant.\n */\n maxTimeoutSeconds?: number;\n /**\n * Optional filter: emit only entries whose `scheme` is in this list. Combined with\n * {@link InflowAcceptsOptions.networks} as logical AND. Omit (or pass `undefined`) for \"any scheme.\"\n */\n schemes?: PaymentScheme[];\n /**\n * Optional filter: emit only entries whose `network` is in this list. Combined with\n * {@link InflowAcceptsOptions.schemes} as logical AND. Omit (or pass `undefined`) for \"any network.\"\n */\n networks?: string[];\n}\n\n/**\n * Build the `RouteConfig.accepts` array from the seller's cached `/v1/x402/config`. Each entry's `price` is\n * pre-resolved to `AssetAmount` form (asset contract address + atomic-unit amount), so the foundation middleware never\n * needs to consult the config itself. See\n * {@link https://github.com/inflowpayai/inflow-node/blob/main/docs/x402/architecture.md#inflowaccepts-algorithm | the architecture doc}\n * for the full emission and ordering rules.\n *\n * @throws {@link X402PriceParseError} When `price` matches none of the accepted forms.\n */\nexport async function inflowAccepts(\n client: InflowSellerClient,\n options: InflowAcceptsOptions,\n): Promise<PaymentOption[]> {\n const maxTimeoutSeconds = options.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;\n const priceSpec = normalizePrice(options.price);\n const { amount: parsedAmount, currency: targetCurrency } = parsePriceSpec(priceSpec);\n const config = await client.config();\n const entries: PaymentOption[] = [];\n\n // On-chain entries: one per (wallet, matching-asset, transfer-method).\n for (const wallet of config.wallets) {\n const assets = config.assets.filter(\n (a) => a.blockchain === wallet.blockchain && currencyMatches(a.currency, targetCurrency),\n );\n for (const asset of assets) {\n const methods = resolveTransferMethods(asset);\n for (const method of methods) {\n if (!includeEntry(options, SCHEMES.EXACT, asset.network)) continue;\n entries.push(\n buildOnChainOption({\n wallet,\n asset,\n method,\n amount: factorParsed(parsedAmount, asset.decimals, priceSpec.amount),\n maxTimeoutSeconds,\n }),\n );\n }\n }\n }\n\n // Non-blockchain entries: one per (paymentMethod, supported stablecoin).\n // Every scheme the server publishes flows through unchanged — the SDK\n // does not gate on specific scheme names. New schemes light up as soon\n // as the server starts including them in /v1/x402/config.\n for (const method of config.paymentMethods) {\n if (!includeEntry(options, method.scheme, method.network)) continue;\n for (const currency of resolveCurrencies(config, targetCurrency)) {\n entries.push(\n buildPaymentMethodOption({\n method,\n currency,\n amount: factorParsed(parsedAmount, method.decimals, priceSpec.amount),\n maxTimeoutSeconds,\n }),\n );\n }\n }\n\n return entries;\n}\n\n/**\n * Stablecoins the seller's config advertises for non-blockchain methods. 'USD' expands to every distinct currency\n * present in `config.assets`; any other target returns just that currency.\n */\nfunction resolveCurrencies(config: { assets: { currency: string }[] }, target: string): readonly string[] {\n if (target !== 'USD') return [target];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const a of config.assets) {\n if (!seen.has(a.currency)) {\n seen.add(a.currency);\n out.push(a.currency);\n }\n }\n return out;\n}\n\ninterface OnChainOptionArgs {\n wallet: X402WalletInfo;\n asset: X402AssetInfo;\n method: string | undefined;\n amount: string;\n maxTimeoutSeconds: number;\n}\n\nfunction buildOnChainOption(args: OnChainOptionArgs): PaymentOption {\n const { wallet, asset, method, amount, maxTimeoutSeconds } = args;\n const extra: Record<string, unknown> = {};\n // EIP-712 domain fields are only published by the server for EVM assets.\n if (asset.tokenName !== undefined) extra[EXTRA_KEYS.NAME] = asset.tokenName;\n if (asset.tokenVersion !== undefined) extra[EXTRA_KEYS.VERSION] = asset.tokenVersion;\n if (method !== undefined) extra[EXTRA_KEYS.ASSET_TRANSFER_METHOD] = method;\n // For Permit2 entries we advertise the proxy address the facilitator\n // expects as the EIP-712 `spender`. The address is canonical\n // (`CONTRACTS.PERMIT2_PROXY`) on every supported EVM chain, but\n // publishing it explicitly lets third-party buyers verify it without\n // hardcoding our SDK constant — and the value is part of the signed\n // typed-data, so the buyer needs it before signing either way.\n if (method === ASSET_TRANSFER_METHODS.PERMIT2 && asset.permit2Proxy !== undefined) {\n extra[EXTRA_KEYS.PERMIT2_PROXY] = asset.permit2Proxy;\n }\n if (wallet.feePayer !== undefined) {\n extra[EXTRA_KEYS.FEE_PAYER] = wallet.feePayer;\n }\n return {\n scheme: SCHEMES.EXACT,\n // CAIP-2 string — narrower than the foundation `Network` template\n // literal type would assume from the assignment site, so cast at the\n // construction boundary.\n network: asset.network as PaymentOption['network'],\n payTo: wallet.address,\n price: { asset: asset.assetId, amount },\n maxTimeoutSeconds,\n extra,\n };\n}\n\ninterface PaymentMethodOptionArgs {\n method: PaymentMethodInfo;\n currency: string;\n amount: string;\n maxTimeoutSeconds: number;\n}\n\nfunction buildPaymentMethodOption(args: PaymentMethodOptionArgs): PaymentOption {\n const { method, currency, amount, maxTimeoutSeconds } = args;\n const base: PaymentOption = {\n scheme: method.scheme,\n // CAIP-2 string (`'inflow:1'` for the InFlow balance ledger).\n network: method.network as PaymentOption['network'],\n payTo: method.payTo,\n // The currency name keys the InFlow ledger that gets debited.\n price: { asset: currency, amount },\n maxTimeoutSeconds,\n };\n if (method.extra !== undefined && Object.keys(method.extra).length > 0) {\n base.extra = { ...method.extra };\n }\n return base;\n}\n\n/**\n * Transfer methods to emit for an asset. The server-published `assetTransferMethod` is taken verbatim; no client-side\n * defaulting. The Permit2 proxy address is canonical and identical on every EVM chain, so the server signals Permit2\n * availability through `assetTransferMethod` alone — there is no per-asset proxy override.\n */\nfunction resolveTransferMethods(asset: X402AssetInfo): readonly (string | undefined)[] {\n return [asset.assetTransferMethod];\n}\n\nfunction includeEntry(options: InflowAcceptsOptions, scheme: PaymentScheme, network: string): boolean {\n if (options.schemes !== undefined && !options.schemes.includes(scheme)) return false;\n if (options.networks !== undefined && !options.networks.includes(network)) return false;\n return true;\n}\n\n/**\n * `'USD'` is a wildcard that matches any stablecoin asset configured for the seller (USDC, USDT, PYUSD, …); any other\n * value is matched verbatim against `X402AssetInfo.currency`.\n */\nfunction currencyMatches(assetCurrency: string, target: string): boolean {\n if (target === 'USD') return true;\n return assetCurrency === target;\n}\n\ninterface ParsedAmount {\n /** Integer part with no leading zeros (`'0'` for empty). */\n integer: string;\n /** Decimal-point digits as typed, unpadded. Empty string when no decimal part. */\n fraction: string;\n /** Currency embedded in the input, or `undefined` for the bare form. */\n embeddedCurrency: string | undefined;\n}\n\nfunction normalizePrice(input: PriceSpec | string): PriceSpec {\n return typeof input === 'string' ? { amount: input } : input;\n}\n\n/**\n * Parse one of the three accepted price-amount string forms. Does not resolve the final currency — that's\n * `parsePriceSpec`'s job once it's reconciled the embedded currency (if any) against `PriceSpec.currency`.\n */\nfunction parsePriceAmount(input: string): ParsedAmount {\n let match = PRICE_USD_REGEX.exec(input);\n if (match !== null) {\n return {\n integer: stripLeadingZeros(match[1] ?? '0'),\n fraction: match[2] ?? '',\n embeddedCurrency: 'USD',\n };\n }\n match = PRICE_WITH_CURRENCY_REGEX.exec(input);\n if (match !== null) {\n return {\n integer: stripLeadingZeros(match[1] ?? '0'),\n fraction: match[2] ?? '',\n embeddedCurrency: match[3],\n };\n }\n match = PRICE_BARE_REGEX.exec(input);\n if (match !== null) {\n return {\n integer: stripLeadingZeros(match[1] ?? '0'),\n fraction: match[2] ?? '',\n embeddedCurrency: undefined,\n };\n }\n throw new X402PriceParseError(input);\n}\n\n/**\n * Resolve a {@link PriceSpec} into a fully-parsed amount plus a final currency. The `currency` field wins on\n * disagreement with any currency embedded in `amount`. Not re-exported from the package barrel; the public surface is\n * {@link inflowAccepts}.\n *\n * @throws {@link X402PriceParseError} When neither side provides a currency or the input is unparseable.\n * @internal\n */\nexport function parsePriceSpec(price: PriceSpec): {\n amount: ParsedAmount;\n currency: string;\n} {\n const amount = parsePriceAmount(price.amount);\n const resolvedCurrency = price.currency ?? amount.embeddedCurrency;\n if (resolvedCurrency === undefined) {\n throw new X402PriceParseError(`${price.amount} (no currency in amount and no currency field supplied)`);\n }\n return { amount, currency: resolvedCurrency };\n}\n\n/**\n * Convert a price-amount string into an atomic-unit string for an asset with `decimals` decimal places (multiply by `10\n * ** decimals`). Pure string math — no `Number` or `BigInt` precision loss. Not re-exported from the package barrel;\n * the public surface is {@link inflowAccepts}, which calls this under the hood.\n *\n * @throws {@link X402PriceParseError} On unparseable input or when converting to `decimals` would truncate a non-zero\n * digit.\n * @internal\n */\nexport function toAtomicAmount(amount: string, decimals: number): string {\n const parsed = parsePriceAmount(amount);\n return factorParsed(parsed, decimals, amount);\n}\n\nfunction factorParsed(parsed: ParsedAmount, decimals: number, rawForErrorMessage: string): string {\n const fractionPlaces = parsed.fraction.length;\n // Combined string: integer * 10**fractionPlaces + fraction.\n const combined = stripLeadingZeros(`${parsed.integer}${parsed.fraction}`);\n if (decimals === fractionPlaces) return combined;\n if (decimals > fractionPlaces) {\n return `${combined}${'0'.repeat(decimals - fractionPlaces)}`;\n }\n // decimals < fractionPlaces: drop trailing digits (must be zero).\n const drop = fractionPlaces - decimals;\n const trimmed = combined.slice(0, -drop);\n const dropped = combined.slice(-drop);\n if (!/^0*$/u.test(dropped)) {\n throw new X402PriceParseError(\n `${rawForErrorMessage} (cannot be expressed in ${decimals.toString()} decimals without truncation)`,\n );\n }\n return trimmed.length === 0 ? '0' : trimmed;\n}\n\nfunction stripLeadingZeros(s: string): string {\n const stripped = s.replace(/^0+/u, '');\n return stripped.length === 0 ? '0' : stripped;\n}\n","import { SCHEMES } from '@inflowpayai/x402';\nimport type {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n SupportedKind,\n} from '@x402/core/types';\n\nimport type { InflowSellerClient } from './seller-client.js';\n\n/**\n * Structural shape of `@x402/express` and `@x402/hono`'s `SchemeRegistration` interface — `{ network, server }` —\n * declared locally so this package stays platform-neutral. Both adapter packages export a `SchemeRegistration`\n * interface composed of the same `@x402/core/types` types, so {@link InflowSchemeRegistration} is structurally\n * assignable to either.\n */\nexport interface InflowSchemeRegistration {\n network: Network;\n server: SchemeNetworkServer;\n}\n\n/**\n * Build the passthrough `SchemeRegistration[]` for every `(scheme, network)` pair the seller's `/v1/x402/config` can\n * emit. Pass the result as the third argument to `paymentMiddlewareFromConfig` — the foundation refuses to boot\n * otherwise (`hasRegisteredScheme` is checked before facilitator support). Deduplicated: multiple assets on the same\n * network collapse to one registration. See the architecture doc for the rationale.\n */\nexport async function inflowSchemeRegistrations(client: InflowSellerClient): Promise<InflowSchemeRegistration[]> {\n const config = await client.config();\n const registrations: InflowSchemeRegistration[] = [];\n const seen = new Set<string>();\n\n function add(scheme: string, network: string): void {\n const key = `${scheme}|${network}`;\n if (seen.has(key)) return;\n seen.add(key);\n registrations.push({\n // Boundary cast to the foundation's `${string}:${string}` Network\n // type. Every value passing through (CAIP-2 chain ids and\n // `'inflow:1'`) is CAIP-2 shaped at runtime.\n network: network as Network,\n server: inflowPassthroughScheme(scheme),\n });\n }\n\n // On-chain entries: `'exact'` scheme on every distinct asset.network.\n // Multiple assets per network (USDC + USDT on the same chain) collapse\n // to a single registration thanks to `seen`.\n for (const asset of config.assets) {\n add(SCHEMES.EXACT, asset.network);\n }\n\n // Non-blockchain entries: scheme + network from each payment method\n // (e.g. `'balance' / 'inflow:1'`). Every scheme the server publishes\n // registers; the SDK does not enumerate an allowlist.\n for (const method of config.paymentMethods) {\n add(method.scheme, method.network);\n }\n\n return registrations;\n}\n\n// Passthrough `SchemeNetworkServer`: declares `scheme` so\n// `hasRegisteredScheme` returns true, then forwards both hooks\n// unchanged. The `parsePrice` rejection on `Money`-form input is\n// deliberate — non-`AssetAmount` prices reach this only when a route\n// bypassed `inflowAccepts`, and we can't safely guess the asset's\n// decimals here.\nfunction inflowPassthroughScheme(scheme: string): SchemeNetworkServer {\n return {\n scheme,\n parsePrice(price: Price, _network: Network): Promise<AssetAmount> {\n if (typeof price !== 'object' || price === null || !('asset' in price) || !('amount' in price)) {\n return Promise.reject(\n new Error(\n `inflowPassthroughScheme: parsePrice expected AssetAmount-form price ` +\n `(use inflowAccepts to build PaymentOption.price); got ${JSON.stringify(price)}`,\n ),\n );\n }\n // Reassemble explicitly so `exactOptionalPropertyTypes` is happy:\n // only attach `extra` when it's actually present.\n const out: AssetAmount =\n price.extra !== undefined\n ? { asset: price.asset, amount: price.amount, extra: price.extra }\n : { asset: price.asset, amount: price.amount };\n return Promise.resolve(out);\n },\n enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n _supportedKind: SupportedKind,\n _facilitatorExtensions: string[],\n ): Promise<PaymentRequirements> {\n return Promise.resolve(paymentRequirements);\n },\n };\n}\n"]}
|