@4mica/sdk 1.1.1 → 1.2.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 (2) hide show
  1. package/README.md +70 -57
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -27,19 +27,19 @@ Node.js 18+ is required.
27
27
 
28
28
  ## Networks
29
29
 
30
- | Shorthand | CAIP-2 | Core API URL |
31
- |---|---|---|
32
- | `ethereum-sepolia` | `eip155:11155111` | `https://ethereum.sepolia.4mica.xyz/` |
33
- | `base-sepolia` | `eip155:84532` | `https://base.sepolia.4mica.xyz/` |
30
+ | Shorthand | CAIP-2 | Core API URL |
31
+ | ------------------ | ----------------- | ----------------------------------------- |
32
+ | `ethereum-sepolia` | `eip155:11155111` | `https://ethereum.sepolia.api.4mica.xyz/` |
33
+ | `base-sepolia` | `eip155:84532` | `https://base.sepolia.api.4mica.xyz/` |
34
34
 
35
35
  The default network is Ethereum Sepolia. Use `.network()` or the `4MICA_NETWORK` environment
36
36
  variable to switch networks.
37
37
 
38
38
  ```ts
39
- import { NETWORKS } from "@4mica/sdk";
39
+ import { NETWORKS } from '@4mica/sdk';
40
40
 
41
- console.log(NETWORKS["base-sepolia"].caip2); // "eip155:84532"
42
- console.log(NETWORKS["base-sepolia"].rpcUrl); // "https://base.sepolia.4mica.xyz/"
41
+ console.log(NETWORKS['base-sepolia'].caip2); // "eip155:84532"
42
+ console.log(NETWORKS['base-sepolia'].rpcUrl); // "https://base.sepolia.api.4mica.xyz/"
43
43
  ```
44
44
 
45
45
  ## Initialization and Configuration
@@ -63,12 +63,12 @@ The SDK requires a signing key and can use sensible defaults for the rest:
63
63
  ### 1) Using ConfigBuilder
64
64
 
65
65
  ```ts
66
- import { Client, ConfigBuilder } from "@4mica/sdk";
66
+ import { Client, ConfigBuilder } from '@4mica/sdk';
67
67
 
68
68
  async function main() {
69
69
  const cfg = new ConfigBuilder()
70
- .network("base-sepolia") // or "ethereum-sepolia" (default)
71
- .walletPrivateKey("0x...")
70
+ .network('base-sepolia') // or "ethereum-sepolia" (default)
71
+ .walletPrivateKey('0x...')
72
72
  .build();
73
73
 
74
74
  const client = await Client.new(cfg);
@@ -88,12 +88,12 @@ Set environment variables (example `.env`):
88
88
  4MICA_WALLET_PRIVATE_KEY="0x..."
89
89
  4MICA_NETWORK="base-sepolia" # shorthand or CAIP-2 id
90
90
  # or override URL directly:
91
- # 4MICA_RPC_URL="https://base.sepolia.4mica.xyz/"
91
+ # 4MICA_RPC_URL="https://base.sepolia.api.4mica.xyz/"
92
92
  4MICA_ETHEREUM_HTTP_RPC_URL="http://localhost:8545"
93
93
  4MICA_CONTRACT_ADDRESS="0x..."
94
94
  4MICA_ADMIN_API_KEY="ak_..."
95
95
  4MICA_BEARER_TOKEN="Bearer <access_token>"
96
- 4MICA_AUTH_URL="https://ethereum.sepolia.4mica.xyz/"
96
+ 4MICA_AUTH_URL="https://ethereum.sepolia.api.4mica.xyz/"
97
97
  4MICA_AUTH_REFRESH_MARGIN_SECS="60"
98
98
  ```
99
99
 
@@ -107,7 +107,7 @@ env 4MICA_WALLET_PRIVATE_KEY="0x..." 4MICA_NETWORK="base-sepolia" node app.js
107
107
  Then in code:
108
108
 
