@4mica/x402 0.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.
Files changed (43) hide show
  1. package/.eslintrc.cjs +29 -0
  2. package/.prettierignore +3 -0
  3. package/.prettierrc +6 -0
  4. package/CHANGELOG.md +8 -0
  5. package/LICENSE +21 -0
  6. package/README.md +389 -0
  7. package/demo/.env.example +8 -0
  8. package/demo/README.md +125 -0
  9. package/demo/package.json +26 -0
  10. package/demo/src/client.ts +54 -0
  11. package/demo/src/deposit.ts +39 -0
  12. package/demo/src/server.ts +74 -0
  13. package/demo/tsconfig.json +8 -0
  14. package/demo/yarn.lock +925 -0
  15. package/dist/client/index.d.ts +1 -0
  16. package/dist/client/index.js +1 -0
  17. package/dist/client/scheme.d.ts +11 -0
  18. package/dist/client/scheme.js +65 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +1 -0
  21. package/dist/server/express/adapter.d.ts +71 -0
  22. package/dist/server/express/adapter.js +90 -0
  23. package/dist/server/express/index.d.ts +122 -0
  24. package/dist/server/express/index.js +340 -0
  25. package/dist/server/facilitator.d.ts +35 -0
  26. package/dist/server/facilitator.js +52 -0
  27. package/dist/server/index.d.ts +6 -0
  28. package/dist/server/index.js +4 -0
  29. package/dist/server/scheme.d.ts +93 -0
  30. package/dist/server/scheme.js +179 -0
  31. package/eslint.config.mjs +22 -0
  32. package/package.json +79 -0
  33. package/src/client/index.ts +1 -0
  34. package/src/client/scheme.ts +95 -0
  35. package/src/index.ts +7 -0
  36. package/src/server/express/adapter.ts +100 -0
  37. package/src/server/express/index.ts +466 -0
  38. package/src/server/facilitator.ts +90 -0
  39. package/src/server/index.ts +10 -0
  40. package/src/server/scheme.ts +223 -0
  41. package/tsconfig.build.json +5 -0
  42. package/tsconfig.json +17 -0
  43. package/vitest.config.ts +12 -0
