@4mica/sdk 1.2.1 → 1.2.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.
Files changed (2) hide show
  1. package/dist/contract.js +65 -7
  2. package/package.json +3 -3
package/dist/contract.js CHANGED
@@ -6,6 +6,22 @@ const core4mica_1 = require("./abi/core4mica");
6
6
  const chain_1 = require("./chain");
7
7
  const errors_1 = require("./errors");
8
8
  const utils_1 = require("./utils");
9
+ /**
10
+ * Extract a human-readable message from a viem contract error, falling back
11
+ * to the raw message if no structured reason is available.
12
+ */
13
+ function wrapViemError(error, context) {
14
+ if (error instanceof errors_1.ContractError)
15
+ return error;
16
+ if (error instanceof Error) {
17
+ const e = error;
18
+ const reason = e['cause']?.['reason'] ??
19
+ e['shortMessage'] ??
20
+ error.message;
21
+ return new errors_1.ContractError(`${context}: ${reason}`);
22
+ }
23
+ return new errors_1.ContractError(`${context}: ${String(error)}`);
24
+ }
9
25
  const DEFAULT_REMUNERATE_GAS_LIMIT = 8000000n;
10
26
  const DEFAULT_PAY_TAB_ERC20_GAS_LIMIT = 300000n;
11
27
  const DEFAULT_MAX_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
@@ -100,26 +116,68 @@ class ContractGateway {
100
116
  }
101
117
  return txReceipt;
102
118
  };
119
+ let txReceipt;
103
120
  try {
104
- return await sendApprove(targetAllowance);
121
+ txReceipt = await sendApprove(targetAllowance);
105
122
  }
106
123
  catch (error) {
107
- // Some ERC20s require resetting allowance to zero before setting a new value.
124
+ // Some ERC20s (e.g. USDT) require resetting allowance to zero before
125
+ // setting a new non-zero value.
108
126
  if (targetAllowance === 0n) {
109
- throw error;
127
+ throw wrapViemError(error, 'ERC20 approve failed');
128
+ }
129
+ try {
130
+ await sendApprove(0n);
131
+ txReceipt = await sendApprove(targetAllowance);
132
+ }
133
+ catch (retryError) {
134
+ throw wrapViemError(retryError, 'ERC20 approve failed after allowance reset');
135
+ }
136
+ }
137
+ // Verify the allowance was actually set on-chain. The catch path above can
138
+ // leave allowance at 0 if the re-approve transaction fails silently.
139
+ const account = this.walletClient.account;
140
+ if (account) {
141
+ const actual = await erc20.read.allowance([account.address, spender]);
142
+ if (actual < targetAllowance) {
143
+ throw new errors_1.ContractError(`ERC20 allowance verification failed: on-chain allowance is ${actual} but expected ${targetAllowance}. ` +
144
+ `Try calling approveErc20 again.`);
110
145
  }
111
- await sendApprove(0n);
112
- return sendApprove(targetAllowance);
113
146
  }
147
+ return txReceipt;
114
148
  }
115
149
  async deposit(amount, erc20Token, waitOptions) {
116
150
  const { receipt } = this.splitWaitOptions(waitOptions);
151
+ const parsedAmount = (0, utils_1.parseU256)(amount);
117
152
  let hash;
118
153
  if (erc20Token) {
119
- hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, (0, utils_1.parseU256)(amount)], this.defaultFeeParams()));
154
+ // Pre-check allowance to surface a clear error before hitting the contract.
155
+ const account = this.walletClient.account;
156
+ if (account) {
157
+ const erc20 = this.erc20(erc20Token);
158
+ const allowance = await erc20.read.allowance([
159
+ account.address,
160
+ this.contract.address,
161
+ ]);
162
+ if (allowance < parsedAmount) {
163
+ throw new errors_1.ContractError(`Insufficient ERC20 allowance: ${allowance} approved but ${parsedAmount} required. ` +
164
+ `Call approveErc20("${erc20Token}", ${parsedAmount}) before depositing.`);
165
+ }
166
+ }
167
+ try {
168
+ hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, parsedAmount], this.defaultFeeParams()));
169
+ }
170
+ catch (error) {
171
+ throw wrapViemError(error, 'depositStablecoin failed');
172
+ }
120
173
  }
121
174
  else {
122
- hash = await this.enqueueTx(() => this.contract.write.deposit({ value: (0, utils_1.parseU256)(amount), ...this.defaultFeeParams() }));
175
+ try {
176
+ hash = await this.enqueueTx(() => this.contract.write.deposit({ value: parsedAmount, ...this.defaultFeeParams() }));
177
+ }
178
+ catch (error) {
179
+ throw wrapViemError(error, 'deposit failed');
180
+ }
123
181
  }
124
182
  return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
125
183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4mica/sdk",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "TypeScript SDK for interacting with the 4Mica payment network",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -49,8 +49,8 @@
49
49
  "fmt": "prettier --check \"{src,tests}/**/*.{ts,js,json}\""
50
50
  },
51
51
  "dependencies": {
52
- "@4mica/x402": "file:../x402-4mica/packages/typescript/x402",
53
- "@noble/curves": "^2.0.1",
52
+ "@4mica/x402": "^1.2.0",
53
+ "@noble/curves": "^2.2.0",
54
54
  "@quillai-network/wachai-validation-sdk": "^0.1.0",
55
55
  "viem": "^2.45.1"
56
56
  },