109
109
  ```ts
110
- import { Client, ConfigBuilder } from "@4mica/sdk";
110
+ import { Client, ConfigBuilder } from '@4mica/sdk';
111
111
 
112
112
  const cfg = new ConfigBuilder().fromEnv().build();
113
113
  const client = await Client.new(cfg);
@@ -120,8 +120,8 @@ If you want to integrate with a custom signer (hardware wallet, remote signer, e
120
120
  SIWE auth.
121
121
 
122
122
  ```ts
123
- import { Client, ConfigBuilder } from "@4mica/sdk";
124
- import { privateKeyToAccount } from "viem/accounts";
123
+ import { Client, ConfigBuilder } from '@4mica/sdk';
124
+ import { privateKeyToAccount } from 'viem/accounts';
125
125
 
126
126
  const signer = privateKeyToAccount(process.env.PAYER_KEY as `0x${string}`);
127
127
  const cfg = new ConfigBuilder().signer(signer).build();
@@ -133,11 +133,11 @@ const client = await Client.new(cfg);
133
133
  Enable automatic SIWE auth refresh, or pass a static bearer token:
134
134
 
135
135
  ```ts
136
- import { Client, ConfigBuilder } from "@4mica/sdk";
136
+ import { Client, ConfigBuilder } from '@4mica/sdk';
137
137
 
138
138
  const cfg = new ConfigBuilder()
139
- .walletPrivateKey("0x...")
140
- .rpcUrl("https://api.4mica.xyz/")
139
+ .walletPrivateKey('0x...')
140
+ .rpcUrl('https://api.4mica.xyz/')
141
141
  .enableAuth()
142
142
  .build();
143
143
 
@@ -149,8 +149,8 @@ Or use a static token:
149
149
 
150
150
  ```ts
151
151
  const cfg = new ConfigBuilder()
152
- .walletPrivateKey("0x...")
153
- .bearerToken("Bearer <access_token>")
152
+ .walletPrivateKey('0x...')
153
+ .bearerToken('Bearer <access_token>')
154
154
  .build();
155
155
  ```
156
156
 
@@ -167,6 +167,7 @@ The SDK exposes three main entry points:
167
167
  ### End-to-end Example (Base Sepolia + x402 v2)
168
168
 
169
169
  See `examples/base-sepolia-x402-facilitator-e2e.ts` for a full flow in the `examples` folder:
170
+
170
171
  - deposit collateral
171
172
  - create/get a tab via facilitator
172
173
  - issue and verify V1 + V2 guarantees
@@ -189,6 +190,7 @@ X-PAYMENT header (and optional `/settle` call) that the facilitator will accept.
189
190
  #### What the SDK expects from `paymentRequirements`
190
191
 
191
192
  At minimum you need:
193
+
192
194
  - `scheme` and `network` (scheme must include `4mica`, e.g. `4mica-credit`)
193
195
  - `payTo` (recipient address), `asset`, and `maxAmountRequired` (v1) or `amount` (v2)
194
196
  - `extra.tabEndpoint` for tab resolution
@@ -200,8 +202,8 @@ At minimum you need:
200
202
  Version 1 returns payment requirements in the JSON response body:
201
203
 
202
204
  ```ts
203
- import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
204
- import type { PaymentRequirementsV1 } from "@4mica/sdk";
205
+ import { Client, ConfigBuilder, X402Flow } from '@4mica/sdk';
206
+ import type { PaymentRequirementsV1 } from '@4mica/sdk';
205
207
 
