@dexterai/x402 1.0.3 โ 1.0.4
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 +139 -162
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,135 +2,91 @@
|
|
|
2
2
|
<img src="./assets/dexter-wordmark.svg" alt="Dexter" width="360">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<h1 align="center">@dexterai/x402</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<
|
|
9
|
-
<a href="https://www.npmjs.com/package/@dexterai/x402"><img src="https://img.shields.io/npm/v/@dexterai/x402.svg" alt="npm version"></a>
|
|
10
|
-
<a href="https://x402.dexter.cash"><img src="https://img.shields.io/badge/facilitator-x402.dexter.cash-orange.svg" alt="x402 Facilitator"></a>
|
|
8
|
+
<strong>The x402 SDK that actually works.</strong>
|
|
11
9
|
</p>
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@dexterai/x402"><img src="https://img.shields.io/npm/v/@dexterai/x402.svg" alt="npm"></a>
|
|
13
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E=18-brightgreen.svg" alt="Node"></a>
|
|
14
|
+
<a href="https://dexter.cash/sdk"><img src="https://img.shields.io/badge/๐ฎ_Live_Demo-dexter.cash%2Fsdk-blueviolet" alt="Live Demo"></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://dexter.cash/sdk"><strong>๐ Try it with real payments โ</strong></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## โจ Why This SDK?
|
|
24
|
+
|
|
25
|
+
- **๐ Multi-chain** โ Solana and Base, same API
|
|
26
|
+
- **โก x402 v2** โ Full protocol support, verified working
|
|
27
|
+
- **โ๏ธ React Hook** โ `useX402Payment` with loading states, balances, and transaction tracking
|
|
28
|
+
- **๐ฐ Smart Balance Check** โ Clear "insufficient funds" error *before* the wallet popup
|
|
29
|
+
- **๐ป Phantom Compatible** โ Handles Lighthouse safety assertions automatically
|
|
30
|
+
- **๐ฆ Zero Config** โ Wrap `fetch()`, payments just work
|
|
14
31
|
|
|
15
32
|
---
|
|
16
33
|
|
|
17
|
-
##
|
|
34
|
+
## ๐ฎ See It Working
|
|
18
35
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
**Don't take our word for it.** Make a real payment yourself:
|
|
37
|
+
|
|
38
|
+
**[โ dexter.cash/sdk](https://dexter.cash/sdk)**
|
|
39
|
+
|
|
40
|
+
The demo uses this exact SDK. Solana and Base. Real USDC. Real transactions.
|
|
24
41
|
|
|
25
42
|
---
|
|
26
43
|
|
|
27
|
-
## Quick Start
|
|
44
|
+
## ๐ Quick Start
|
|
28
45
|
|
|
29
46
|
### Install
|
|
30
47
|
|
|
31
48
|
```bash
|
|
32
|
-
npm install @dexterai/x402
|
|
49
|
+
npm install @dexterai/x402
|
|
33
50
|
```
|
|
34
51
|
|
|
35
|
-
### Client (Browser
|
|
52
|
+
### Client (Browser)
|
|
36
53
|
|
|
37
54
|
```typescript
|
|
38
55
|
import { createX402Client } from '@dexterai/x402/client';
|
|
39
56
|
|
|
40
|
-
// Single wallet (Solana)
|
|
41
|
-
const client = createX402Client({
|
|
42
|
-
wallet: solanaWallet,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Multi-chain: provide wallets for each chain
|
|
46
57
|
const client = createX402Client({
|
|
47
58
|
wallets: {
|
|
48
59
|
solana: solanaWallet,
|
|
49
|
-
evm: evmWallet,
|
|
60
|
+
evm: evmWallet,
|
|
61
|
+
},
|
|
62
|
+
rpcUrls: {
|
|
63
|
+
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': 'https://your-solana-rpc.com',
|
|
64
|
+
'eip155:8453': 'https://your-base-rpc.com',
|
|
50
65
|
},
|
|
51
|
-
preferredNetwork: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
52
66
|
});
|
|
53
67
|
|
|
54
|
-
//
|
|
68
|
+
// That's it. 402 responses are handled automatically.
|
|
55
69
|
const response = await client.fetch('https://api.example.com/protected');
|
|
56
70
|
```
|
|
57
71
|
|
|
58
|
-
### Server (Express/Next.js)
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import { createX402Server } from '@dexterai/x402/server';
|
|
62
|
-
|
|
63
|
-
// Create server for Solana payments
|
|
64
|
-
const server = createX402Server({
|
|
65
|
-
payTo: 'YourSolanaAddress...',
|
|
66
|
-
network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Or for Base payments
|
|
70
|
-
const baseServer = createX402Server({
|
|
71
|
-
payTo: '0xYourEvmAddress...',
|
|
72
|
-
network: 'eip155:8453',
|
|
73
|
-
asset: { address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', decimals: 6 },
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// In your route handler
|
|
77
|
-
app.post('/protected', async (req, res) => {
|
|
78
|
-
const paymentSig = req.headers['payment-signature'];
|
|
79
|
-
|
|
80
|
-
if (!paymentSig) {
|
|
81
|
-
const requirements = await server.buildRequirements({
|
|
82
|
-
amountAtomic: '50000', // 0.05 USDC
|
|
83
|
-
resourceUrl: req.originalUrl,
|
|
84
|
-
});
|
|
85
|
-
res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));
|
|
86
|
-
return res.status(402).json({});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const result = await server.settlePayment(paymentSig);
|
|
90
|
-
if (!result.success) {
|
|
91
|
-
return res.status(402).json({ error: result.errorReason });
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
res.json({ data: 'protected content', transaction: result.transaction });
|
|
95
|
-
});
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
> โ ๏ธ **Note:** The server SDK (`createX402Server`) has not been battle-tested in production.
|
|
99
|
-
> The client SDK and React hook have been verified with real payments.
|
|
100
|
-
|
|
101
72
|
### React
|
|
102
73
|
|
|
103
74
|
```tsx
|
|
104
75
|
import { useX402Payment } from '@dexterai/x402/react';
|
|
105
|
-
import { useWallet } from '@solana/wallet-adapter-react';
|
|
106
|
-
import { useAccount } from 'wagmi';
|
|
107
76
|
|
|
108
77
|
function PayButton() {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const {
|
|
113
|
-
fetch,
|
|
114
|
-
isLoading,
|
|
115
|
-
balances,
|
|
116
|
-
connectedChains,
|
|
117
|
-
transactionUrl,
|
|
118
|
-
} = useX402Payment({
|
|
119
|
-
wallets: {
|
|
120
|
-
solana: solanaWallet,
|
|
121
|
-
evm: evmWallet,
|
|
122
|
-
},
|
|
78
|
+
const { fetch, isLoading, balances, transactionUrl } = useX402Payment({
|
|
79
|
+
wallets: { solana: solanaWallet, evm: evmWallet },
|
|
80
|
+
rpcUrls: { /* your RPC endpoints */ },
|
|
123
81
|
});
|
|
124
82
|
|
|
125
83
|
return (
|
|
126
84
|
<div>
|
|
127
|
-
{balances.
|
|
128
|
-
<p key={b.network}>{b.chainName}: ${b.balance.toFixed(2)}</p>
|
|
129
|
-
))}
|
|
85
|
+
<p>Balance: ${balances[0]?.balance.toFixed(2)}</p>
|
|
130
86
|
<button onClick={() => fetch(url)} disabled={isLoading}>
|
|
131
|
-
{isLoading ? 'Paying...' : 'Pay
|
|
87
|
+
{isLoading ? 'Paying...' : 'Pay'}
|
|
132
88
|
</button>
|
|
133
|
-
{transactionUrl && <a href={transactionUrl}>View Transaction
|
|
89
|
+
{transactionUrl && <a href={transactionUrl}>View Transaction โ</a>}
|
|
134
90
|
</div>
|
|
135
91
|
);
|
|
136
92
|
}
|
|
@@ -138,120 +94,141 @@ function PayButton() {
|
|
|
138
94
|
|
|
139
95
|
---
|
|
140
96
|
|
|
141
|
-
## Supported Networks
|
|
97
|
+
## ๐ Supported Networks
|
|
142
98
|
|
|
143
|
-
| Network |
|
|
144
|
-
|
|
145
|
-
| Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` |
|
|
146
|
-
| Base Mainnet | `eip155:8453` |
|
|
147
|
-
| Arbitrum One | `eip155:42161` | USDC |
|
|
148
|
-
| Ethereum | `eip155:1` | USDC |
|
|
99
|
+
| Network | Identifier | Status |
|
|
100
|
+
|---------|------------|--------|
|
|
101
|
+
| Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | โ
Verified |
|
|
102
|
+
| Base Mainnet | `eip155:8453` | โ
Verified |
|
|
149
103
|
|
|
150
|
-
|
|
104
|
+
All networks use USDC.
|
|
151
105
|
|
|
152
|
-
|
|
106
|
+
---
|
|
153
107
|
|
|
154
|
-
|
|
108
|
+
## ๐ฆ Package Exports
|
|
155
109
|
|
|
156
110
|
```typescript
|
|
111
|
+
// Client - browser & Node.js
|
|
157
112
|
import { createX402Client } from '@dexterai/x402/client';
|
|
158
113
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
114
|
+
// React hook
|
|
115
|
+
import { useX402Payment } from '@dexterai/x402/react';
|
|
116
|
+
|
|
117
|
+
// Server helpers (see note below)
|
|
118
|
+
import { createX402Server } from '@dexterai/x402/server';
|
|
119
|
+
|
|
120
|
+
// Chain adapters (advanced)
|
|
121
|
+
import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';
|
|
122
|
+
|
|
123
|
+
// Utilities
|
|
124
|
+
import { toAtomicUnits, fromAtomicUnits } from '@dexterai/x402/utils';
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## ๐ ๏ธ Utilities
|
|
167
130
|
|
|
168
|
-
|
|
131
|
+
```typescript
|
|
132
|
+
import { toAtomicUnits, fromAtomicUnits } from '@dexterai/x402/utils';
|
|
133
|
+
|
|
134
|
+
// Convert dollars to atomic units (for API calls)
|
|
135
|
+
toAtomicUnits(0.05, 6); // '50000'
|
|
136
|
+
toAtomicUnits(1.50, 6); // '1500000'
|
|
137
|
+
|
|
138
|
+
// Convert atomic units back to dollars (for display)
|
|
139
|
+
fromAtomicUnits('50000', 6); // 0.05
|
|
140
|
+
fromAtomicUnits(1500000n, 6); // 1.5
|
|
169
141
|
```
|
|
170
142
|
|
|
171
|
-
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## ๐ฅ๏ธ Server SDK
|
|
172
146
|
|
|
173
147
|
```typescript
|
|
174
148
|
import { createX402Server } from '@dexterai/x402/server';
|
|
175
149
|
|
|
176
150
|
const server = createX402Server({
|
|
177
|
-
payTo: '
|
|
151
|
+
payTo: 'YourAddress...',
|
|
178
152
|
network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
179
|
-
asset: { address: 'mint', decimals: 6 },
|
|
180
153
|
facilitatorUrl: 'https://x402.dexter.cash',
|
|
181
|
-
defaultTimeoutSeconds: 60,
|
|
182
154
|
});
|
|
183
155
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
await server.settlePayment(header);
|
|
188
|
-
```
|
|
156
|
+
// In your route handler
|
|
157
|
+
app.post('/protected', async (req, res) => {
|
|
158
|
+
const paymentSig = req.headers['payment-signature'];
|
|
189
159
|
|
|
190
|
-
|
|
160
|
+
if (!paymentSig) {
|
|
161
|
+
const requirements = await server.buildRequirements({
|
|
162
|
+
amountAtomic: '50000', // $0.05 USDC
|
|
163
|
+
resourceUrl: req.originalUrl,
|
|
164
|
+
});
|
|
165
|
+
res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));
|
|
166
|
+
return res.status(402).json({});
|
|
167
|
+
}
|
|
191
168
|
|
|
192
|
-
|
|
193
|
-
|
|
169
|
+
const result = await server.settlePayment(paymentSig);
|
|
170
|
+
if (!result.success) {
|
|
171
|
+
return res.status(402).json({ error: result.errorReason });
|
|
172
|
+
}
|
|
194
173
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
isLoading, // Payment in progress
|
|
198
|
-
status, // 'idle' | 'pending' | 'success' | 'error'
|
|
199
|
-
error, // Error if failed
|
|
200
|
-
transactionId, // Tx signature on success
|
|
201
|
-
transactionUrl, // Explorer link
|
|
202
|
-
balances, // Token balances per chain
|
|
203
|
-
connectedChains, // { solana: bool, evm: bool }
|
|
204
|
-
reset, // Clear state
|
|
205
|
-
refreshBalances, // Manual balance refresh
|
|
206
|
-
} = useX402Payment({ wallets, preferredNetwork, verbose });
|
|
174
|
+
res.json({ data: 'Your protected content' });
|
|
175
|
+
});
|
|
207
176
|
```
|
|
208
177
|
|
|
209
|
-
|
|
178
|
+
> โ ๏ธ **Note:** The server SDK has not been battle-tested in production yet. The client SDK and React hook have been verified with real payments at [dexter.cash/sdk](https://dexter.cash/sdk).
|
|
210
179
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## ๐ API Reference
|
|
183
|
+
|
|
184
|
+
### `createX402Client(options)`
|
|
185
|
+
|
|
186
|
+
| Option | Type | Description |
|
|
187
|
+
|--------|------|-------------|
|
|
188
|
+
| `wallet` | `SolanaWallet` | Single Solana wallet (legacy) |
|
|
189
|
+
| `wallets` | `{ solana?, evm? }` | Multi-chain wallets |
|
|
190
|
+
| `preferredNetwork` | `string` | Prefer this network when multiple options available |
|
|
191
|
+
| `rpcUrls` | `Record<string, string>` | RPC endpoints per network (CAIP-2 format) |
|
|
192
|
+
| `maxAmountAtomic` | `string` | Maximum payment cap |
|
|
193
|
+
| `verbose` | `boolean` | Enable debug logging |
|
|
194
|
+
|
|
195
|
+
### `useX402Payment(options)`
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
|
|
199
|
+
| Property | Type | Description |
|
|
200
|
+
|----------|------|-------------|
|
|
201
|
+
| `fetch` | `function` | Payment-aware fetch |
|
|
202
|
+
| `isLoading` | `boolean` | Payment in progress |
|
|
203
|
+
| `status` | `string` | `'idle'` \| `'pending'` \| `'success'` \| `'error'` |
|
|
204
|
+
| `error` | `X402Error?` | Error details if failed |
|
|
205
|
+
| `transactionId` | `string?` | Transaction signature |
|
|
206
|
+
| `transactionUrl` | `string?` | Block explorer link |
|
|
207
|
+
| `balances` | `Balance[]` | Token balances per chain |
|
|
208
|
+
| `refreshBalances` | `function` | Manual refresh |
|
|
209
|
+
| `reset` | `function` | Clear state |
|
|
233
210
|
|
|
234
211
|
---
|
|
235
212
|
|
|
236
|
-
## Development
|
|
213
|
+
## ๐ง Development
|
|
237
214
|
|
|
238
215
|
```bash
|
|
239
216
|
npm run build # Build ESM + CJS
|
|
240
217
|
npm run dev # Watch mode
|
|
241
|
-
npm run typecheck # TypeScript
|
|
218
|
+
npm run typecheck # TypeScript
|
|
242
219
|
npm test # Run tests
|
|
243
220
|
```
|
|
244
221
|
|
|
245
222
|
---
|
|
246
223
|
|
|
247
|
-
##
|
|
224
|
+
## ๐ License
|
|
248
225
|
|
|
249
|
-
|
|
250
|
-
- [x402 Protocol Spec](https://docs.cdp.coinbase.com/x402)
|
|
251
|
-
- [Seller Onboarding](https://dexter.cash/onboard)
|
|
226
|
+
MIT โ see [LICENSE](./LICENSE)
|
|
252
227
|
|
|
253
228
|
---
|
|
254
229
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
230
|
+
<p align="center">
|
|
231
|
+
<a href="https://x402.dexter.cash">Dexter Facilitator</a> ยท
|
|
232
|
+
<a href="https://dexter.cash/sdk">Live Demo</a> ยท
|
|
233
|
+
<a href="https://dexter.cash/onboard">Become a Seller</a>
|
|
234
|
+
</p>
|