package/.eslintrc.cjs ADDED
@@ -0,0 +1,29 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ es2020: true,
5
+ node: true,
6
+ },
7
+ parser: "@typescript-eslint/parser",
8
+ parserOptions: {
9
+ sourceType: "module",
10
+ ecmaVersion: 2020,
11
+ project: "./tsconfig.json",
12
+ },
13
+ plugins: ["@typescript-eslint"],
14
+ extends: [
15
+ "eslint:recommended",
16
+ "plugin:@typescript-eslint/recommended",
17
+ "eslint-config-prettier",
18
+ ],
19
+ rules: {
20
+ "@typescript-eslint/no-explicit-any": "off",
21
+ "@typescript-eslint/explicit-module-boundary-types": "off",
22
+ "@typescript-eslint/no-unused-vars": [
23
+ "error",
24
+ { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
25
+ ],
26
+ "@typescript-eslint/no-var-requires": "off",
27
+ },
28
+ ignorePatterns: ["dist", "node_modules"],
29
+ };
@@ -0,0 +1,3 @@
1
+ dist
2
+ node_modules
3
+ coverage
package/.prettierrc ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "singleQuote": true,
3
+ "trailingComma": "es5",
4
+ "printWidth": 100,
5
+ "semi": false
6
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0
4
+ - Breaking: include `reqId` in `PaymentGuaranteeRequestClaims` and signing payloads (EIP-712/EIP-191).
5
+ - Breaking: X402 envelopes now emit `req_id` and `TabResponse` exposes `nextReqId` for claim building.
6
+ - Fix: `listRecipientTabs` query parameter uses `settlement_status` to match core API.
7
+ - Improve: RPC admin endpoints return typed `UserSuspensionStatus`/`AdminApiKey*` models and errors carry status metadata.
8
+ - Fix: contract gateway disambiguates overloaded withdrawal functions for ethers v6.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 4Mica
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,389 @@
1
+ # @4mica/x402
2
+
3
+ Express middleware and client integration for the x402 Payment Protocol with 4mica credit flow support. This package provides batteries-included middleware for adding 4mica payment requirements to your Express.js applications, with automatic facilitator and scheme registration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm install @4mica/x402
9
+ ```
10
+
11
+ ## Quick Start (Server)
12
+
13
+ ```typescript
14
+ import express from "express";
15
+ import { paymentMiddlewareFromConfig } from "@4mica/x402/server/express";
16
+
17
+ const app = express();
18
+ app.use(express.json());
19
+
20
+ // Apply the payment middleware - facilitator and scheme are automatically configured
21
+ app.use(
22
+ paymentMiddlewareFromConfig(
23
+ {
24
+ "GET /premium-content": {
25
+ accepts: {
26
+ scheme: "4mica-credit",
27
+ price: "$0.10",
28
+ network: "eip155:11155111", // Ethereum Sepolia
29
+ payTo: "0xYourAddress",
30
+ },
31
+ description: "Access to premium content",
32
+ },
33
+ },
34
+ // Payment tab config
35
+ {
36
+ advertisedEndpoint: "https://api.example.com/tabs/open",
37
+ }
38
+ )
39
+ );
40
+
41
+ // Implement your protected route
42
+ app.get("/premium-content", (req, res) => {
43
+ res.json({ message: "This is premium content behind a paywall" });
44
+ });
45
+
46
+ app.listen(3000, () => {
47
+ console.log("Server running on http://localhost:3000");
48
+ });
49
+ ```
50
+
51
+ ## Quick Start (Client)
52
+
53
+ ### Using with Fetch
54
+
55
+ Use with `@x402/fetch` for automatic payment handling:
56
+
57
+ ```typescript
58
+ import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
59
+ import { FourMicaEvmScheme } from "@4mica/x402/client";
60
+ import { privateKeyToAccount } from "viem/accounts";
61
+
62
+ // Create an EVM account
63
+ const account = privateKeyToAccount("0xYourPrivateKey");
64
+
65
+ // Create the 4mica scheme client
66
+ const scheme = await FourMicaEvmScheme.create(account);
67
+
68
+ // Wrap fetch with payment handling
69
+ const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
70
+ schemes: [
71
+ {
72
+ network: "eip155:11155111", // Ethereum Sepolia
73
+ client: scheme,
74
+ },
75
+ ],
76
+ });
77
+
78
+ // Make requests - payments are handled automatically
79
+ const response = await fetchWithPayment("https://api.example.com/premium-content");
80
+ const data = await response.json();
81
+ console.log(data);
82
+ ```
83
+
84
+ ### Using with Axios
85
+
86
+ Use with `@x402/axios` for Axios-based applications:
87
+
88
+ ```typescript
89
+ import axios from "axios";
90
+ import { wrapAxiosWithPaymentFromConfig } from "@x402/axios";
91
+ import { FourMicaEvmScheme } from "@4mica/x402/client";
92
+ import { privateKeyToAccount } from "viem/accounts";
93
+
94
+ // Create an EVM account
95
+ const account = privateKeyToAccount("0xYourPrivateKey");
96
+
97
+ // Create the 4mica scheme client
98
+ const scheme = await FourMicaEvmScheme.create(account);
99
+
100
+ // Wrap axios instance with payment handling
101
+ const api = wrapAxiosWithPaymentFromConfig(axios.create(), {
102
+ schemes: [
103
+ {
104
+ network: "eip155:11155111", // Ethereum Sepolia
105
+ client: scheme,
106
+ },
107
+ ],
108
+ });
109
+
110
+ // Make requests - payments are handled automatically
111
+ const response = await api.get("https://api.example.com/premium-content");
112
+ const data = response.data;
113
+ console.log(data);
114
+ ```
115
+
116
+ ## Server Configuration
117
+
118
+ ### `paymentMiddlewareFromConfig(routes, tabConfig, ...options)`
119
+
120
+ The recommended middleware factory for most use cases. Automatically configures the 4mica facilitator and registers the `FourMicaEvmScheme` for all supported networks.
121
+
122
+ #### Parameters
123
+
124
+ 1. **`routes`** (required): Route configurations for protected endpoints
125
+
126
+ ```typescript
127
+ {
128
+ "GET /path": {
129
+ accepts: {
130
+ scheme: "4mica-credit",
131
+ price: "$0.10",
132
+ network: "eip155:11155111", // or "eip155:80002" for Polygon Amoy
133
+ payTo: "0xRecipientAddress",
134
+ },
135
+ description: "What the user is paying for",
136
+ }
137
+ }
138
+ ```
139
+
140
+ 2. **`tabConfig`** (required): Payment tab configuration
141
+
142
+ ```typescript
143
+ {
144
+ // Full URL endpoint for opening payment tabs
145
+ // This is injected into paymentRequirements.extra and clients use it to open tabs
146
+ advertisedEndpoint: "https://api.example.com/tabs/open",
147
+
148
+ // Lifetime of payment tabs in seconds
149
+ ttlSeconds: 3600, // optional, defaults to facilitator's default
150
+ }
151
+ ```
152
+
153
+ 3. **`facilitatorClients`** (optional): Additional facilitator client(s) for other payment schemes
154
+ 4. **`schemes`** (optional): Additional scheme registrations for other networks/schemes
155
+ 5. **`paywallConfig`** (optional): Configuration for the built-in paywall UI
156
+ 6. **`paywall`** (optional): Custom paywall provider
157
+ 7. **`syncFacilitatorOnStart`** (optional): Whether to sync with facilitator on startup (defaults to true)
158
+
159
+ #### Supported Networks
160
+
161
+ - `eip155:11155111` - Ethereum Sepolia
162
+ - `eip155:80002` - Polygon Amoy
163
+
164
+ ### Advanced Server Usage
165
+
166
+ For advanced scenarios where you need additional payment schemes or custom configuration:
167
+
168
+ #### Using `paymentMiddleware` with Custom Server
169
+
170
+ ```typescript
171
+ import { paymentMiddleware } from "@4mica/x402/server/express";
172
+ import {
173
+ x402ResourceServer,
174
+ FourMicaFacilitatorClient,
175
+ } from "@4mica/x402/server";
176
+ import { ExactEvmScheme } from "@x402/evm/exact/server";
177
+ import { HTTPFacilitatorClient } from "@x402/core/server";
178
+
179
+ // Create 4mica facilitator
180
+ const fourMicaFacilitator = new FourMicaFacilitatorClient();
181
+
182
+ // Optionally add other facilitators/schemes for additional payment methods
183
+ const otherFacilitator = new HTTPFacilitatorClient({
184
+ url: "https://other-facilitator.example.com"
185
+ });
186
+
187
+ // Create resource server with facilitators and additional schemes
188
+ // The middleware will auto-register FourMicaEvmScheme
189
+ const resourceServer = new x402ResourceServer([
190
+ fourMicaFacilitator,
191
+ otherFacilitator,
192
+ ])
193
+ .register("eip155:8453", new ExactEvmScheme()); // Add Base mainnet with exact scheme
194
+
195
+ app.use(
196
+ paymentMiddleware(
197
+ routes,
198
+ resourceServer,
199
+ {
200
+ advertisedEndpoint: "https://api.example.com/tabs/open",
201
+ ttlSeconds: 3600,
202
+ },
203
+ paywallConfig
204
+ )
205
+ );
206
+ ```
207
+
208
+ #### Using `paymentMiddlewareFromHTTPServer` with HTTP Hooks
209
+
210
+ ```typescript
211
+ import { paymentMiddlewareFromHTTPServer } from "@4mica/x402/server/express";
212
+ import {
213
+ x402ResourceServer,
214
+ x402HTTPResourceServer,
215
+ FourMicaFacilitatorClient,
216
+ } from "@4mica/x402/server";
217
+
218
+ // Create 4mica facilitator
219
+ const fourMicaFacilitator = new FourMicaFacilitatorClient();
220
+
221
+ // The middleware will auto-register FourMicaEvmScheme
222
+ const resourceServer = new x402ResourceServer(fourMicaFacilitator);
223
+
224
+ const httpServer = new x402HTTPResourceServer(resourceServer, routes)
225
+ .onProtectedRequest((context) => {
226
+ console.log("Protected request:", context.path);
227
+ });
228
+
229
+ app.use(
230
+ paymentMiddlewareFromHTTPServer(
231
+ httpServer,
232
+ {
233
+ advertisedEndpoint: "https://api.example.com/tabs/open",
234
+ ttlSeconds: 3600,
235
+ },
236
+ paywallConfig
237
+ )
238
+ );
239
+ ```
240
+
241
+ ## Client Configuration
242
+
243
+ ### Multi-Network Client Setup
244
+
245
+ ```typescript
246
+ import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
247
+ import { FourMicaEvmScheme } from "@4mica/x402/client";
248
+
249
+ const sepoliaScheme = await FourMicaEvmScheme.create(sepoliaAccount);
250
+ const amoyScheme = await FourMicaEvmScheme.create(amoyAccount);
251
+
252
+ const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
253
+ schemes: [
254
+ {
255
+ network: "eip155:11155111", // Ethereum Sepolia
256
+ client: sepoliaScheme,
257
+ },
258
+ {
259
+ network: "eip155:80002", // Polygon Amoy
260
+ client: amoyScheme,
261
+ },
262
+ ],
263
+ });
264
+ ```
265
+
266
+ ### Using Builder Pattern
267
+
268
+ ```typescript
269
+ import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
270
+ import { FourMicaEvmScheme } from "@4mica/x402/client";
271
+
272
+ const scheme = await FourMicaEvmScheme.create(account);
273
+
274
+ const client = new x402Client()
275
+ .register("eip155:11155111", scheme);
276
+
277
+ const fetchWithPayment = wrapFetchWithPayment(fetch, client);
278
+ ```
279
+
280
+ ## Complete Example
281
+
282
+ ### Server
283
+
284
+ ```typescript
285
+ import express from "express";
286
+ import { paymentMiddlewareFromConfig } from "@4mica/x402/server/express";
287
+
288
+ const app = express();
289
+ app.use(express.json());
290
+
291
+ app.use(
292
+ paymentMiddlewareFromConfig(
293
+ {
294
+ "GET /api/data": {
295
+ accepts: {
296
+ scheme: "4mica-credit",
297
+ price: "$0.05",
298
+ network: "eip155:11155111",
299
+ payTo: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
300
+ },
301
+ description: "API data access",
302
+ },
303
+ "POST /api/compute": {
304
+ accepts: {
305
+ scheme: "4mica-credit",
306
+ price: "$0.20",
307
+ network: "eip155:11155111",
308
+ payTo: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
309
+ },
310
+ description: "Computation service",
311
+ },
312
+ },
313
+ {
314
+ advertisedEndpoint: "https://api.example.com/tabs/open",
315
+ ttlSeconds: 7200, // 2 hours
316
+ }
317
+ )
318
+ );
319
+
320
+ app.get("/api/data", (req, res) => {
321
+ res.json({ data: "Premium data content" });
322
+ });
323
+
324
+ app.post("/api/compute", (req, res) => {
325
+ res.json({ result: "Computation complete" });
326
+ });
327
+
328
+ app.listen(3000);
329
+ ```
330
+
331
+ ### Client
332
+
333
+ ```typescript
334
+ import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
335
+ import { FourMicaEvmScheme } from "@4mica/x402/client";
336
+ import { privateKeyToAccount } from "viem/accounts";
337
+
338
+ async function main() {
339
+ const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
340
+ const scheme = await FourMicaEvmScheme.create(account);
341
+
342
+ const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
343
+ schemes: [
344
+ {
345
+ network: "eip155:11155111",
346
+ client: scheme,
347
+ },
348
+ ],
349
+ });
350
+
351
+ // Fetch premium data - payment handled automatically
352
+ const dataResponse = await fetchWithPayment("https://api.example.com/api/data");
353
+ const data = await dataResponse.json();
354
+ console.log("Data:", data);
355
+
356
+ // Make computation request - payment handled automatically
357
+ const computeResponse = await fetchWithPayment("https://api.example.com/api/compute", {
358
+ method: "POST",
359
+ headers: { "Content-Type": "application/json" },
360
+ body: JSON.stringify({ input: "some data" }),
361
+ });
362
+ const result = await computeResponse.json();
363
+ console.log("Result:", result);
364
+ }
365
+
366
+ main();
367
+ ```
368
+
369
+ ## How It Works
370
+
371
+ 1. **Server Setup**: The middleware automatically registers the `FourMicaEvmScheme` and injects the 4mica facilitator client, so you don't need to configure them manually.
372
+
373
+ 2. **Tab Management**: When a client requests a protected resource, the middleware handles the tab lifecycle:
374
+ - The `advertisedEndpoint` is injected into `paymentRequirements.extra.tabEndpoint`
375
+ - Clients use this endpoint to open payment tabs
376
+ - The middleware automatically processes tab opening requests when they arrive at the advertised endpoint
377
+
378
+ 3. **Payment Flow**:
379
+ - Client makes initial request to protected resource
380
+ - Server responds with `402 Payment Required` including payment requirements
381
+ - Client requests a tab from the advertised endpoint
382
+ - Client signs a payment guarantee using the 4mica SDK
383
+ - Client retries the request with the payment payload
384
+ - Server verifies and settles the payment via the 4mica facilitator
385
+ - Server returns the protected resource
386
+
387
+ ## License
388
+
389
+ MIT
@@ -0,0 +1,8 @@
1
+ # Server Configuration
2
+ PORT=3000
3
+ PAY_TO_ADDRESS=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
4
+ ADVERTISED_ENDPOINT=http://localhost:3000/payment/tab
5
+
6
+ # Client Configuration
7
+ PRIVATE_KEY=0xYourPrivateKeyHere
8
+ API_URL=http://localhost:3000
package/demo/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # @4mica/x402 Demo
2
+
3
+ This demo shows how to use `@4mica/x402` to protect an API endpoint with 4mica payments.
4
+
5
+ ## Setup
6
+
7
+ 1. **Install dependencies**:
8
+
9
+ First, build the parent package:
10
+
11
+ ```bash
12
+ cd ..
13
+ yarn install
14
+ yarn build
15
+ ```
16
+
17
+ Then install demo dependencies:
18
+
19
+ ```bash
20
+ cd demo
21
+ yarn install
22
+ ```
23
+
24
+ 2. **Configure environment variables**:
25
+
26
+ Copy the example file and edit it:
27
+
28
+ ```bash
29
+ cp .env.example .env
30
+ # Edit .env with your private key and settings
31
+ ```
32
+
33
+ Required variables:
34
+ - `PRIVATE_KEY`: Your Ethereum private key (with 0x prefix) for Sepolia testnet
35
+ - `PAY_TO_ADDRESS`: Address that will receive payments (optional, defaults to a test address)
36
+
37
+ ## Running the Demo
38
+
39
+ ### Terminal 1: Start the server
40
+
41
+ From the demo directory:
42
+
43
+ ```bash
44
+ yarn server
45
+ ```
46
+
47
+ Or from the package root:
48
+
49
+ ```bash
50
+ yarn demo:server
51
+ ```
52
+
53
+ You should see:
54
+ ```
55
+ x402 Demo Server running on http://localhost:3000
56
+ Protected endpoint: http://localhost:3000/api/premium-data
57
+ Payment required: $0.05 (4mica credit on Sepolia)
58
+ ```
59
+
60
+ ### Terminal 2: Run the client
61
+
62
+ The client will automatically load environment variables from `.env`:
63
+
64
+ From the demo directory:
65
+
66
+ ```bash
67
+ yarn client
68
+ ```
69
+
70
+ Or from the package root:
71
+
72
+ ```bash
73
+ yarn demo:client
74
+ ```
75
+
76
+ You can also set PRIVATE_KEY inline:
77
+
78
+ ```bash
79
+ PRIVATE_KEY=0xYourPrivateKey yarn client
80
+ ```
81
+
82
+ ## What Happens
83
+
84
+ 1. **Server** starts with one protected endpoint: `GET /api/premium-data`
85
+ - Requires a payment of $0.05 in 4mica credits on Sepolia
86
+ - Uses x402 payment protocol
87
+
88
+ 2. **Client** makes a request to the protected endpoint:
89
+ - First receives `402 Payment Required` response
90
+ - Automatically opens a payment tab via the 4mica facilitator
91
+ - Signs and submits the payment
92
+ - Retries the request with payment proof
93
+ - Receives the protected data
94
+
95
+ 3. **Payment Flow**:
96
+ ```
97
+ Client → GET /api/premium-data
98
+ ← 402 Payment Required (with payment requirements)
99
+
100
+ Client → POST /payment/tab (open payment tab)
101
+ ← 200 OK (tab details)
102
+
103
+ Client → Signs payment guarantee (via 4mica SDK)
104
+
105
+ Client → GET /api/premium-data (with payment proof)
106
+ ← 200 OK (protected data)
107
+ ```
108
+
109
+ ## Testing Without Running the Client
110
+
111
+ You can also test the server manually using curl:
112
+
113
+ ```bash
114
+ # Check server status
115
+ curl http://localhost:3000/
116
+
117
+ # Try to access protected endpoint (will return 402)
118
+ curl -v http://localhost:3000/api/premium-data
119
+ ```
120
+
121
+ ## Notes
122
+
123
+ - Make sure your account has sufficient balance on Sepolia testnet
124
+ - The demo uses the default 4mica facilitator configuration
125
+ - Tab TTL is set to 1 hour (3600 seconds)
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@4mica/x402-demo",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "server": "tsx src/server.ts",
8
+ "client": "tsx src/client.ts",
9
+ "deposit": "tsx src/deposit.ts",
10
+ "dev": "tsx watch src/server.ts"
11
+ },
12
+ "dependencies": {
13
+ "@4mica/sdk": "file:../../../../../ts-sdk-4mica",
14
+ "@4mica/x402": "file:..",
15
+ "@x402/fetch": "^2.2.0",
16
+ "dotenv": "^16.4.7",
17
+ "express": "^5.2.1",
18
+ "viem": "^2.21.54"
19
+ },
20
+ "devDependencies": {
21
+ "@types/express": "^5.0.6",
22
+ "@types/node": "^25.0.7",
23
+ "tsx": "^4.19.2",
24
+ "typescript": "^5.3.3"
25
+ }
26
+ }
@@ -0,0 +1,54 @@
1
+ import 'dotenv/config'
2
+ import { wrapFetchWithPaymentFromConfig } from '@x402/fetch'
3
+ import { FourMicaEvmScheme } from '@4mica/x402/client'
4
+ import { privateKeyToAccount } from 'viem/accounts'
5
+
6
+ async function main() {
7
+ const privateKey = process.env.PRIVATE_KEY
8
+ if (!privateKey || !privateKey.startsWith('0x')) {
9
+ console.error('Error: PRIVATE_KEY environment variable must be set and start with 0x')
10
+ console.error('Example: PRIVATE_KEY=0x1234... yarn client')
11
+ process.exit(1)
12
+ }
13
+
14
+ const apiUrl = process.env.API_URL || 'http://localhost:3000'
15
+ const endpoint = `${apiUrl}/api/premium-data`
16
+
17
+ console.log('Initializing x402 client...')
18
+ console.log(`Target endpoint: ${endpoint}`)
19
+
20
+ const account = privateKeyToAccount(privateKey as `0x${string}`)
21
+ console.log(`Using account: ${account.address}`)
22
+
23
+ const scheme = await FourMicaEvmScheme.create(account)
24
+
25
+ const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
26
+ schemes: [
27
+ {
28
+ network: 'eip155:11155111', // Ethereum Sepolia
29
+ client: scheme,
30
+ },
31
+ ],
32
+ })
33
+
34
+ console.log('\nMaking request to protected endpoint...')
35
+
36
+ try {
37
+ const response = await fetchWithPayment(endpoint)
38
+ const data = await response.json()
39
+
40
+ console.log('Request successful!')
41
+ console.log('Response:', JSON.stringify(data, null, 2))
42
+ } catch (error) {
43
+ console.error('Request failed:', error)
44
+ if (error instanceof Error) {
45
+ console.error('Message:', error.message)
46
+ }
47
+ process.exit(1)
48
+ }
49
+ }
50
+
51
+ main().catch((error) => {
52
+ console.error('Unhandled error:', error)
53
+ process.exit(1)
54
+ })