@4mica/sdk 1.0.0 → 1.0.2

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 (48) hide show
  1. package/README.md +17 -0
  2. package/dist/contract.d.ts +1 -0
  3. package/dist/contract.js +44 -18
  4. package/package.json +7 -2
  5. package/dist/abi/core4mica.json +0 -1605
  6. package/dist/abi/erc20.json +0 -187
  7. package/dist/client.d.ts +0 -56
  8. package/dist/client.js +0 -258
  9. package/dist/src/abi/core4mica.json +0 -1605
  10. package/dist/src/abi/erc20.json +0 -187
  11. package/dist/src/bls.d.ts +0 -5
  12. package/dist/src/bls.js +0 -45
  13. package/dist/src/client.d.ts +0 -55
  14. package/dist/src/client.js +0 -214
  15. package/dist/src/config.d.ts +0 -21
  16. package/dist/src/config.js +0 -76
  17. package/dist/src/contract.d.ts +0 -33
  18. package/dist/src/contract.js +0 -121
  19. package/dist/src/errors.d.ts +0 -17
  20. package/dist/src/errors.js +0 -31
  21. package/dist/src/guarantee.d.ts +0 -3
  22. package/dist/src/guarantee.js +0 -66
  23. package/dist/src/index.d.ts +0 -11
  24. package/dist/src/index.js +0 -27
  25. package/dist/src/models.d.ts +0 -119
  26. package/dist/src/models.js +0 -132
  27. package/dist/src/rpc.d.ts +0 -30
  28. package/dist/src/rpc.js +0 -122
  29. package/dist/src/signing.d.ts +0 -16
  30. package/dist/src/signing.js +0 -102
  31. package/dist/src/utils.d.ts +0 -8
  32. package/dist/src/utils.js +0 -78
  33. package/dist/src/x402.d.ts +0 -77
  34. package/dist/src/x402.js +0 -214
  35. package/dist/tests/config.test.d.ts +0 -1
  36. package/dist/tests/config.test.js +0 -26
  37. package/dist/tests/guarantee.test.d.ts +0 -1
  38. package/dist/tests/guarantee.test.js +0 -26
  39. package/dist/tests/rpc.test.d.ts +0 -1
  40. package/dist/tests/rpc.test.js +0 -44
  41. package/dist/tests/signing.test.d.ts +0 -1
  42. package/dist/tests/signing.test.js +0 -25
  43. package/dist/tests/utils.test.d.ts +0 -1
  44. package/dist/tests/utils.test.js +0 -25
  45. package/dist/tests/x402.test.d.ts +0 -1
  46. package/dist/tests/x402.test.js +0 -65
  47. package/dist/x402.d.ts +0 -78
  48. package/dist/x402.js +0 -231
package/README.md CHANGED
@@ -144,6 +144,23 @@ The SDK exposes three main entry points:
144
144
  - `client.recipient`: recipient-side operations (tabs, guarantees, remuneration)
145
145
  - `X402Flow`: helper for 402-protected HTTP resources
146
146
 
147
+ ### End-to-end Example (Base Sepolia + x402 v2)
148
+
149
+ See `examples/base-sepolia-x402-facilitator-e2e.ts` for a full flow in the `examples` folder:
150
+ - deposit collateral
151
+ - create/get a tab via facilitator
152
+ - issue and verify V1 + V2 guarantees
153
+ - `payTab` in ERC20 for V1
154
+ - remunerate V2 only after `wachai-validation-sdk` returns a passing ERC-8004 validation
155
+ - submit + finalize withdrawal
156
+
157
+ Run it with:
158
+
159
+ ```bash
160
+ cp examples/.env.x402-facilitator-e2e.example examples/.env.x402-facilitator-e2e
161
+ npx dotenv-cli -e examples/.env.x402-facilitator-e2e -- npm run example:base-sepolia:x402-v2
162
+ ```
163
+
147
164
  ### X402 flow (HTTP 402)
148
165
 
149
166
  The X402 helper turns `paymentRequirements` from a `402 Payment Required` response into an
