@dexterai/x402 1.0.3 โ 1.1.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/README.md +185 -160
- package/dist/client/index.cjs +7 -1
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.js +7 -1
- package/dist/client/index.js.map +1 -1
- package/dist/react/index.cjs +7 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +7 -1
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +88 -2
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +105 -1
- package/dist/server/index.d.ts +105 -1
- package/dist/server/index.js +85 -1
- package/dist/server/index.js.map +1 -1
- 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>
|
|
14
20
|
|
|
15
21
|
---
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## โจ Why This SDK?
|
|
18
24
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
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
|
|
24
31
|
|
|
25
32
|
---
|
|
26
33
|
|
|
27
|
-
##
|
|
34
|
+
## ๐ฎ See It Working
|
|
35
|
+
|
|
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.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
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,189 @@ 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
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { toAtomicUnits, fromAtomicUnits } from '@dexterai/x402/utils';
|
|
167
133
|
|
|
168
|
-
|
|
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).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## ๐ธ Dynamic Pricing
|
|
183
|
+
|
|
184
|
+
For LLM/AI endpoints where cost scales with input size:
|
|
210
185
|
|
|
211
186
|
```typescript
|
|
212
|
-
import {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
187
|
+
import { createX402Server, createDynamicPricing } from '@dexterai/x402/server';
|
|
188
|
+
|
|
189
|
+
const server = createX402Server({ payTo: '...', network: '...' });
|
|
190
|
+
const pricing = createDynamicPricing({
|
|
191
|
+
unitSize: 1000, // chars per unit
|
|
192
|
+
ratePerUnit: 0.01, // $0.01 per unit
|
|
193
|
+
minUsd: 0.01, // floor
|
|
194
|
+
maxUsd: 10.00, // ceiling
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
app.post('/api/llm', async (req, res) => {
|
|
198
|
+
const { prompt } = req.body;
|
|
199
|
+
const paymentSig = req.headers['payment-signature'];
|
|
200
|
+
|
|
201
|
+
if (!paymentSig) {
|
|
202
|
+
const quote = pricing.calculate(prompt);
|
|
203
|
+
const requirements = await server.buildRequirements({
|
|
204
|
+
amountAtomic: quote.amountAtomic,
|
|
205
|
+
resourceUrl: req.originalUrl,
|
|
206
|
+
});
|
|
207
|
+
res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));
|
|
208
|
+
res.setHeader('X-Quote-Hash', quote.quoteHash);
|
|
209
|
+
return res.status(402).json({ usdAmount: quote.usdAmount });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Validate quote hasn't changed (prevents prompt manipulation)
|
|
213
|
+
const quoteHash = req.headers['x-quote-hash'];
|
|
214
|
+
if (!pricing.validateQuote(prompt, quoteHash)) {
|
|
215
|
+
return res.status(400).json({ error: 'Prompt changed, re-quote required' });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const result = await server.settlePayment(paymentSig);
|
|
219
|
+
if (!result.success) return res.status(402).json({ error: result.errorReason });
|
|
220
|
+
|
|
221
|
+
const response = await runLLM(prompt);
|
|
222
|
+
res.json(response);
|
|
223
|
+
});
|
|
232
224
|
```
|
|
233
225
|
|
|
226
|
+
The client SDK automatically forwards `X-Quote-Hash` on retry.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## ๐ API Reference
|
|
231
|
+
|
|
232
|
+
### `createX402Client(options)`
|
|
233
|
+
|
|
234
|
+
| Option | Type | Description |
|
|
235
|
+
|--------|------|-------------|
|
|
236
|
+
| `wallet` | `SolanaWallet` | Single Solana wallet (legacy) |
|
|
237
|
+
| `wallets` | `{ solana?, evm? }` | Multi-chain wallets |
|
|
238
|
+
| `preferredNetwork` | `string` | Prefer this network when multiple options available |
|
|
239
|
+
| `rpcUrls` | `Record<string, string>` | RPC endpoints per network (CAIP-2 format) |
|
|
240
|
+
| `maxAmountAtomic` | `string` | Maximum payment cap |
|
|
241
|
+
| `verbose` | `boolean` | Enable debug logging |
|
|
242
|
+
|
|
243
|
+
### `useX402Payment(options)`
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
|
|
247
|
+
| Property | Type | Description |
|
|
248
|
+
|----------|------|-------------|
|
|
249
|
+
| `fetch` | `function` | Payment-aware fetch |
|
|
250
|
+
| `isLoading` | `boolean` | Payment in progress |
|
|
251
|
+
| `status` | `string` | `'idle'` \| `'pending'` \| `'success'` \| `'error'` |
|
|
252
|
+
| `error` | `X402Error?` | Error details if failed |
|
|
253
|
+
| `transactionId` | `string?` | Transaction signature |
|
|
254
|
+
| `transactionUrl` | `string?` | Block explorer link |
|
|
255
|
+
| `balances` | `Balance[]` | Token balances per chain |
|
|
256
|
+
| `refreshBalances` | `function` | Manual refresh |
|
|
257
|
+
| `reset` | `function` | Clear state |
|
|
258
|
+
|
|
234
259
|
---
|
|
235
260
|
|
|
236
|
-
## Development
|
|
261
|
+
## ๐ง Development
|
|
237
262
|
|
|
238
263
|
```bash
|
|
239
264
|
npm run build # Build ESM + CJS
|
|
240
265
|
npm run dev # Watch mode
|
|
241
|
-
npm run typecheck # TypeScript
|
|
266
|
+
npm run typecheck # TypeScript
|
|
242
267
|
npm test # Run tests
|
|
243
268
|
```
|
|
244
269
|
|
|
245
270
|
---
|
|
246
271
|
|
|
247
|
-
##
|
|
272
|
+
## ๐ License
|
|
248
273
|
|
|
249
|
-
|
|
250
|
-
- [x402 Protocol Spec](https://docs.cdp.coinbase.com/x402)
|
|
251
|
-
- [Seller Onboarding](https://dexter.cash/onboard)
|
|
274
|
+
MIT โ see [LICENSE](./LICENSE)
|
|
252
275
|
|
|
253
276
|
---
|
|
254
277
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
278
|
+
<p align="center">
|
|
279
|
+
<a href="https://x402.dexter.cash">Dexter Facilitator</a> ยท
|
|
280
|
+
<a href="https://dexter.cash/sdk">Live Demo</a> ยท
|
|
281
|
+
<a href="https://dexter.cash/onboard">Become a Seller</a>
|
|
282
|
+
</p>
|
package/dist/client/index.cjs
CHANGED
|
@@ -515,6 +515,10 @@ function createX402Client(config) {
|
|
|
515
515
|
);
|
|
516
516
|
}
|
|
517
517
|
log("Payment requirements:", requirements);
|
|
518
|
+
const quoteHash = response.headers.get("X-Quote-Hash");
|
|
519
|
+
if (quoteHash) {
|
|
520
|
+
log("Quote hash received:", quoteHash);
|
|
521
|
+
}
|
|
518
522
|
const match = findPaymentOption(requirements.accepts);
|
|
519
523
|
if (!match) {
|
|
520
524
|
const availableNetworks = requirements.accepts.map((a) => a.network).join(", ");
|
|
@@ -576,7 +580,9 @@ function createX402Client(config) {
|
|
|
576
580
|
...init,
|
|
577
581
|
headers: {
|
|
578
582
|
...init?.headers || {},
|
|
579
|
-
"PAYMENT-SIGNATURE": paymentSignatureHeader
|
|
583
|
+
"PAYMENT-SIGNATURE": paymentSignatureHeader,
|
|
584
|
+
// Forward quote hash for dynamic pricing validation
|
|
585
|
+
...quoteHash ? { "X-Quote-Hash": quoteHash } : {}
|
|
580
586
|
}
|
|
581
587
|
});
|
|
582
588
|
log("Retry response status:", retryResponse.status);
|