206
208
  type ResourceResponse = {
207
209
  x402Version: number;
@@ -209,23 +211,23 @@ type ResourceResponse = {
209
211
  error?: string;
210
212
  };
211
213
 
212
- const cfg = new ConfigBuilder().walletPrivateKey("0x...").build();
214
+ const cfg = new ConfigBuilder().walletPrivateKey('0x...').build();
213
215
  const client = await Client.new(cfg);
214
216
  const flow = X402Flow.fromClient(client);
215
217
 
216
218
  // 1) GET the protected endpoint and parse JSON body
217
- const res = await fetch("https://resource-url/resource");
219
+ const res = await fetch('https://resource-url/resource');
218
220
  const body = (await res.json()) as ResourceResponse;
219
221
 
220
222
  // 2) Select a payment option
221
223
  const requirements = body.accepts[0];
222
224
 
223
225
  // 3) Build the X-PAYMENT header with the SDK
224
- const payment = await flow.signPayment(requirements, "0xUser");
226
+ const payment = await flow.signPayment(requirements, '0xUser');
225
227
 
226
228
  // 4) Call the protected resource with the header
227
- await fetch("https://resource-url/resource", {
228
- headers: { "X-PAYMENT": payment.header },
229
+ await fetch('https://resource-url/resource', {
230
+ headers: { 'X-PAYMENT': payment.header },
229
231
  });
230
232
 
231
233
  await client.aclose();
@@ -236,31 +238,31 @@ await client.aclose();
236
238
  Version 2 uses the `payment-required` header (base64-encoded) instead of a JSON response body:
237
239
 
238
240
  ```ts
239
- import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
240
- import type { X402PaymentRequired, PaymentRequirementsV2 } from "@4mica/sdk";
241
+ import { Client, ConfigBuilder, X402Flow } from '@4mica/sdk';
242
+ import type { X402PaymentRequired, PaymentRequirementsV2 } from '@4mica/sdk';
241
243
 
242
- const cfg = new ConfigBuilder().walletPrivateKey("0x...").build();
244
+ const cfg = new ConfigBuilder().walletPrivateKey('0x...').build();
243
245
  const client = await Client.new(cfg);
244
246
  const flow = X402Flow.fromClient(client);
245
247
 
246
248
  // 1) GET the protected endpoint and extract payment-required header
247
- const res = await fetch("https://resource-url/resource");
248
- const header = res.headers.get("payment-required");
249
- if (!header) throw new Error("Missing payment-required header");
249
+ const res = await fetch('https://resource-url/resource');
250
+ const header = res.headers.get('payment-required');
251
+ if (!header) throw new Error('Missing payment-required header');
250
252
 
251
253
  // 2) Decode the header
252
- const decoded = Buffer.from(header, "base64").toString("utf8");
254
+ const decoded = Buffer.from(header, 'base64').toString('utf8');
253
255
  const paymentRequired = JSON.parse(decoded) as X402PaymentRequired;
254
256
 
255
257
  // 3) Select a payment option
256
258
  const accepted = paymentRequired.accepts[0] as PaymentRequirementsV2;
257
259
 
258
260
  // 4) Build the PAYMENT-SIGNATURE header with the SDK
259
- const signed = await flow.signPaymentV2(paymentRequired, accepted, "0xUser");
261
+ const signed = await flow.signPaymentV2(paymentRequired, accepted, '0xUser');
260
262
 
261
263
  // 5) Call the protected resource with the header
262
- await fetch("https://resource-url/resource", {
263
- headers: { "PAYMENT-SIGNATURE": signed.header },
264
+ await fetch('https://resource-url/resource', {
265
+ headers: { 'PAYMENT-SIGNATURE': signed.header },
264
266
  });
265
267
 
266
268
  await client.aclose();
@@ -272,8 +274,8 @@ If your resource server proxies to the facilitator, you can reuse the SDK to set
272
274
  verifying:
273
275
 
274
276
  ```ts
275
- import { Client, ConfigBuilder, X402Flow } from "@4mica/sdk";
276
- import type { PaymentRequirementsV1, X402SignedPayment } from "@4mica/sdk";
277
+ import { Client, ConfigBuilder, X402Flow } from '@4mica/sdk';
278
+ import type { PaymentRequirementsV1, X402SignedPayment } from '@4mica/sdk';
277
279
 
278
280
  async function settle(
279
281
  facilitatorUrl: string,
@@ -286,13 +288,14 @@ async function settle(
286
288
  const flow = X402Flow.fromClient(core);
287
289
 
288
290
  const settled = await flow.settlePayment(payment, paymentRequirements, facilitatorUrl);
289
- console.log("settlement result:", settled.settlement);
291
+ console.log('settlement result:', settled.settlement);
290
292
 
291
293
  await core.aclose();
292
294
  }
293
295
  ```
294
296
 
295
297
  Notes:
298
+
296
299
  - `signPayment` and `signPaymentV2` always use EIP-712 signing and will error if the scheme is not 4mica.
297
300
  - `UserClient.signPayment` supports `SigningScheme.EIP712` (default) and `SigningScheme.EIP191`.
298
301
  - `settlePayment` only hits `/settle`; resource servers should still call `/verify` first when enforcing access.
@@ -351,11 +354,17 @@ import {
351
354
  computeValidationSubjectHash,
352
355
  computeValidationRequestHash,
353
356
  SigningScheme,
354
- } from "@4mica/sdk";
357
+ } from '@4mica/sdk';
355
358
 
356
359
  // 1) Build base V1 claims first
357
360
  const baseClaims = PaymentGuaranteeRequestClaims.new(
358
- userAddress, recipientAddress, tabId, amount, timestamp, erc20Token, reqId
361
+ userAddress,
362
+ recipientAddress,
363
+ tabId,
364
+ amount,
365
+ timestamp,
366
+ erc20Token,
367
+ reqId
359
368
  );
360
369
 
361
370
  // 2) Compute canonical hashes
@@ -363,14 +372,14 @@ const validationSubjectHash = computeValidationSubjectHash(baseClaims);
363
372
 
364
373
  const partialV2 = new PaymentGuaranteeRequestClaimsV2({
365
374
  ...baseClaims,
366
- validationRegistryAddress: "0x...",
367
- validationRequestHash: "0x" + "00".repeat(32), // placeholder
375
+ validationRegistryAddress: '0x...',
376
+ validationRequestHash: '0x' + '00'.repeat(32), // placeholder
368
377
  validationChainId: 1,
369
- validatorAddress: "0x...",
378
+ validatorAddress: '0x...',
370
379
  validatorAgentId: 1n,
371
- minValidationScore: 80, // 1–100
380
+ minValidationScore: 80, // 1–100
372
381
  validationSubjectHash,
373
- requiredValidationTag: "my-tag",
382
+ requiredValidationTag: 'my-tag',
374
383
  });
375
384
 
376
385
  const validationRequestHash = computeValidationRequestHash(partialV2);
@@ -387,21 +396,25 @@ All SDK errors extend `FourMicaError`. Import individual error classes to distin
387
396
 
388
397
  ```ts
389
398
  import {
390
- ConfigError, // invalid ConfigBuilder input
391
- RpcError, // 4Mica core service error (has .status and .body)
392
- SigningError, // signing scheme unsupported or address mismatch
393
- ContractError, // on-chain call failed or unexpected result
394
- VerificationError, // BLS certificate decode/domain mismatch
395
- X402Error, // x402 flow error (bad scheme, tab resolution, settlement)
396
- AuthError, // base class for all auth errors
399
+ ConfigError, // invalid ConfigBuilder input
400
+ RpcError, // 4Mica core service error (has .status and .body)
401
+ SigningError, // signing scheme unsupported or address mismatch
402
+ ContractError, // on-chain call failed or unexpected result
403
+ VerificationError, // BLS certificate decode/domain mismatch
404
+ X402Error, // x402 flow error (bad scheme, tab resolution, settlement)
405
+ AuthError, // base class for all auth errors
397
406
  AuthMissingConfigError, // auth not configured when login() is called
398
- } from "@4mica/sdk";
407
+ } from '@4mica/sdk';
399
408
 
400
409
  try {
401
410
  await client.recipient.remunerate(cert);
402
411
  } catch (err) {
403
- if (err instanceof VerificationError) { /* bad cert */ }
404
- if (err instanceof ContractError) { /* on-chain failure */ }
412
+ if (err instanceof VerificationError) {
413
+ /* bad cert */
414
+ }
415
+ if (err instanceof ContractError) {
416
+ /* on-chain failure */
417
+ }
405
418
  }
406
419
  ```
407
420
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4mica/sdk",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "TypeScript SDK for interacting with the 4Mica payment network",
5
5
  "license": "MIT",
6
6
  "repository": {