@@ -21,6 +21,7 @@ export declare class ContractGateway {
21
21
  static create(rpcUrl: string, signer: Account, contractAddress: Hex, chainId: number): Promise<ContractGateway>;
22
22
  private erc20;
23
23
  private enqueueTx;
24
+ private defaultFeeParams;
24
25
  private splitWaitOptions;
25
26
  getGuaranteeDomain(): Promise<string>;
26
27
  getGuaranteeVersionConfig(version: number): Promise<{
package/dist/contract.js CHANGED
@@ -7,6 +7,9 @@ const chain_1 = require("./chain");
7
7
  const errors_1 = require("./errors");
8
8
  const utils_1 = require("./utils");
9
9
  const DEFAULT_REMUNERATE_GAS_LIMIT = 8000000n;
10
+ const DEFAULT_PAY_TAB_ERC20_GAS_LIMIT = 300000n;
11
+ const DEFAULT_MAX_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
12
+ const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
10
13
  class ContractGateway {
11
14
  publicClient;
12
15
  walletClient;
@@ -58,6 +61,12 @@ class ContractGateway {
58
61
  this.txQueue = run.then(() => undefined, () => undefined);
59
62
  return run;
60
63
  }
64
+ defaultFeeParams() {
65
+ return {
66
+ maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
67
+ maxPriorityFeePerGas: DEFAULT_MAX_PRIORITY_FEE_PER_GAS,
68
+ };
69
+ }
61
70
  splitWaitOptions(waitOptions) {
62
71
  if (!waitOptions) {
63
72
  return { receipt: {} };
@@ -81,19 +90,36 @@ class ContractGateway {
81
90
  async approveErc20(token, amount, waitOptions) {
82
91
  const { receipt } = this.splitWaitOptions(waitOptions);
83
92
  const erc20 = this.erc20(token);
84
- // spender address logic
85
93
  const spender = this.contract.address;
86
- const hash = await this.enqueueTx(() => erc20.write.approve([spender, (0, utils_1.parseU256)(amount)]));
87
- return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
94
+ const targetAllowance = (0, utils_1.parseU256)(amount);
95
+ const sendApprove = async (value) => {
96
+ const hash = await this.enqueueTx(() => erc20.write.approve([spender, value], this.defaultFeeParams()));
97
+ const txReceipt = await this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
98
+ if (txReceipt.status !== 'success') {
99
+ throw new errors_1.ContractError(`approve transaction reverted: ${hash}`);
100
+ }
101
+ return txReceipt;
102
+ };
103
+ try {
104
+ return await sendApprove(targetAllowance);
105
+ }
106
+ catch (error) {
107
+ // Some ERC20s require resetting allowance to zero before setting a new value.
108
+ if (targetAllowance === 0n) {
109
+ throw error;
110
+ }
111
+ await sendApprove(0n);
112
+ return sendApprove(targetAllowance);
113
+ }
88
114
  }
89
115
  async deposit(amount, erc20Token, waitOptions) {
90
116
  const { receipt } = this.splitWaitOptions(waitOptions);
91
117
  let hash;
92
118
  if (erc20Token) {
93
- hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, (0, utils_1.parseU256)(amount)]));
119
+ hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, (0, utils_1.parseU256)(amount)], this.defaultFeeParams()));
94
120
  }
95
121
  else {
96
- hash = await this.enqueueTx(() => this.contract.write.deposit({ value: (0, utils_1.parseU256)(amount) }));
122
+ hash = await this.enqueueTx(() => this.contract.write.deposit({ value: (0, utils_1.parseU256)(amount), ...this.defaultFeeParams() }));
97
123
  }
98
124
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
99
125
  }
@@ -128,17 +154,16 @@ class ContractGateway {
128
154
  to: recipient,
129
155
  value: (0, utils_1.parseU256)(amount),
130
156
  data: (0, utils_1.hexFromBytes)(data),
157
+ ...this.defaultFeeParams(),
131
158
  }));
132
159
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
133
160
  }
