@inflowpayai/x402-buyer 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 +129 -0
- package/dist/index.cjs +592 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +427 -0
- package/dist/index.d.ts +427 -0
- package/dist/index.js +576 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -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,129 @@
|
|
|
1
|
+
# @inflowpayai/x402-buyer
|
|
2
|
+
|
|
3
|
+
Buyer-side InFlow primitives that plug into the foundation V2 buyer transport (`x402HTTPClient` from `@x402/core`). This package ships
|
|
4
|
+
**`InflowClient`** — a subclass of `@x402/core`'s `x402Client` that routes InFlow-acceptable `(scheme, network)` pairs through the InFlow
|
|
5
|
+
MPC signing flow and delegates everything else to foundation-managed schemes registered on the same instance.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @inflowpayai/x402-buyer @x402/core
|
|
11
|
+
# …add @x402/evm or @x402/svm as needed for on-chain signing
|
|
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
|
+
- `createInflowClient(options)` — async factory. Returns a primed `InflowClient`. Primes the buyer capability cache before
|
|
19
|
+
resolving, so the routing decision inside `createPaymentPayload` is synchronous against in-memory data.
|
|
20
|
+
- `InflowClient` — `extends @x402/core/client.x402Client`. Overrides `createPaymentPayload` to route to InFlow first and fall back to
|
|
21
|
+
foundation-registered schemes. Adds `prepareInflowPayment` for callers that want to surface pending-approval UI before the protected
|
|
22
|
+
request is replayed.
|
|
23
|
+
- `parseEvmPrivateKey`, `decodeSolanaSecret` — key-decoding helpers for callers wiring up foundation EVM/SVM schemes from existing
|
|
24
|
+
InFlow-managed wallet exports.
|
|
25
|
+
- Typed errors: `X402AdapterRoutingError`, `X402ApprovalCancelledError`, `X402ApprovalFailedError`, `X402ApprovalTimeoutError`,
|
|
26
|
+
`X402PaymentIdFormatError`, `X402InvalidEvmKeyError`, `X402InvalidSolanaKeyError`.
|
|
27
|
+
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { createInflowClient } from '@inflowpayai/x402-buyer';
|
|
32
|
+
import { x402HTTPClient } from '@x402/core/client';
|
|
33
|
+
|
|
34
|
+
const core = await createInflowClient({
|
|
35
|
+
apiKey: process.env.INFLOW_API_KEY!,
|
|
36
|
+
environment: 'sandbox',
|
|
37
|
+
});
|
|
38
|
+
const http = new x402HTTPClient(core);
|
|
39
|
+
|
|
40
|
+
const initial = await fetch('https://api.example.com/widgets');
|
|
41
|
+
if (initial.status === 402) {
|
|
42
|
+
const paymentRequired = http.getPaymentRequiredResponse((n) => initial.headers.get(n));
|
|
43
|
+
const paymentPayload = await http.createPaymentPayload(paymentRequired);
|
|
44
|
+
const paymentHeaders = http.encodePaymentSignatureHeader(paymentPayload);
|
|
45
|
+
const paid = await fetch('https://api.example.com/widgets', { headers: paymentHeaders });
|
|
46
|
+
const result = await http.processResponse(paid);
|
|
47
|
+
if (result.kind === 'success') {
|
|
48
|
+
console.log(result.body, result.settleResponse.transaction);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The same composition works with axios — see [`examples/x402-buyer-axios`](../../examples/x402-buyer-axios) for the variant that swaps `fetch`
|
|
54
|
+
for an axios call and decodes the response header with `decodePaymentResponseHeader` from `@x402/core/http`.
|
|
55
|
+
|
|
56
|
+
## Composing with foundation schemes
|
|
57
|
+
|
|
58
|
+
`InflowClient` extends `@x402/core`'s `x402Client`, so foundation registration helpers accept it directly:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { createInflowClient } from '@inflowpayai/x402-buyer';
|
|
62
|
+
import { x402HTTPClient } from '@x402/core/client';
|
|
63
|
+
import { registerExactEvmScheme } from '@x402/evm/exact/client';
|
|
64
|
+
import { registerExactSvmScheme } from '@x402/svm/exact/client';
|
|
65
|
+
|
|
66
|
+
const core = await createInflowClient({ apiKey, environment: 'sandbox' });
|
|
67
|
+
registerExactEvmScheme(core, { signer: evmAccount, networks: ['eip155:1'] });
|
|
68
|
+
registerExactSvmScheme(core, { signer: svmKeypair, networks: ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'] });
|
|
69
|
+
|
|
70
|
+
const http = new x402HTTPClient(core);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
When the seller's 402 offers a requirement InFlow signs (`balance/inflow:1`, or any `(scheme, network)` advertised by the buyer capability
|
|
74
|
+
cache), the InFlow path wins. Otherwise the foundation's selector routes to whatever EVM or SVM scheme the caller registered. The
|
|
75
|
+
foundation methods (`register`, `registerPolicy`, `onBeforePaymentCreation`, …) are return-type narrowed to `this` so chaining preserves
|
|
76
|
+
the `InflowClient` type.
|
|
77
|
+
|
|
78
|
+
## Two-phase signing (pending-approval UI)
|
|
79
|
+
|
|
80
|
+
For callers that want to surface a pending-approval state to the user before the protected request is replayed, `prepareInflowPayment`
|
|
81
|
+
returns a `PreparedPayment` handle:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const prepared = await core.prepareInflowPayment(requirement, {
|
|
85
|
+
resource: paymentRequired.resource,
|
|
86
|
+
x402Version: paymentRequired.x402Version,
|
|
87
|
+
});
|
|
88
|
+
console.log(`approval ${prepared.approvalId} pending — show dashboard prompt`);
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const payment = await prepared.awaitPayload({ timeoutMs: 5 * 60 * 1000 });
|
|
92
|
+
console.log(payment.encodedPayload);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
void prepared.cancel(); // fire-and-forget; never rejects
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The two-phase flow is InFlow-specific — there's no foundation equivalent. `prepareInflowPayment` throws `X402AdapterRoutingError` if
|
|
100
|
+
the requirement is not in the InFlow buyer capability cache.
|
|
101
|
+
|
|
102
|
+
## Signing timeouts
|
|
103
|
+
|
|
104
|
+
`SignOptions.timeoutMs` defaults to **15 minutes** to match the server-side approval expiry. `SignOptions.pollIntervalMs` defaults to
|
|
105
|
+
**5 seconds** — caller-overridable, no jitter or backoff. Transient 5xx errors during a single poll are swallowed; the loop is itself the retry.
|
|
106
|
+
|
|
107
|
+
## Caller-supplied payment IDs
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { generatePaymentId } from '@inflowpayai/x402/extensions';
|
|
111
|
+
|
|
112
|
+
const paymentId = generatePaymentId(); // 'pay_<32 hex>'
|
|
113
|
+
const prepared = await core.prepareInflowPayment(requirement, context, { paymentId });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The ID is forwarded to the server's `remotePaymentId` field and embedded in the resulting `PaymentPayload.extensions['payment-identifier']`.
|
|
117
|
+
Invalid format (16–128 chars, `^[a-zA-Z0-9_-]+$`) throws `X402PaymentIdFormatError` before any server round trip. The one-shot
|
|
118
|
+
`createPaymentPayload` path doesn't carry a per-call `paymentId` — use `prepareInflowPayment` when a custom ID is required.
|
|
119
|
+
|
|
120
|
+
## See also
|
|
121
|
+
|
|
122
|
+
- [@inflowpayai/x402](../x402) — protocol types and HTTP client
|
|
123
|
+
- [Product overview](../../docs/x402/README.md)
|
|
124
|
+
- [Architecture](../../docs/x402/architecture.md) — buyer-side composition, request lifecycle, conflict precedence
|
|
125
|
+
- [Extensions](../../docs/x402/extensions.md) — `payment-identifier` end-to-end
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT.
|