@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 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.