134
161
  async payTabErc20(tabId, amount, erc20Token, recipient, waitOptions) {
135
- const { receipt } = this.splitWaitOptions(waitOptions);
136
- const hash = await this.enqueueTx(() => this.contract.write.payTabInERC20Token([
137
- (0, utils_1.parseU256)(tabId),
138
- erc20Token,
139
- (0, utils_1.parseU256)(amount),
140
- recipient,
141
- ]));
162
+ const { gas, receipt } = this.splitWaitOptions(waitOptions);
163
+ const hash = await this.enqueueTx(() => this.contract.write.payTabInERC20Token([(0, utils_1.parseU256)(tabId), erc20Token, (0, utils_1.parseU256)(amount), recipient], {
164
+ gas: gas ?? DEFAULT_PAY_TAB_ERC20_GAS_LIMIT,
165
+ ...this.defaultFeeParams(),
166
+ }));
142
167
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
143
168
  }
144
169
  async requestWithdrawal(amount, erc20Token, waitOptions) {
@@ -146,10 +171,10 @@ class ContractGateway {
146
171
  const value = (0, utils_1.parseU256)(amount);
147
172
  let hash;
148
173
  if (erc20Token) {
149
- hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([erc20Token, value]));
174
+ hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([erc20Token, value], this.defaultFeeParams()));
150
175
  }
151
176
  else {
152
- hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([value]));
177
+ hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([value], this.defaultFeeParams()));
153
178
  }
154
179
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
155
180
  }
@@ -157,10 +182,10 @@ class ContractGateway {
157
182
  const { receipt } = this.splitWaitOptions(waitOptions);
158
183
  let hash;
159
184
  if (erc20Token) {
160
- hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal([erc20Token]));
185
+ hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal([erc20Token], this.defaultFeeParams()));
161
186
  }
162
187
  else {
163
- hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal());
188
+ hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal(this.defaultFeeParams()));
164
189
  }
165
190
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
166
191
  }
@@ -168,10 +193,10 @@ class ContractGateway {
168
193
  const { receipt } = this.splitWaitOptions(waitOptions);
169
194
  let hash;
170
195
  if (erc20Token) {
171
- hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal([erc20Token]));
196
+ hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal([erc20Token], this.defaultFeeParams()));
172
197
  }
173
198
  else {
174
- hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal());
199
+ hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal(this.defaultFeeParams()));
175
200
  }
176
201
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
177
202
  }
@@ -189,6 +214,7 @@ class ContractGateway {
189
214
  };
190
215
  const hash = await this.enqueueTx(() => this.contract.write.remunerate([(0, utils_1.hexFromBytes)(claimsBlob), sigStruct], {
191
216
  gas: gas ?? DEFAULT_REMUNERATE_GAS_LIMIT,
217
+ ...this.defaultFeeParams(),
192
218
  }));
193
219
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
194
220
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4mica/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "TypeScript SDK for interacting with the 4Mica payment network",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -39,14 +39,19 @@
39
39
  "ethers"
40
40
  ],
41
41
  "scripts": {
42
- "build": "tsc -p tsconfig.build.json",
42
+ "clean": "node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true })\"",
43
+ "build": "npm run clean && tsc -p tsconfig.build.json",
43
44
  "test": "vitest run",
44
45
  "test:e2e": "vitest run --config vitest.e2e.config.ts",
46
+ "example:base-sepolia:x402-v2": "node_modules/.bin/tsx examples/base-sepolia-x402-facilitator-e2e.ts",
47
+ "example:manual:agents": "node_modules/.bin/tsx examples/manual-agents/demo.ts",
45
48
  "lint": "eslint . --ext .ts",
46
49
  "fmt": "prettier --check \"{src,tests}/**/*.{ts,js,json}\""
47
50
  },
48
51
  "dependencies": {
52
+ "@4mica/x402": "file:../x402-4mica/packages/typescript/x402",
49
53
  "@noble/curves": "^2.0.1",
54
+ "@quillai-network/wachai-validation-sdk": "^0.1.0",
50
55
  "viem": "^2.45.1"
51
56
  },
52
57
  "devDependencies": {