@4mica/sdk 0.5.1 → 0.5.3

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 CHANGED
@@ -1,444 +1,311 @@
1
- # x402-4mica Facilitator
1
+ [![npm](https://img.shields.io/npm/v/@4mica/sdk.svg)](https://www.npmjs.com/package/@4mica/sdk)
2
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
2
3
 
3
- <p align="center">
4
- <a href="https://github.com/4mica-network/x402-4mica/actions/workflows/ci.yml">
5
- <img src="https://github.com/4mica-network/x402-4mica/actions/workflows/ci.yml/badge.svg" alt="CI">
6
- </a>
7
- <a href="LICENSE">
8
- <img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT">
9
- </a>
10
- </p>
4
+ # 4Mica TypeScript SDK
11
5
 
12
- A facilitator for the x402 protocol that runs the 4mica credit flow. Resource servers call it to
13
- open tabs, validate `X-PAYMENT` headers against their `paymentRequirements`, and settle by returning
14
- the BLS certificate to the recipient.
6
+ The official TypeScript SDK for interacting with the 4Mica payment network.
15
7
 
8
+ ## Overview
16
9
 
17
- **Contents**
18
- - [How to use the system](#how-to-use-the-system)
19
- - [Integrate from x402](#integrate-from-x402)
20
- - [Run your own facilitator](#run-your-own-facilitator)
10
+ 4Mica is a payment network that enables cryptographically-enforced lines of credit for autonomous
11
+ payments. This SDK provides:
21
12
 
22
- ## How to use the system
13
+ - **User Client**: deposit collateral, sign payments, and manage withdrawals in ETH or ERC20 tokens
14
+ - **Recipient Client**: create payment tabs, verify payment guarantees, and claim from user collateral
15
+ - **X402 Flow Helper**: generate X-PAYMENT headers for 402-protected HTTP resources via an X402-compatible service
16
+ - **Admin RPCs**: manage user suspension and admin API keys (when authorized)
23
17
 
24
- ### Quick integration (resource servers)
18
+ ## Installation
25
19
 
26
- - Configure the 4mica facilitator (for example `https://x402.4mica.xyz/`) and choose a POST tab endpoint on your API (e.g. `POST https://api.example.com/x402/tab`). Your `402 Payment Required` responses should advertise `scheme = "4mica-credit"`, a supported `network`, and set `payTo` / `asset` / `maxAmountRequired`, embedding your tab endpoint in `paymentRequirements.extra.tabEndpoint`.
27
- - Implement the tab endpoint to accept `{ userAddress, paymentRequirements }`. For each call, open or reuse a tab by calling the facilitator’s standard `POST /tabs` with `{ userAddress, recipientAddress = payTo, erc20Token = asset, ttlSeconds? }`, then return the tab response (at least `tabId` and `userAddress`) to the client. Cache tabs per (user, recipient, asset) if you want to avoid unnecessary `/tabs` calls – the facilitator will return the existing tab for that combination either way.
28
- - Clients combine this tab with your original `paymentRequirements` to build and sign a guarantee, producing a base64-encoded `X-PAYMENT` header that they send on the retried request for the protected resource. You never construct this header yourself; you only need to validate and consume it.
29
- - When a request arrives with `X-PAYMENT`, base64-decode the header into the standard x402 payment envelope and send its payment payload together with the original `paymentRequirements` to the facilitator’s `/verify` and `/settle` endpoints. Use `/verify` as an optional preflight check before doing work, and `/settle` once you are ready to accept credit and obtain the BLS certificate for downstream remuneration.
20
+ ```bash
21
+ npm install @4mica/sdk
22
+ # or
23
+ yarn add @4mica/sdk
24
+ ```
30
25
 
31
- ### Quick integration (clients)
26
+ Node.js 18+ is required.
32
27
 
33
- - Python SDK:
28
+ ## Initialization and Configuration
34
29
 
35
- ```bash
36
- pip install sdk-4mica
37
- ```
30
+ The SDK requires a signing key and can use sensible defaults for the rest:
38
31
 
39
- ```python
40
- import asyncio
41
- from fourmica_sdk import Client, ConfigBuilder, PaymentRequirements, X402Flow
32
+ - `walletPrivateKey` (**required** unless `signer` is provided): private key used for signing
33
+ - `rpcUrl` (optional): URL of the 4Mica core RPC server. Defaults to `https://api.4mica.xyz/`.
34
+ - `ethereumHttpRpcUrl` (optional): Ethereum JSON-RPC endpoint; fetched from core if omitted
35
+ - `contractAddress` (optional): Core4Mica contract address; fetched from core if omitted
36
+ - `adminApiKey` (optional): API key for admin RPCs
37
+ - `bearerToken` (optional): static bearer token for auth
38
+ - `authUrl` and `authRefreshMarginSecs` (optional): SIWE auth config. Only used when auth is
39
+ enabled via `enableAuth()` or by setting either value (defaults to `rpcUrl` and 60 seconds).
42
40
 
43
- payer_key = "0x..." # wallet private key
44
- user_address = "0x..." # address to embed in the claims
41
+ > Note: `ethereumHttpRpcUrl` and `contractAddress` are fetched from the core service and validated
42
+ > against the connected Ethereum provider automatically. Only override these if you need to use
43
+ > different values than the server defaults.
45
44
 
46
- async def main():
47
- cfg = ConfigBuilder().wallet_private_key(payer_key).rpc_url("https://api.4mica.xyz/").build()
48
- client = await Client.new(cfg)
49
- flow = X402Flow.from_client(client)
45
+ ### 1) Using ConfigBuilder
50
46
 
51
- # Fetch the recipient's paymentRequirements (must include extra.tabEndpoint)
52
- req_raw = fetch_requirements_somehow()[0]
53
- requirements = PaymentRequirements.from_raw(req_raw)
47
+ ```ts
48
+ import { Client, ConfigBuilder } from "@4mica/sdk";
54
49
 
55
- payment = await flow.sign_payment(requirements, user_address)
56
- headers = {"X-PAYMENT": payment.header} # base64 string to send with the retry
57
- await client.aclose()
50
+ async function main() {
51
+ const cfg = new ConfigBuilder()
52
+ .rpcUrl("https://api.4mica.xyz/")
53
+ .walletPrivateKey("0x...")
54
+ .build();
58
55
 
59
- asyncio.run(main())
60
- ```
56
+ const client = await Client.new(cfg);
57
+ try {
58
+ // use client.user, client.recipient, client.rpc
59
+ } finally {
60
+ await client.aclose();
61
+ }
62
+ }
63
+ ```
61
64
 
62
- - TypeScript SDK:
65
+ ### 2) Using Environment Variables
63
66
 
64
- ```bash
65
- npm install sdk-4mica
66
- ```
67
+ Set environment variables (example `.env`):
67
68
 
68
- ```ts
69
- import { Client, ConfigBuilder, PaymentRequirements, X402Flow } from "sdk-4mica";
69
+ ```bash
70
+ 4MICA_WALLET_PRIVATE_KEY="0x..."
71
+ 4MICA_RPC_URL="https://api.4mica.xyz/"
72
+ 4MICA_ETHEREUM_HTTP_RPC_URL="http://localhost:8545"
73
+ 4MICA_CONTRACT_ADDRESS="0x..."
74
+ 4MICA_ADMIN_API_KEY="ak_..."
75
+ 4MICA_BEARER_TOKEN="Bearer <access_token>"
76
+ 4MICA_AUTH_URL="https://api.4mica.xyz/"
77
+ 4MICA_AUTH_REFRESH_MARGIN_SECS="60"
78
+ ```
70
79
 
71
- async function run() {
72
- const cfg = new ConfigBuilder().walletPrivateKey("0x...").build();
73
- const client = await Client.new(cfg);
74
- const flow = X402Flow.fromClient(client);
80
+ If you want to set them inline for a single command, use `env` since most shells do not allow
81
+ variable names that start with a digit:
75
82
 
76
- const reqRaw = fetchRequirementsSomehow()[0]; // includes extra.tabEndpoint
77
- const requirements = PaymentRequirements.fromRaw(reqRaw);
83
+ ```bash
84
+ env 4MICA_WALLET_PRIVATE_KEY="0x..." 4MICA_RPC_URL="https://api.4mica.xyz/" node app.js
85
+ ```
78
86
 
79
- const payment = await flow.signPayment(requirements, "0xUser");
80
- const headers = { "X-PAYMENT": payment.header };
81
- await client.aclose();
82
- }
87
+ Then in code:
83
88
 
84
- run();
85
- ```
89
+ ```ts
90
+ import { Client, ConfigBuilder } from "@4mica/sdk";
86
91
 
87
- **SIWE auth (optional)**
92
+ const cfg = new ConfigBuilder().fromEnv().build();
93
+ const client = await Client.new(cfg);
94
+ ```
88
95
 
89
- ```ts
90
- import { Client, ConfigBuilder } from "sdk-4mica";
96
+ ### 3) Using a Custom Signer
91
97
 
92
- const cfg = new ConfigBuilder()
93
- .walletPrivateKey("0x...")
94
- .rpcUrl("https://api.4mica.xyz/")
95
- .enableAuth()
96
- .build();
98
+ If you want to integrate with a custom signer (hardware wallet, remote signer, etc.), provide a
99
+ `viem` `Account` implementation. It must expose `address`, `signTypedData`, and `signMessage` for
100
+ SIWE auth.
97
101
 
98
- const client = await Client.new(cfg);
99
- await client.login(); // optional: first RPC call also triggers auth
100
- ```
102
+ ```ts
103
+ import { Client, ConfigBuilder } from "@4mica/sdk";
104
+ import { privateKeyToAccount } from "viem/accounts";
101
105
 
102
- Or pass a static bearer token:
106
+ const signer = privateKeyToAccount(process.env.PAYER_KEY as `0x${string}`);
107
+ const cfg = new ConfigBuilder().signer(signer).build();
108
+ const client = await Client.new(cfg);
109
+ ```
103
110
 
104
- ```ts
105
- const cfg = new ConfigBuilder()
106
- .walletPrivateKey("0x...")
107
- .bearerToken("Bearer <access_token>")
108
- .build();
109
- ```
111
+ ### SIWE Auth (Optional)
110
112
 
111
- Env vars: `4MICA_BEARER_TOKEN`, `4MICA_AUTH_URL`, `4MICA_AUTH_REFRESH_MARGIN_SECS`.
113
+ Enable automatic SIWE auth refresh, or pass a static bearer token:
112
114
 
113
- - Rust SDK: `cargo add rust-sdk-4mica` and call
114
- `X402Flow::sign_payment(requirements, user_address)` to obtain the same `payment.header` for the
115
- retry request.
115
+ ```ts
116
+ import { Client, ConfigBuilder } from "@4mica/sdk";
116
117
 
117
- ### Demo example
118
+ const cfg = new ConfigBuilder()
119
+ .walletPrivateKey("0x...")
120
+ .rpcUrl("https://api.4mica.xyz/")
121
+ .enableAuth()
122
+ .build();
118
123
 
119
- You can pair the client with `examples/server/mock_paid_api.py`, a FastAPI server that simulates a
120
- paywalled endpoint. Start it with `python examples/server/mock_paid_api.py` (set `PORT` to override
121
- the default `9000`). The mock resource will call the facilitator’s `/verify` endpoint (defaulting to
122
- `https://x402.4mica.xyz/`; override with `FACILITATOR_URL`) whenever it receives an `X-PAYMENT`
123
- header.
124
+ const client = await Client.new(cfg);
125
+ await client.login(); // optional: first RPC call also triggers auth
126
+ ```
124
127
 
125
- The bundled Rust example shows how to sign a payment
126
- header with `rust-sdk-4mica`:
128
+ Or use a static token:
127
129
 
128
- ```bash
129
- # requires PAYER_KEY, USER_ADDRESS, RESOURCE_URL and ASSET_ADDRESS
130
- cargo run --example rust_client
130
+ ```ts
131
+ const cfg = new ConfigBuilder()
132
+ .walletPrivateKey("0x...")
133
+ .bearerToken("Bearer <access_token>")
134
+ .build();
131
135
  ```
132
136
 
133
- The example will read environment variables from `examples/.env` (or a root `.env`) if present. A
134
- Python counterpart lives in `examples/python_client/client.py` (install deps with `pip install -r
135
- examples/python_client/requirements.txt`). A TypeScript version lives in `examples/ts_client`
136
- (`npm install && npm start`).
137
-
138
- ### X-PAYMENT header schema
139
-
140
- `X-PAYMENT` must be a base64-encoded JSON envelope:
141
-
142
- ```json
143
- {
144
- "x402Version": 1,
145
- "scheme": "4mica-credit",
146
- "network": "polygon-amoy",
147
- "payload": {
148
- "claims": {
149
- "user_address": "<0x-prefixed checksum string>",
150
- "recipient_address": "<0x-prefixed checksum string>",
151
- "tab_id": "<decimal or 0x value>",
152
- "req_id": "<decimal or 0x value>",
153
- "amount": "<decimal or 0x value>",
154
- "asset_address": "<0x-prefixed checksum string>",
155
- "timestamp": 1716500000,
156
- "version": "v1"
157
- },
158
- "signature": "<0x-prefixed wallet signature>",
159
- "scheme": "eip712"
160
- }
161
- }
162
- ```
137
+ Env vars: `4MICA_BEARER_TOKEN`, `4MICA_AUTH_URL`, `4MICA_AUTH_REFRESH_MARGIN_SECS`.
163
138
 
164
- The facilitator enforces that:
165
-
166
- - `scheme` / `network` match both `/supported` and the resource server’s requirements.
167
- - `payTo` equals the `recipient_address` present inside the claim.
168
- - `asset` and `maxAmountRequired` must match the signed `amount` exactly (no partial spends).
169
- - If `X402_GUARANTEE_DOMAIN` is set (legacy `FOUR_MICA_GUARANTEE_DOMAIN` / `4MICA_GUARANTEE_DOMAIN`
170
- are also honored), the certificate domain returned by core matches it exactly.
171
-
172
- ### HTTP API
173
-
174
- - `GET /supported` – returns all `(scheme, network)` tuples the facilitator can service (4mica and,
175
- if configured, any additional `exact` flows).
176
- - `GET /health` – liveness probe that returns `{ "status": "ok" }`.
177
- - `POST /tabs`
178
- - Request: `{ "userAddress", "recipientAddress", "erc20Token"?, "ttlSeconds"? }`.
179
- Use `erc20Token = null` (or omit it) for ETH tabs; otherwise pass the token contract address.
180
- - Response: `{ "tabId", "userAddress", "recipientAddress", "assetAddress", "startTimestamp", "ttlSeconds", "nextReqId"? }`.
181
- `tabId` is always emitted as a canonical hex string. Recipients call this after a user shares
182
- their wallet; the facilitator reuses the existing tab for that pair whenever possible.
183
- - `POST /verify`
184
- - Request: `{ "x402Version": 1, "paymentHeader": "<base64 X-PAYMENT>", "paymentRequirements": { ... } }`.
185
- - Response: `{ "isValid": true|false, "invalidReason"?, "certificate": null }`.
186
- - `POST /settle`
187
- - Request: same shape as `/verify`.
188
- - Response: for 4mica, `{ "success": true, "networkId": "<network>", "certificate": { "claims", "signature" } }`.
189
- When delegating to the `exact` facilitator the structure mirrors upstream x402 responses and may
190
- include `txHash`.
191
- If `X402_DEBIT_URL` is set, debit requests are proxied to the configured x402-rs
192
- facilitator, allowing clients to follow the x402 debit flow unchanged.
193
-
194
- ### End-to-end credit flow
195
-
196
- The sequence below highlights each HTTP request, who sends it, and how data travels through
197
- x402-4mica and the 4mica core service.
198
-
199
- 1. **Client discovers the paywall**
200
- - Client → Recipient resource: request protected content.
201
- - Recipient → Client: `402 Payment Required` that advertises the supported `(scheme, network)`
202
- and instructs the client where to request a payment tab (for example, `POST /tab` with their
203
- wallet address). No per-user data is known yet.
204
- 2. **Client requests a tab**
205
- - Client → Recipient resource: `POST /tab` (or an equivalent endpoint) with their
206
- `{ userAddress, erc20Token?, ttlSeconds? }`.
207
- - Recipient → Facilitator: `POST /tabs` using the supplied body. The facilitator will reuse the
208
- existing tab for that `(user, recipient, asset)` combination or create a fresh one.
209
- - Facilitator → 4mica core: `POST core/tabs` whenever a new tab is required.
210
- - Facilitator → Recipient: `{ tabId, userAddress, recipientAddress, assetAddress, startTimestamp, ttlSeconds }`.
211
- Recipients cache this tab and reuse it until expiry, then hand `tabId`/`userAddress` back to
212
- the client inside `paymentRequirements`.
213
- 3. **Client signs a guarantee**
214
- - Client builds the JSON payload that matches the resource requirements, signs it with their
215
- private key (EIP‑712 by default; EIP‑191 is also accepted), and wraps the result in a base64
216
- `X-PAYMENT` header.
217
- 4. **Client retries the protected call**
218
- - Client → Recipient resource: same HTTP request plus `X-PAYMENT: <base64 envelope>`.
219
- 5. **Recipient verifies the header**
220
- - Recipient → Facilitator: `POST /verify` with
221
- `{ x402Version, paymentHeader, paymentRequirements }`.
222
- - Facilitator: decodes `paymentHeader`, ensures `scheme`/`network` match `/supported`, confirms
223
- the claims reference the advertised tab, user, asset, `payTo`, and that `amount` exactly equals
224
- `maxAmountRequired`.
225
- - Facilitator → Recipient: `{ isValid, invalidReason?, certificate: null }`. No request touches
226
- 4mica core here; this is purely structural validation so recipients can pre-flight calls.
227
- 6. **Recipient settles the tab**
228
- - Recipient → Facilitator: `POST /settle` with the same payload.
229
- - Facilitator: revalidates the header, then
230
- - sends `POST core/guarantees` with `{ claims, signature, scheme }` where `claims` contains the
231
- tab id, user, recipient, asset, amount, and timestamp (plus a version field injected by the
232
- facilitator),
233
- - receives a BLS signature over those claims,
234
- - verifies the certificate by reusing the public parameters fetched at startup, rejecting the
235
- settlement if the signature or expected domain fail to match.
236
- - Facilitator → Recipient: `{ success, networkId, certificate, error: null, txHash: null }`.
237
- `certificate.claims` and `certificate.signature` are byte strings that recipients can persist or
238
- pass to downstream infrastructure as proof of credit issuance. If the request belonged to a
239
- delegated `exact` scheme the facilitator instead forwards the settlement to x402-rs and returns
240
- that response (which may contain a `txHash` instead of a certificate).
241
-
242
- ## Integrate from x402
243
-
244
- The facilitator can transparently replace the EIP-3009/x402 debit flow. The key is to swap the old
245
- `exact` scheme for the 4mica credit primitives described below.
246
-
247
- ### Changes resource servers must make
248
-
249
- 1. **Point at the credit facilitator** – set `X402_FACILITATOR_URL=https://x402.4mica.xyz`
250
- (or the TypeScript `CC_FACILITATOR_URL`). This host validates guarantee envelopes and returns BLS
251
- certificates instead of ERC-3009 receipts.
252
- 2. **Provision tabs before issuing requirements** – whenever a user shares their wallet, call
253
- `POST https://x402.4mica.xyz/tabs` with `{ userAddress, recipientAddress, erc20Token?, ttlSeconds? }`.
254
- Cache `{ tabId, assetAddress, startTimestamp, ttlSeconds }` and reuse that tab per
255
- `(user, recipient, asset)` combination.
256
- 3. **Emit credit-flavoured `paymentRequirements`** – embed the latest tab metadata and switch the
257
- identifying strings:
258
-
259
- ```jsonc
260
- {
261
- "scheme": "4mica-credit",
262
- "network": "polygon-amoy",
263
- "maxAmountRequired": "<decimal or 0x amount>",
264
- "resource": "/your/resource",
265
- "description": "Describe the protected work",
266
- "mimeType": "application/json",
267
- "payTo": "<recipientAddress>",
268
- "maxTimeoutSeconds": 300,
269
- "asset": "<assetAddress>",
270
- "extra": {
271
- "tabEndpoint": "<tabEndpoint>",
272
- "...other metadata you already add..."
273
- }
274
- }
275
- ```
276
-
277
- The facilitator enforces that `scheme`, `network`, `payTo` and `asset`
278
- match the tab exactly, so keep them synchronized.
279
-
280
- 4. **Expect credit certificates during settlement** – `/verify` still performs structural checks and
281
- `/settle` now returns `{ success, networkId: "polygon-amoy", certificate: { claims, signature } }`.
282
- Persist the certificate if you need to downstream claim remuneration via 4mica core.
283
-
284
- ### Changes clients (payers) must make
285
-
286
- Payers sign guarantees instead of EIP-3009 transfers. Use the official SDK `rust-sdk-4mica` to manage collateral and produce signatures.
287
-
288
- 1. **Install the SDK** – inside your agent crate run
289
-
290
- ```bash
291
- cargo add rust-sdk-4mica
292
- ```
293
-
294
- or add the same entry manually to `Cargo.toml`.
295
-
296
- 2. **Configure the client** – create a `Client` with the payer’s signing key. The SDK pulls the
297
- remaining parameters (domain separator, operator key, etc.) from `X402_CORE_API_URL`.
298
-
299
- ```rust
300
- use rust_sdk_4mica::{Client, ConfigBuilder};
301
-
302
- let config = ConfigBuilder::default()
303
- .rpc_url("https://api.4mica.xyz/".into())
304
- .wallet_private_key(std::env::var("PAYER_KEY")?)
305
- .build()?;
306
- let client = Client::new(config).await?;
307
- ```
308
-
309
- 3. **Fund the tab** – before requesting credit, ensure the payer has collateral using
310
- `client.user.deposit(...)` (or `approve_erc20` + `deposit` for tokens). Refer to the SDK README
311
- for concrete examples.
312
- 4. **Sign guarantee claims** – derive `PaymentGuaranteeClaims` from the recipient’s
313
- `paymentRequirements` (copy `tabId`, `userAddress`, `payTo`, `asset`, and the desired `amount`),
314
- choose a signing scheme (usually `SigningScheme::Eip712`), and call `client.user.sign_payment`.
315
-
316
- ```rust
317
- use rust_sdk_4mica::{PaymentGuaranteeClaims, SigningScheme, U256};
318
-
319
- let claims = PaymentGuaranteeClaims {
320
- user_address: payer_wallet.clone(),
321
- recipient_address: pay_to.clone(),
322
- tab_id: tab_id_u256,
323
- amount: U256::from(amount_wei),
324
- asset_address: asset.clone(),
325
- timestamp: chrono::Utc::now().timestamp() as u64,
326
- req_id: U256::from(rand::random::<u64>()),
327
- };
328
- let signature = client
329
- .user
330
- .sign_payment(claims.clone(), SigningScheme::Eip712)
331
- .await?;
332
- ```
333
-
334
- 5. **Build the `X-PAYMENT` header** – wrap `{ x402Version: 1, scheme: "4mica-credit", network:
335
- "polygon-amoy", payload: { claims, signature, scheme: "eip712" } }` into base64 (see
336
- `examples/rust_client/main.rs` or `examples/python_client/client.py`) and send it alongside the retrying
337
- HTTP request.
338
- 6. **Settle your tabs** – every tab response includes `ttlSeconds`, which is the settlement window in
339
- seconds from `startTimestamp`. Recipients should call `/settle` (and issue the guarantee) before
340
- that TTL lapses; once a certificate comes back they must relay the `tabId`, `reqId`, `amount`, and
341
- `asset` to the payer. Payers are expected to clear the balance within the same TTL window to avoid
342
- the recipient redeeming their collateral. Use the SDK’s `UserClient::pay_tab` helper to repay the
343
- outstanding credit with the exact asset used when the tab was opened:
344
-
345
- ```rust
346
- use rust_sdk_4mica::U256;
347
-
348
- let receipt = client
349
- .user
350
- .pay_tab(tab_id, req_id, U256::from(amount_wei), recipient_address.clone(), erc20_token)
351
- .await?;
352
- ```
353
-
354
- After broadcasting the repayment transaction, poll `client.user.get_tab_payment_status(tab_id)`
355
- (or `client.user.get_user()`) to verify that `paid` equals the guaranteed amount. If the TTL
356
- expires without repayment the recipient is free to run `recipient.remunerate(cert)` from the SDK,
357
- which slashes your posted collateral on-chain.
358
-
359
- ## Run your own facilitator
360
-
361
- ### Configuration
362
-
363
- Environment variables (defaults shown):
139
+ ## Usage
364
140
 
365
- ```bash
366
- export HOST=0.0.0.0
367
- export PORT=8080
368
- export X402_SCHEME=4mica-credit
369
- # List of supported networks (JSON). Each entry must include `{ "network", "coreApiUrl" }`.
370
- export X402_NETWORKS='[{"network":"polygon-amoy","coreApiUrl":"https://api.4mica.xyz/"}]'
371
- # Legacy single-network fallback if X402_NETWORKS is unset
372
- export X402_NETWORK=polygon-amoy
373
-
374
- # 4mica public API used to fetch operator parameters
375
- export X402_CORE_API_URL=https://api.4mica.xyz/
376
- # Default asset address to apply when callers omit assetAddress in /tabs requests
377
- export ASSET_ADDRESS=0x...
378
-
379
- # Optional: pin the expected domain separator (32-byte hex, 0x-prefixed)
380
- export X402_GUARANTEE_DOMAIN=0x...
381
- # legacy: FOUR_MICA_GUARANTEE_DOMAIN / 4MICA_GUARANTEE_DOMAIN
382
-
383
- # Optional: proxy x402 debit flows to an existing x402-rs facilitator
384
- export X402_DEBIT_URL=https://x402.example.com/
385
-
386
- # Optional: enable standard x402 settlement for EVM networks
387
- export SIGNER_TYPE=private-key
388
- export EVM_PRIVATE_KEY=0x...
389
- export RPC_URL_BASE=https://mainnet.base.org
390
- export RPC_URL_BASE_SEPOLIA=https://sepolia.base.org
141
+ The SDK exposes three main entry points:
142
+
143
+ - `client.user`: payer-side operations (collateral, signing, withdrawals)
144
+ - `client.recipient`: recipient-side operations (tabs, guarantees, remuneration)
145
+ - `X402Flow`: helper for 402-protected HTTP resources
146
+
147
+ ### X402 flow (HTTP 402)
148
+
149
+ The X402 helper turns `paymentRequirements` from a `402 Payment Required` response into an
150
+ X-PAYMENT header (and optional `/settle` call) that the facilitator will accept.
151
+
152
+ #### What the SDK expects from `paymentRequirements`
153
+
154
+ At minimum you need:
155
+ - `scheme` and `network` (scheme must include `4mica`, e.g. `4mica-credit`)
156
+ - `extra.tabEndpoint` for tab resolution
157
+
158
+ `X402Flow` will refresh the tab by calling `extra.tabEndpoint` before signing.
159
+
160
+ #### X402 Version 1
161
+
162
+ Version 1 returns payment requirements in the JSON response body:
163
+
164
+ ```ts
165
+ import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
166
+ import type { PaymentRequirementsV1 } from "@4mica/sdk";
167
+
168
+ type ResourceResponse = {
169
+ x402Version: number;
170
+ accepts: PaymentRequirementsV1[];
171
+ error?: string;
172
+ };
173
+
174
+ const cfg = new ConfigBuilder().walletPrivateKey("0x...").build();
175
+ const client = await Client.new(cfg);
176
+ const flow = X402Flow.fromClient(client);
177
+
178
+ // 1) GET the protected endpoint and parse JSON body
179
+ const res = await fetch("https://resource-url/resource");
180
+ const body = (await res.json()) as ResourceResponse;
181
+
182
+ // 2) Select a payment option
183
+ const requirements = body.accepts[0];
184
+
185
+ // 3) Build the X-PAYMENT header with the SDK
186
+ const payment = await flow.signPayment(requirements, "0xUser");
187
+
188
+ // 4) Call the protected resource with the header
189
+ await fetch("https://resource-url/resource", {
190
+ headers: { "X-PAYMENT": payment.header },
191
+ });
192
+
193
+ await client.aclose();
391
194
  ```
392
195
 
393
- When `X402_NETWORKS` is present it overrides the legacy `X402_NETWORK` / `X402_CORE_API_URL`
394
- environment variables and enables multi-network support. Each configured network gets its own 4mica
395
- Core API base URL so the facilitator can fetch operator parameters and issue guarantees for that
396
- network independently.
196
+ #### X402 Version 2
397
197
 
398
- On startup the facilitator loads the public parameters described above and, if the optional x402
399
- variables are present, initialises the upstream `exact` ERC-3009 facilitator as well. Any schemes
400
- that fail to initialise are omitted from `/supported`.
401
- When `X402_DEBIT_URL` is provided, `/supported` also includes the debit schemes advertised by
402
- the referenced x402-rs facilitator, and `/verify` / `/settle` proxy those requests to it.
198
+ Version 2 uses the `payment-required` header (base64-encoded) instead of a JSON response body:
403
199
 
404
- ### Running
200
+ ```ts
201
+ import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
202
+ import type { X402PaymentRequired, PaymentRequirementsV2 } from "@4mica/sdk";
405
203
 
406
- ```bash
407
- cargo run
204
+ const cfg = new ConfigBuilder().walletPrivateKey("0x...").build();
205
+ const client = await Client.new(cfg);
206
+ const flow = X402Flow.fromClient(client);
207
+
208
+ // 1) GET the protected endpoint and extract payment-required header
209
+ const res = await fetch("https://resource-url/resource");
210
+ const header = res.headers.get("payment-required");
211
+ if (!header) throw new Error("Missing payment-required header");
212
+
213
+ // 2) Decode the header
214
+ const decoded = Buffer.from(header, "base64").toString("utf8");
215
+ const paymentRequired = JSON.parse(decoded) as X402PaymentRequired;
216
+
217
+ // 3) Select a payment option
218
+ const accepted = paymentRequired.accepts[0] as PaymentRequirementsV2;
219
+
220
+ // 4) Build the PAYMENT-SIGNATURE header with the SDK
221
+ const signed = await flow.signPaymentV2(paymentRequired, accepted, "0xUser");
222
+
223
+ // 5) Call the protected resource with the header
224
+ await fetch("https://resource-url/resource", {
225
+ headers: { "PAYMENT-SIGNATURE": signed.header },
226
+ });
227
+
228
+ await client.aclose();
408
229
  ```
409
230
 
410
- The bound address is logged on start-up. Use `GET /supported` to read the `(scheme, network)` pair
411
- that resource servers should use inside their `402 Payment Required` responses.
231
+ #### Resource server / facilitator side
412
232
 
413
- ### Testing
233
+ If your resource server proxies to the facilitator, you can reuse the SDK to settle after
234
+ verifying:
414
235
 
415
- ```bash
416
- cargo test
236
+ ```ts
237
+ import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
238
+ import type { PaymentRequirementsV1, X402SignedPayment } from "@4mica/sdk";
239
+
240
+ async function settle(
241
+ facilitatorUrl: string,
242
+ paymentRequirements: PaymentRequirementsV1,
243
+ payment: X402SignedPayment
244
+ ) {
245
+ const core = await Client.new(
246
+ new ConfigBuilder().walletPrivateKey(process.env.RESOURCE_SIGNER_KEY!).build()
247
+ );
248
+ const flow = X402Flow.fromClient(core);
249
+
250
+ const settled = await flow.settlePayment(payment, paymentRequirements, facilitatorUrl);
251
+ console.log("settlement result:", settled.settlement);
252
+
253
+ await core.aclose();
254
+ }
417
255
  ```
418
256
 
419
- Integration-style tests use a mock verifier to exercise `/verify`, `/settle`, `/tabs`, and the
420
- discovery endpoints without contacting 4mica.
421
-
422
- Point your x402 resource server at this facilitator to outsource 4mica guarantee verification while
423
- keeping custody, settlement, and tab management under your own infrastructure.
424
-
425
- ### How the facilitator moves data
426
-
427
- - **Startup** – the process loads configuration from the environment, then calls
428
- `X402_CORE_API_URL/core/public-params` (or the first `coreApiUrl` listed inside `X402_NETWORKS`) to
429
- fetch the operator’s BLS public key, domain separator, and API base URL. Those values are kept in
430
- memory and reused for all later requests.
431
- - **Tab provisioning (`POST /tabs`)** – recipients can ask the facilitator to open a payment tab on
432
- their behalf. The facilitator relays the request to `core/tabs`, converts the 4mica
433
- response into a plain JSON payload, and hands the tab metadata back to the resource server.
434
- - **Verification (`POST /verify`)** – recipients send the base64 `X-PAYMENT` header plus the
435
- `paymentRequirements` they issued to the client. The facilitator decodes the header, validates the
436
- claims against the requirements, and mirrors the upstream x402 error semantics. No 4mica network
437
- call is made in this path.
438
- - **Settlement (`POST /settle`)** – recipients replay the same payload once they are ready to accept
439
- credit. The facilitator re-runs validation, submits the signed guarantee to
440
- `core/guarantees`, receives the BLS certificate, verifies it against the cached operator public
441
- key (and optional domain), and returns the certificate to the caller.
442
-
443
- If EVM settlement variables are present the facilitator also instantiates the upstream `exact`
444
- facilitator from `x402-rs`, exposing those `(scheme, network)` pairs on `/supported`.
257
+ Notes:
258
+ - `signPayment` and `signPaymentV2` always use EIP-712 signing and will error if the scheme is not 4mica.
259
+ - `UserClient.signPayment` supports `SigningScheme.EIP712` (default) and `SigningScheme.EIP191`.
260
+ - `settlePayment` only hits `/settle`; resource servers should still call `/verify` first when enforcing access.
261
+
262
+ ### API Methods Summary
263
+
264
+ #### UserClient Methods
265
+
266
+ - `approveErc20(token, amount)`
267
+ - `deposit(amount, erc20Token?)`
268
+ - `getUser()`
269
+ - `getTabPaymentStatus(tabId)`
270
+ - `signPayment(claims, scheme?)`
271
+ - `payTab(tabId, reqId, amount, recipientAddress, erc20Token?)`
272
+ - `requestWithdrawal(amount, erc20Token?)`
273
+ - `cancelWithdrawal(erc20Token?)`
274
+ - `finalizeWithdrawal(erc20Token?)`
275
+
276
+ #### RecipientClient Methods
277
+
278
+ - `createTab(userAddress, recipientAddress, erc20Token?, ttl?)`
279
+ - `getTabPaymentStatus(tabId)`
280
+ - `issuePaymentGuarantee(claims, signature, scheme)`
281
+ - `verifyPaymentGuarantee(cert)`
282
+ - `remunerate(cert)`
283
+ - `listSettledTabs()`
284
+ - `listPendingRemunerations()`
285
+ - `getTab(tabId)`
286
+ - `listRecipientTabs(settlementStatuses?)`
287
+ - `getTabGuarantees(tabId)`
288
+ - `getLatestGuarantee(tabId)`
289
+ - `getGuarantee(tabId, reqId)`
290
+ - `listRecipientPayments()`
291
+ - `getCollateralEventsForTab(tabId)`
292
+ - `getUserAssetBalance(userAddress, assetAddress)`
293
+
294
+ #### Admin / RPC Methods
295
+
296
+ Available under `client.rpc` (requires an admin API key):
297
+
298
+ - `updateUserSuspension(userAddress, suspended)`
299
+ - `createAdminApiKey({ name, scopes })`
300
+ - `listAdminApiKeys()`
301
+ - `revokeAdminApiKey(keyId)`
302
+
303
+ ## Error Handling
304
+
305
+ All SDK errors extend `FourMicaError`. Common error types include `ConfigError`, `RpcError`,
306
+ `ClientInitializationError`, `ContractError`, `SigningError`, `VerificationError`, `X402Error`, and
307
+ `AuthError`.
308
+
309
+ ## License
310
+
311
+ MIT