@agentokratia/x402-escrow 2.0.1 → 2.1.1
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 +214 -94
- package/dist/client/index.cjs +424 -351
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +129 -9
- package/dist/client/index.d.ts +129 -9
- package/dist/client/index.js +405 -345
- package/dist/client/index.js.map +1 -1
- package/dist/escrow-3qiwbT6c.d.cts +103 -0
- package/dist/escrow-dXa2Rtdo.d.ts +103 -0
- package/dist/index.cjs +599 -367
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +585 -364
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +337 -18
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +129 -38
- package/dist/server/index.d.ts +129 -38
- package/dist/server/index.js +321 -16
- package/dist/server/index.js.map +1 -1
- package/dist/types-B1CHqiXv.d.cts +106 -0
- package/dist/types-B1CHqiXv.d.ts +106 -0
- package/package.json +5 -1
- package/dist/session-wrapper-CcQU6BOI.d.cts +0 -447
- package/dist/session-wrapper-CcQU6BOI.d.ts +0 -447
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @agentokratia/x402-escrow
|
|
2
2
|
|
|
3
|
-
Escrow payment scheme for the x402 protocol.
|
|
3
|
+
Escrow payment scheme for the x402 protocol. Supports direct USDC payments and cross-token swaps.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
7
|
+
- **Direct USDC payments** - Gasless via ERC-3009 ReceiveWithAuthorization
|
|
8
|
+
- **Multi-token support** - Pay with WETH, DAI, USDT → receiver gets USDC
|
|
9
|
+
- **Automatic swap quotes** - Server fetches DEX quotes, client just signs
|
|
10
|
+
- **Gzip compression** - Aggregator calldata compressed for smaller payloads
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -19,140 +19,260 @@ npm install @agentokratia/x402-escrow
|
|
|
19
19
|
|
|
20
20
|
For apps and agents paying for APIs.
|
|
21
21
|
|
|
22
|
-
###
|
|
22
|
+
### Basic Setup
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
25
|
+
import { EscrowScheme } from '@agentokratia/x402-escrow/client';
|
|
26
|
+
import { x402Client } from '@x402/core/client';
|
|
27
|
+
import { ExactEvmScheme } from '@x402/evm';
|
|
28
|
+
import type { WalletClient } from 'viem';
|
|
29
|
+
|
|
30
|
+
// Convert wagmi WalletClient to x402 signer
|
|
31
|
+
function walletClientToSigner(walletClient: WalletClient) {
|
|
32
|
+
return {
|
|
33
|
+
address: walletClient.account!.address,
|
|
34
|
+
signTypedData: async (message) =>
|
|
35
|
+
walletClient.signTypedData({
|
|
36
|
+
account: walletClient.account!,
|
|
37
|
+
domain: message.domain,
|
|
38
|
+
types: message.types,
|
|
39
|
+
primaryType: message.primaryType,
|
|
40
|
+
message: message.message,
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Create x402 client
|
|
46
|
+
const client = new x402Client();
|
|
47
|
+
|
|
48
|
+
// Register exact scheme for direct USDC payments
|
|
49
|
+
const exactScheme = new ExactEvmScheme(walletClientToSigner(walletClient));
|
|
50
|
+
client.register('eip155:8453', exactScheme);
|
|
51
|
+
|
|
52
|
+
// Register escrow scheme for swap payments
|
|
53
|
+
const escrowScheme = new EscrowScheme(walletClient);
|
|
54
|
+
client.register('eip155:8453', escrowScheme);
|
|
46
55
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
56
|
+
// Create payment payload from 402 response
|
|
57
|
+
const paymentPayload = await client.createPaymentPayload(paymentRequired);
|
|
50
58
|
```
|
|
51
59
|
|
|
52
|
-
###
|
|
60
|
+
### With Policies (Token Selection)
|
|
53
61
|
|
|
54
62
|
```typescript
|
|
55
63
|
import { x402Client } from '@x402/core/client';
|
|
56
|
-
import {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
import { EscrowScheme } from '@agentokratia/x402-escrow/client';
|
|
65
|
+
|
|
66
|
+
// Selector that prefers exact scheme over escrow
|
|
67
|
+
const preferExactSelector = (version, requirements) => {
|
|
68
|
+
const exact = requirements.find((r) => r.scheme === 'exact');
|
|
69
|
+
return exact || requirements[0];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Policy that filters by input token
|
|
73
|
+
function createInputTokenPolicy(inputToken: string) {
|
|
74
|
+
return (version, requirements) => {
|
|
75
|
+
return requirements.filter((req) => {
|
|
76
|
+
if (req.scheme === 'exact') {
|
|
77
|
+
return req.asset?.toLowerCase() === inputToken.toLowerCase();
|
|
78
|
+
}
|
|
79
|
+
// For escrow, check swapData.inputToken
|
|
80
|
+
const swapData = req.extra?.swapData;
|
|
81
|
+
if (swapData?.inputToken) {
|
|
82
|
+
return swapData.inputToken.toLowerCase() === inputToken.toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
return req.asset?.toLowerCase() === inputToken.toLowerCase();
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Create client with selector
|
|
90
|
+
const client = new x402Client(preferExactSelector);
|
|
91
|
+
|
|
92
|
+
// Register policy to filter by selected token
|
|
93
|
+
client.registerPolicy(createInputTokenPolicy('0x4200000000000000000000000000000000000006')); // WETH
|
|
94
|
+
|
|
95
|
+
// Register schemes
|
|
96
|
+
client.register('eip155:8453', new ExactEvmScheme(signer));
|
|
97
|
+
client.register('eip155:8453', new EscrowScheme(walletClient));
|
|
63
98
|
```
|
|
64
99
|
|
|
65
100
|
## Server Usage
|
|
66
101
|
|
|
67
102
|
For APIs accepting payments. Config is auto-discovered from facilitator.
|
|
68
103
|
|
|
69
|
-
###
|
|
104
|
+
### Basic Setup
|
|
70
105
|
|
|
71
106
|
```typescript
|
|
72
107
|
import { x402ResourceServer, HTTPFacilitatorClient } from '@x402/core/server';
|
|
73
|
-
import { paymentMiddleware } from '@x402/express';
|
|
74
108
|
import { EscrowScheme } from '@agentokratia/x402-escrow/server';
|
|
109
|
+
import { ExactEvmScheme } from '@x402/evm/exact/server';
|
|
75
110
|
|
|
111
|
+
// 1. Create facilitator client
|
|
76
112
|
const facilitator = new HTTPFacilitatorClient({
|
|
77
113
|
url: 'https://facilitator.agentokratia.com',
|
|
78
114
|
createAuthHeaders: async () => ({
|
|
79
115
|
verify: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
|
|
80
116
|
settle: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
|
|
81
|
-
supported: {},
|
|
117
|
+
supported: { Authorization: `Bearer ${process.env.X402_API_KEY}` },
|
|
82
118
|
}),
|
|
83
119
|
});
|
|
84
120
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
payTo: ownerAddress,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
server
|
|
100
|
-
)
|
|
101
|
-
);
|
|
121
|
+
// 2. Create escrow scheme (for swap payments)
|
|
122
|
+
const escrow = new EscrowScheme({
|
|
123
|
+
facilitator,
|
|
124
|
+
apiKey: process.env.X402_API_KEY,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// 3. Create x402 server with both schemes
|
|
128
|
+
const server = new x402ResourceServer(facilitator);
|
|
129
|
+
server.register('eip155:8453', new ExactEvmScheme()); // Direct USDC
|
|
130
|
+
server.register('eip155:8453', escrow); // Swaps
|
|
102
131
|
```
|
|
103
132
|
|
|
104
|
-
###
|
|
133
|
+
### Building Payment Requirements (402 Response)
|
|
105
134
|
|
|
106
135
|
```typescript
|
|
107
|
-
|
|
108
|
-
|
|
136
|
+
// Build accepts for both schemes in parallel
|
|
137
|
+
const [exactResult, escrowResult] = await Promise.allSettled([
|
|
138
|
+
// Exact scheme (USDC direct)
|
|
139
|
+
server.buildPaymentRequirements({
|
|
140
|
+
scheme: 'exact',
|
|
141
|
+
network: 'eip155:8453',
|
|
142
|
+
price: '$1.00',
|
|
143
|
+
payTo: recipientAddress,
|
|
144
|
+
maxTimeoutSeconds: 600,
|
|
145
|
+
}),
|
|
146
|
+
// Escrow scheme (swaps) - fetches DEX quotes
|
|
147
|
+
escrow.buildAcceptsResolved({
|
|
148
|
+
network: 'eip155:8453',
|
|
149
|
+
price: '$1.00',
|
|
150
|
+
payTo: recipientAddress,
|
|
151
|
+
}),
|
|
152
|
+
]);
|
|
153
|
+
|
|
154
|
+
// Combine into payment requirements array
|
|
155
|
+
const paymentRequirements = [];
|
|
156
|
+
|
|
157
|
+
if (exactResult.status === 'fulfilled') {
|
|
158
|
+
paymentRequirements.push(...exactResult.value);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (escrowResult.status === 'fulfilled') {
|
|
162
|
+
for (const accept of escrowResult.value) {
|
|
163
|
+
paymentRequirements.push({
|
|
164
|
+
scheme: accept.scheme,
|
|
165
|
+
network: accept.network,
|
|
166
|
+
asset: accept.price.asset,
|
|
167
|
+
amount: accept.price.amount,
|
|
168
|
+
payTo: accept.payTo,
|
|
169
|
+
maxTimeoutSeconds: accept.maxTimeoutSeconds || 600,
|
|
170
|
+
extra: accept.price.extra || {},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Return 402 with PAYMENT-REQUIRED header
|
|
176
|
+
const encoded = Buffer.from(JSON.stringify(paymentRequirements)).toString('base64');
|
|
177
|
+
response.headers.set('PAYMENT-REQUIRED', encoded);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Processing Payments (Verify & Settle)
|
|
109
181
|
|
|
110
|
-
|
|
182
|
+
```typescript
|
|
183
|
+
import { preprocessSwapPayload } from '@agentokratia/x402-escrow/server';
|
|
184
|
+
|
|
185
|
+
// Decode payment from PAYMENT-SIGNATURE header
|
|
186
|
+
const paymentPayload = JSON.parse(Buffer.from(paymentSignature, 'base64').toString());
|
|
187
|
+
|
|
188
|
+
// Decompress swap calldata before forwarding to facilitator
|
|
189
|
+
// (Server compresses in buildAccepts, client passes through compressed)
|
|
190
|
+
const processedPayload = preprocessSwapPayload({
|
|
191
|
+
x402Version: 2,
|
|
192
|
+
resource: { url: '/api/endpoint', mimeType: 'application/json' },
|
|
193
|
+
accepted: paymentPayload.accepted,
|
|
194
|
+
payload: paymentPayload.payload,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Verify and settle with facilitator
|
|
198
|
+
const verifyResult = await facilitator.verify(processedPayload, processedPayload.accepted);
|
|
199
|
+
if (!verifyResult.isValid) {
|
|
200
|
+
throw new Error(verifyResult.invalidReason);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const settleResult = await facilitator.settle(processedPayload, processedPayload.accepted);
|
|
204
|
+
if (!settleResult.success) {
|
|
205
|
+
throw new Error(settleResult.errorReason);
|
|
206
|
+
}
|
|
111
207
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
'/api/premium': {
|
|
115
|
-
accepts: { scheme: 'escrow', network: 'eip155:84532', payTo: ownerAddress, price: '$0.01' },
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
server
|
|
119
|
-
);
|
|
208
|
+
// Return success with transaction hash
|
|
209
|
+
return { success: true, transaction: settleResult.transaction };
|
|
120
210
|
```
|
|
121
211
|
|
|
122
212
|
## How It Works
|
|
123
213
|
|
|
124
214
|
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
215
|
+
Client Server Facilitator
|
|
216
|
+
│ │ │
|
|
217
|
+
│ GET /api/resource │ │
|
|
218
|
+
│──────────────────────────────>│ │
|
|
219
|
+
│ │ buildAccepts() │
|
|
220
|
+
│ │─────────────────────────────>│
|
|
221
|
+
│ │ (fetches quotes for swaps) │
|
|
222
|
+
│ │<─────────────────────────────│
|
|
223
|
+
│ 402 + PAYMENT-REQUIRED │ │
|
|
224
|
+
│<──────────────────────────────│ │
|
|
225
|
+
│ │ │
|
|
226
|
+
│ User selects token (WETH) │ │
|
|
227
|
+
│ Signs EIP-712 Permit2 │ │
|
|
228
|
+
│ │ │
|
|
229
|
+
│ GET + PAYMENT-SIGNATURE │ │
|
|
230
|
+
│──────────────────────────────>│ │
|
|
231
|
+
│ │ verify() + settle() │
|
|
232
|
+
│ │─────────────────────────────>│
|
|
233
|
+
│ │ (executes swap on-chain) │
|
|
234
|
+
│ │<─────────────────────────────│
|
|
235
|
+
│ 200 + transaction hash │ │
|
|
236
|
+
│<──────────────────────────────│ │
|
|
130
237
|
```
|
|
131
238
|
|
|
132
239
|
## Networks
|
|
133
240
|
|
|
134
|
-
| Network | Chain ID |
|
|
135
|
-
| ------------ | -------- |
|
|
136
|
-
| Base Mainnet | 8453 | `
|
|
137
|
-
| Base Sepolia | 84532 | `
|
|
241
|
+
| Network | Chain ID | Facilitator |
|
|
242
|
+
| ------------ | -------- | -------------------------------------- |
|
|
243
|
+
| Base Mainnet | 8453 | `https://facilitator.agentokratia.com` |
|
|
244
|
+
| Base Sepolia | 84532 | `https://facilitator.agentokratia.com` |
|
|
138
245
|
|
|
139
246
|
## API
|
|
140
247
|
|
|
141
|
-
### Client
|
|
142
|
-
|
|
143
|
-
| Export
|
|
144
|
-
|
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
|
155
|
-
|
|
|
248
|
+
### Client Exports
|
|
249
|
+
|
|
250
|
+
| Export | Description |
|
|
251
|
+
| ------------------------- | ------------------------------------------------- |
|
|
252
|
+
| `EscrowScheme` | Client scheme for x402Client (takes WalletClient) |
|
|
253
|
+
| `signERC3009` | Sign ERC-3009 authorization |
|
|
254
|
+
| `signPermit2TransferFrom` | Sign Permit2 transfer |
|
|
255
|
+
| `computePaymentNonce` | Derive deterministic nonce from payment params |
|
|
256
|
+
| `PERMIT2_ADDRESS` | Universal Permit2 contract address |
|
|
257
|
+
| `decompressCalldata` | Decompress gzipped aggregator calldata |
|
|
258
|
+
|
|
259
|
+
### Server Exports
|
|
260
|
+
|
|
261
|
+
| Export | Description |
|
|
262
|
+
| ----------------------- | ------------------------------------------------- |
|
|
263
|
+
| `EscrowScheme` | Server scheme for x402ResourceServer |
|
|
264
|
+
| `HTTPFacilitatorClient` | Re-export from @x402/core/server |
|
|
265
|
+
| `preprocessSwapPayload` | Decompress swap calldata before facilitator calls |
|
|
266
|
+
| `compressCalldata` | Compress aggregator calldata (gzip) |
|
|
267
|
+
|
|
268
|
+
## Supported Input Tokens (Base Mainnet)
|
|
269
|
+
|
|
270
|
+
| Token | Address |
|
|
271
|
+
| ----- | -------------------------------------------- |
|
|
272
|
+
| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
|
|
273
|
+
| WETH | `0x4200000000000000000000000000000000000006` |
|
|
274
|
+
| DAI | `0x50c5725949a6f0c72e6c4a641f24049a917db0cb` |
|
|
275
|
+
| USDT | `0xfde4c96c8593536e31f229ea8f37b2ada2699bb2` |
|
|
156
276
|
|
|
157
277
|
## License
|
|
158
278
|
|