@dexterai/x402 1.5.0 → 1.5.2
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/README.md +133 -1
- package/dist/client/index.cjs +6 -12
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.js +6 -12
- package/dist/client/index.js.map +1 -1
- package/dist/react/index.cjs +9 -13
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +9 -13
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
x402 is a protocol for HTTP-native micropayments. When a server returns HTTP status `402 Payment Required`, it includes payment details in a `PAYMENT-REQUIRED` header. The client signs a payment transaction and retries the request with a `PAYMENT-SIGNATURE` header. The server verifies and settles the payment, then returns the protected content.
|
|
26
26
|
|
|
27
|
-
This SDK handles the entire flow automatically—you just call `fetch()` and payments happen transparently.
|
|
27
|
+
This SDK handles the entire flow automatically—you just call `fetch()` and payments happen transparently. With **Access Pass** mode, buyers pay once and get unlimited access for a time window—no per-request signing needed.
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
@@ -36,6 +36,8 @@ This SDK handles the entire flow automatically—you just call `fetch()` and pay
|
|
|
36
36
|
|
|
37
37
|
**Token-accurate LLM pricing.** Built-in [tiktoken](https://github.com/openai/tiktoken) support prices AI requests by actual token count. Works with OpenAI models out of the box, or bring your own rates for Anthropic, Gemini, Mistral, or local models.
|
|
38
38
|
|
|
39
|
+
**Access Pass.** Pay once, get unlimited access for a time window. Buyers connect a wallet, make one payment, and receive a JWT token that works like an API key—no per-request signing, no private keys in code. The Stripe replacement for crypto-native APIs.
|
|
40
|
+
|
|
39
41
|
**Full-stack.** Client SDK for browsers, server SDK for backends. React hooks, Express middleware patterns, facilitator client—everything you need.
|
|
40
42
|
|
|
41
43
|
**Multi-chain.** Solana and Base (Ethereum L2) with the same API. Add wallets for both and the SDK picks the right one automatically.
|
|
@@ -158,12 +160,18 @@ import { useX402Payment } from '@dexterai/x402/react';
|
|
|
158
160
|
// Server - Express middleware
|
|
159
161
|
import { x402Middleware } from '@dexterai/x402/server';
|
|
160
162
|
|
|
163
|
+
// Server - Access Pass (pay once, unlimited requests)
|
|
164
|
+
import { x402AccessPass } from '@dexterai/x402/server';
|
|
165
|
+
|
|
161
166
|
// Server - manual control
|
|
162
167
|
import { createX402Server } from '@dexterai/x402/server';
|
|
163
168
|
|
|
164
169
|
// Server - dynamic pricing
|
|
165
170
|
import { createDynamicPricing, createTokenPricing } from '@dexterai/x402/server';
|
|
166
171
|
|
|
172
|
+
// React - Access Pass hook
|
|
173
|
+
import { useAccessPass } from '@dexterai/x402/react';
|
|
174
|
+
|
|
167
175
|
// Chain adapters (advanced)
|
|
168
176
|
import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';
|
|
169
177
|
|
|
@@ -221,6 +229,96 @@ Options:
|
|
|
221
229
|
- `facilitatorUrl` — Override facilitator (default: x402.dexter.cash)
|
|
222
230
|
- `verbose` — Enable debug logging
|
|
223
231
|
|
|
232
|
+
### Access Pass — Pay Once, Unlimited Requests
|
|
233
|
+
|
|
234
|
+
Replace API keys with time-limited access passes. Buyers make one payment and get a JWT token for unlimited requests during a time window.
|
|
235
|
+
|
|
236
|
+
**Server:**
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import express from 'express';
|
|
240
|
+
import { x402AccessPass } from '@dexterai/x402/server';
|
|
241
|
+
|
|
242
|
+
const app = express();
|
|
243
|
+
|
|
244
|
+
// Protect all /api routes with access pass
|
|
245
|
+
app.use('/api', x402AccessPass({
|
|
246
|
+
payTo: 'YourSolanaAddress...',
|
|
247
|
+
tiers: {
|
|
248
|
+
'1h': '0.50', // $0.50 for 1 hour
|
|
249
|
+
'24h': '2.00', // $2.00 for 24 hours
|
|
250
|
+
},
|
|
251
|
+
ratePerHour: '0.50', // also accept custom durations
|
|
252
|
+
}));
|
|
253
|
+
|
|
254
|
+
app.get('/api/data', (req, res) => {
|
|
255
|
+
// Only runs with a valid access pass
|
|
256
|
+
res.json({ data: 'premium content' });
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Client (Node.js):**
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { wrapFetch } from '@dexterai/x402/client';
|
|
264
|
+
|
|
265
|
+
const x402Fetch = wrapFetch(fetch, {
|
|
266
|
+
walletPrivateKey: process.env.SOLANA_PRIVATE_KEY,
|
|
267
|
+
accessPass: { preferTier: '1h', maxSpend: '1.00' },
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// First call: auto-purchases a 1-hour pass ($0.50 USDC)
|
|
271
|
+
const res1 = await x402Fetch('https://api.example.com/api/data');
|
|
272
|
+
|
|
273
|
+
// All subsequent calls for the next hour: uses cached JWT, zero payment
|
|
274
|
+
const res2 = await x402Fetch('https://api.example.com/api/data');
|
|
275
|
+
const res3 = await x402Fetch('https://api.example.com/api/data');
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**React:**
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import { useAccessPass } from '@dexterai/x402/react';
|
|
282
|
+
|
|
283
|
+
function Dashboard() {
|
|
284
|
+
const { tiers, pass, isPassValid, purchasePass, fetch: apFetch } = useAccessPass({
|
|
285
|
+
wallets: { solana: solanaWallet },
|
|
286
|
+
resourceUrl: 'https://api.example.com',
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<div>
|
|
291
|
+
{!isPassValid && tiers?.map(t => (
|
|
292
|
+
<button key={t.id} onClick={() => purchasePass(t.id)}>
|
|
293
|
+
{t.label} — ${t.price}
|
|
294
|
+
</button>
|
|
295
|
+
))}
|
|
296
|
+
{isPassValid && <p>Pass active! {pass?.remainingSeconds}s remaining</p>}
|
|
297
|
+
<button onClick={() => apFetch('/api/data')}>Fetch Data</button>
|
|
298
|
+
</div>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**How it works:**
|
|
304
|
+
1. Client requests a protected endpoint → Server returns `402` with `X-ACCESS-PASS-TIERS` header
|
|
305
|
+
2. Client selects a tier and pays via x402 → Server verifies, settles, issues a JWT
|
|
306
|
+
3. Server returns `200` with `ACCESS-PASS` header containing the JWT
|
|
307
|
+
4. Client caches the JWT and includes it as `Authorization: Bearer <token>` on all subsequent requests
|
|
308
|
+
5. Server validates the JWT locally (no facilitator call) → instant response
|
|
309
|
+
|
|
310
|
+
Options:
|
|
311
|
+
- `payTo` — Address to receive payments
|
|
312
|
+
- `tiers` — Named duration tiers with prices (e.g., `{ '1h': '0.50' }`)
|
|
313
|
+
- `ratePerHour` — Rate for custom durations (buyer sends `?duration=<seconds>`)
|
|
314
|
+
- `network` — CAIP-2 network (default: Solana mainnet)
|
|
315
|
+
- `secret` — HMAC secret for JWT signing (auto-generated if not provided)
|
|
316
|
+
- `facilitatorUrl` — Override facilitator (default: x402.dexter.cash)
|
|
317
|
+
|
|
318
|
+
**[Live demo →](https://dexter.cash/access-pass)**
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
224
322
|
### Manual Server (Advanced)
|
|
225
323
|
|
|
226
324
|
For more control over the payment flow:
|
|
@@ -429,6 +527,18 @@ tiktoken's default encoding works well for most transformer models. Only use a c
|
|
|
429
527
|
| `maxAmountAtomic` | `string` | No | Maximum payment cap |
|
|
430
528
|
| `verbose` | `boolean` | No | Enable debug logging |
|
|
431
529
|
|
|
530
|
+
### `x402AccessPass(options)`
|
|
531
|
+
|
|
532
|
+
| Option | Type | Required | Description |
|
|
533
|
+
|--------|------|----------|-------------|
|
|
534
|
+
| `payTo` | `string` | Yes | Address to receive payments |
|
|
535
|
+
| `tiers` | `Record<string, string>` | One of `tiers` or `ratePerHour` | Named tiers (e.g., `{ '1h': '0.50' }`) |
|
|
536
|
+
| `ratePerHour` | `string` | One of `tiers` or `ratePerHour` | USD rate for custom durations |
|
|
537
|
+
| `network` | `string` | No | CAIP-2 network (default: Solana mainnet) |
|
|
538
|
+
| `secret` | `Buffer` | No | HMAC secret for JWT (auto-generated) |
|
|
539
|
+
| `facilitatorUrl` | `string` | No | Facilitator URL (default: x402.dexter.cash) |
|
|
540
|
+
| `verbose` | `boolean` | No | Enable debug logging |
|
|
541
|
+
|
|
432
542
|
### `useX402Payment(options)`
|
|
433
543
|
|
|
434
544
|
Returns:
|
|
@@ -444,6 +554,27 @@ Returns:
|
|
|
444
554
|
| `balances` | `Balance[]` | Token balances per chain |
|
|
445
555
|
| `refreshBalances` | `function` | Manual refresh |
|
|
446
556
|
| `reset` | `function` | Clear state |
|
|
557
|
+
| `accessPass` | `object?` | Active pass state (tier, expiresAt, remainingSeconds) |
|
|
558
|
+
|
|
559
|
+
### `useAccessPass(options)`
|
|
560
|
+
|
|
561
|
+
| Option | Type | Required | Description |
|
|
562
|
+
|--------|------|----------|-------------|
|
|
563
|
+
| `wallets` | `{ solana?, evm? }` | Yes | Multi-chain wallets |
|
|
564
|
+
| `resourceUrl` | `string` | Yes | The x402 resource base URL |
|
|
565
|
+
| `preferredNetwork` | `string` | No | Prefer this network |
|
|
566
|
+
| `autoConnect` | `boolean` | No | Auto-fetch tiers on mount (default: true) |
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
|
|
570
|
+
| Property | Type | Description |
|
|
571
|
+
|----------|------|-------------|
|
|
572
|
+
| `tiers` | `AccessPassTier[]?` | Available tiers from server |
|
|
573
|
+
| `pass` | `object?` | Active pass (jwt, tier, expiresAt, remainingSeconds) |
|
|
574
|
+
| `isPassValid` | `boolean` | Whether pass is active and not expired |
|
|
575
|
+
| `purchasePass` | `function` | Buy a pass for a tier or custom duration |
|
|
576
|
+
| `isPurchasing` | `boolean` | Purchase in progress |
|
|
577
|
+
| `fetch` | `function` | Fetch with auto pass inclusion |
|
|
447
578
|
|
|
448
579
|
---
|
|
449
580
|
|
|
@@ -466,5 +597,6 @@ MIT — see [LICENSE](./LICENSE)
|
|
|
466
597
|
<p align="center">
|
|
467
598
|
<a href="https://x402.dexter.cash">Dexter Facilitator</a> ·
|
|
468
599
|
<a href="https://dexter.cash/sdk">Live Demo</a> ·
|
|
600
|
+
<a href="https://dexter.cash/access-pass">Access Pass Demo</a> ·
|
|
469
601
|
<a href="https://dexter.cash/onboard">Become a Seller</a>
|
|
470
602
|
</p>
|
package/dist/client/index.cjs
CHANGED
|
@@ -771,8 +771,10 @@ function createX402Client(config) {
|
|
|
771
771
|
const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
|
|
772
772
|
const passResponse = await customFetch(passUrl, {
|
|
773
773
|
...init,
|
|
774
|
+
method: "POST",
|
|
774
775
|
headers: {
|
|
775
776
|
...init?.headers || {},
|
|
777
|
+
"Content-Type": "application/json",
|
|
776
778
|
"PAYMENT-SIGNATURE": paymentSignatureHeader
|
|
777
779
|
}
|
|
778
780
|
});
|
|
@@ -781,19 +783,11 @@ function createX402Client(config) {
|
|
|
781
783
|
return null;
|
|
782
784
|
}
|
|
783
785
|
const accessPassJwt = passResponse.headers.get("ACCESS-PASS");
|
|
784
|
-
if (
|
|
785
|
-
|
|
786
|
+
if (accessPassJwt) {
|
|
787
|
+
cachePass(url, accessPassJwt);
|
|
788
|
+
log("Access pass purchased and cached");
|
|
786
789
|
}
|
|
787
|
-
|
|
788
|
-
log("Access pass purchased and cached");
|
|
789
|
-
const retryResponse = await customFetch(input, {
|
|
790
|
-
...init,
|
|
791
|
-
headers: {
|
|
792
|
-
...init?.headers || {},
|
|
793
|
-
"Authorization": `Bearer ${accessPassJwt}`
|
|
794
|
-
}
|
|
795
|
-
});
|
|
796
|
-
return retryResponse;
|
|
790
|
+
return passResponse;
|
|
797
791
|
}
|
|
798
792
|
async function x402Fetch(input, init) {
|
|
799
793
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|