@gasfree-kit/evm-4337 0.2.0 → 0.3.1

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
@@ -43,17 +43,6 @@ This package gives you:
43
43
  └──────────────────────┘
44
44
  ```
45
45
 
46
- ```mermaid
47
- flowchart TD
48
- A["Your app"] --> B["@gasfree-kit/evm-4337"]
49
- B --> C["WDK wallet manager"]
50
- C --> D["Safe smart account"]
51
- D --> E["ERC-4337 UserOperation"]
52
- F["Paymaster"] -.->|sponsors or charges USDT| E
53
- E --> G["Bundler"]
54
- G --> H["EVM chain"]
55
- ```
56
-
57
46
  ## Supported Chains
58
47
 
59
48
  | Chain | Chain ID | Typical fallback fee estimate |
@@ -66,10 +55,21 @@ flowchart TD
66
55
  | Celo | 42220 | `0.05` USDT |
67
56
  | Plasma | 9745 | `0.05` USDT |
68
57
 
58
+ ## Prerequisites
59
+
60
+ This package depends on [`@gasfree-kit/core`](../core/README.md) for:
61
+
62
+ - **Seed phrase generation** — `generateSeedPhrase()` creates the mnemonic used to set up wallets
63
+ - **Chain metadata** — `EVM_CHAINS` provides chain IDs, USDT addresses, and explorer URLs
64
+ - **Address validation** — `validateEvmAddress()` catches malformed addresses before sending
65
+ - **Error classes** — `GasfreeError`, `InsufficientBalanceError`, etc. for consistent error handling
66
+
67
+ `@gasfree-kit/core` is installed automatically as a dependency.
68
+
69
69
  ## Installation
70
70
 
71
71
  ```bash
72
- npm install @gasfree-kit/evm-4337
72
+ npm install @gasfree-kit/evm-4337 @gasfree-kit/core
73
73
  ```
74
74
 
75
75
  Required peer dependency:
@@ -237,15 +237,6 @@ Important:
237
237
  └──────────────────────┘
238
238
  ```
239
239
 
240
- ```mermaid
241
- flowchart TD
242
- A["Seed phrase owner"] --> C["Safe smart account"]
243
- B["Passkey (WebAuthn)"] --> C
244
- C --> D["Signed UserOperation"]
245
- D --> E["Bundler + Paymaster"]
246
- E --> F["EVM chain"]
247
- ```
248
-
249
240
  ### Link a passkey to an existing Safe
250
241
 
251
242
  ```ts
package/dist/index.d.mts CHANGED
@@ -193,6 +193,11 @@ declare function waitForUserOpConfirmation(userOpHash: string, bundlerUrl: strin
193
193
  */
194
194
  declare function handleTransferError(error: unknown, chain: string): Error;
195
195
 
196
+ declare function jsonRpcCall(rpcUrl: string, request: {
197
+ method: string;
198
+ params: unknown[];
199
+ }): Promise<string>;
200
+
196
201
  /**
197
202
  * Register a new passkey via WebAuthn and link it to an existing Safe account.
198
203
  *
@@ -290,4 +295,4 @@ interface CredentialStore {
290
295
  */
291
296
  declare function createCredentialStore(): CredentialStore;
292
297
 
293
- export { type CredentialStore, type EVM4337ClientConfig, type EvmErc4337NetworkConfig, EvmTransfer, FCL_P256_VERIFIER, GAS_FEE_ESTIMATES, GAS_FEE_FALLBACKS, type PasskeyConfig, type PasskeyCredential, type PasskeyLinkResult, type PasskeyOptions, type PasskeyStorageMode, PasskeyTransfer, SAFE_WEBAUTHN_SIGNER_FACTORY, createCredentialStore, encodeErc20Transfer, feeToUsdt, formatTokenBalance, getErc4337ConfigForChain, handleTransferError, isPasskeyLinked, linkPasskeyToSafe, setupErc4337Wallet, toUsdtBaseUnitsEvm, unlinkPasskeyFromSafe, waitForUserOpConfirmation };
298
+ export { type CredentialStore, type EVM4337ClientConfig, type EvmErc4337NetworkConfig, EvmTransfer, FCL_P256_VERIFIER, GAS_FEE_ESTIMATES, GAS_FEE_FALLBACKS, type PasskeyConfig, type PasskeyCredential, type PasskeyLinkResult, type PasskeyOptions, type PasskeyStorageMode, PasskeyTransfer, SAFE_WEBAUTHN_SIGNER_FACTORY, createCredentialStore, encodeErc20Transfer, feeToUsdt, formatTokenBalance, getErc4337ConfigForChain, handleTransferError, isPasskeyLinked, jsonRpcCall, linkPasskeyToSafe, setupErc4337Wallet, toUsdtBaseUnitsEvm, unlinkPasskeyFromSafe, waitForUserOpConfirmation };
package/dist/index.d.ts CHANGED
@@ -193,6 +193,11 @@ declare function waitForUserOpConfirmation(userOpHash: string, bundlerUrl: strin
193
193
  */
194
194
  declare function handleTransferError(error: unknown, chain: string): Error;
195
195
 
196
+ declare function jsonRpcCall(rpcUrl: string, request: {
197
+ method: string;
198
+ params: unknown[];
199
+ }): Promise<string>;
200
+
196
201
  /**
197
202
  * Register a new passkey via WebAuthn and link it to an existing Safe account.
198
203
  *
@@ -290,4 +295,4 @@ interface CredentialStore {
290
295
  */
291
296
  declare function createCredentialStore(): CredentialStore;
292
297
 
293
- export { type CredentialStore, type EVM4337ClientConfig, type EvmErc4337NetworkConfig, EvmTransfer, FCL_P256_VERIFIER, GAS_FEE_ESTIMATES, GAS_FEE_FALLBACKS, type PasskeyConfig, type PasskeyCredential, type PasskeyLinkResult, type PasskeyOptions, type PasskeyStorageMode, PasskeyTransfer, SAFE_WEBAUTHN_SIGNER_FACTORY, createCredentialStore, encodeErc20Transfer, feeToUsdt, formatTokenBalance, getErc4337ConfigForChain, handleTransferError, isPasskeyLinked, linkPasskeyToSafe, setupErc4337Wallet, toUsdtBaseUnitsEvm, unlinkPasskeyFromSafe, waitForUserOpConfirmation };
298
+ export { type CredentialStore, type EVM4337ClientConfig, type EvmErc4337NetworkConfig, EvmTransfer, FCL_P256_VERIFIER, GAS_FEE_ESTIMATES, GAS_FEE_FALLBACKS, type PasskeyConfig, type PasskeyCredential, type PasskeyLinkResult, type PasskeyOptions, type PasskeyStorageMode, PasskeyTransfer, SAFE_WEBAUTHN_SIGNER_FACTORY, createCredentialStore, encodeErc20Transfer, feeToUsdt, formatTokenBalance, getErc4337ConfigForChain, handleTransferError, isPasskeyLinked, jsonRpcCall, linkPasskeyToSafe, setupErc4337Wallet, toUsdtBaseUnitsEvm, unlinkPasskeyFromSafe, waitForUserOpConfirmation };
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  getErc4337ConfigForChain: () => getErc4337ConfigForChain,
44
44
  handleTransferError: () => handleTransferError,
45
45
  isPasskeyLinked: () => isPasskeyLinked,
46
+ jsonRpcCall: () => jsonRpcCall,
46
47
  linkPasskeyToSafe: () => linkPasskeyToSafe,
47
48
  setupErc4337Wallet: () => setupErc4337Wallet,
48
49
  toUsdtBaseUnitsEvm: () => toUsdtBaseUnitsEvm,
@@ -1178,6 +1179,7 @@ var PasskeyTransfer = class {
1178
1179
  getErc4337ConfigForChain,
1179
1180
  handleTransferError,
1180
1181
  isPasskeyLinked,
1182
+ jsonRpcCall,
1181
1183
  linkPasskeyToSafe,
1182
1184
  setupErc4337Wallet,
1183
1185
  toUsdtBaseUnitsEvm,
package/dist/index.mjs CHANGED
@@ -1128,6 +1128,7 @@ export {
1128
1128
  getErc4337ConfigForChain,
1129
1129
  handleTransferError,
1130
1130
  isPasskeyLinked,
1131
+ jsonRpcCall,
1131
1132
  linkPasskeyToSafe,
1132
1133
  setupErc4337Wallet,
1133
1134
  toUsdtBaseUnitsEvm,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gasfree-kit/evm-4337",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "ERC-4337 gasless transactions for EVM chains — powered by WDK",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -14,8 +14,6 @@
14
14
  },
15
15
  "files": [
16
16
  "dist",
17
- "patches",
18
- "scripts",
19
17
  "README.md"
20
18
  ],
21
19
  "dependencies": {
@@ -36,12 +34,27 @@
36
34
  "optional": true
37
35
  }
38
36
  },
37
+ "keywords": [
38
+ "gasless",
39
+ "gas-free",
40
+ "erc-4337",
41
+ "account-abstraction",
42
+ "paymaster",
43
+ "bundler",
44
+ "user-operation",
45
+ "ethereum",
46
+ "evm",
47
+ "web3",
48
+ "sdk",
49
+ "meta-transactions",
50
+ "safe",
51
+ "smart-account"
52
+ ],
39
53
  "license": "MIT",
40
54
  "publishConfig": {
41
55
  "access": "public"
42
56
  },
43
57
  "scripts": {
44
- "postinstall": "node scripts/postinstall.js",
45
58
  "build": "tsup",
46
59
  "dev": "tsup --watch",
47
60
  "test": "vitest run",
@@ -1,68 +0,0 @@
1
- diff --git a/dist/cjs/src/index.cjs b/dist/cjs/src/index.cjs
2
- --- a/dist/cjs/src/index.cjs
3
- +++ b/dist/cjs/src/index.cjs
4
- @@ -1946,6 +1946,9 @@ var GenericFeeEstimator = class {
5
- const context = "paymasterTokenAddress" in paymasterOptions ? {
6
- token: paymasterOptions.paymasterTokenAddress
7
- } : paymasterOptions.paymasterContext ?? {};
8
- + if (paymasterOptions.sponsorshipPolicyId) {
9
- + context.sponsorshipPolicyId = paymasterOptions.sponsorshipPolicyId;
10
- + }
11
- const [feeData, paymasterStubData] = await Promise.all([
12
- this.#getUserOperationGasPrices(this.rpcUrl),
13
- paymasterClient.request({
14
- @@ -2017,7 +2020,8 @@ var GenericFeeEstimator = class {
15
- const sponsoredData = await paymasterClient.request({
16
- method: "pm_getPaymasterData" /* GET_PAYMASTER_DATA */,
17
- params
18
- });
19
- - return sponsoredData;
20
- + sponsoredData.callGasLimit = userOperation.callGasLimit.toString();
21
- + return sponsoredData;
22
- }
23
- const erc20PaymasterData = await paymasterClient.request({
24
- method: "pm_getPaymasterData" /* GET_PAYMASTER_DATA */,
25
- @@ -2032,7 +2036,8 @@ var GenericFeeEstimator = class {
26
- const threshold = await protocolKit.getThreshold();
27
- erc20PaymasterData.verificationGasLimit = (BigInt(erc20PaymasterData.verificationGasLimit) + BigInt(threshold) * this.defaultVerificationGasLimitOverhead).toString();
28
- }
29
- - return erc20PaymasterData;
30
- + erc20PaymasterData.callGasLimit = userOperation.callGasLimit.toString();
31
- + return erc20PaymasterData;
32
- }
33
- async #getUserOperationGasPrices(rpcUrl) {
34
- const client = (0, import_viem11.createPublicClient)({
35
- diff --git a/dist/esm/src/index.mjs b/dist/esm/src/index.mjs
36
- --- a/dist/esm/src/index.mjs
37
- +++ b/dist/esm/src/index.mjs
38
- @@ -1923,6 +1923,9 @@ var GenericFeeEstimator = class {
39
- const context = "paymasterTokenAddress" in paymasterOptions ? {
40
- token: paymasterOptions.paymasterTokenAddress
41
- } : paymasterOptions.paymasterContext ?? {};
42
- + if (paymasterOptions.sponsorshipPolicyId) {
43
- + context.sponsorshipPolicyId = paymasterOptions.sponsorshipPolicyId;
44
- + }
45
- const [feeData, paymasterStubData] = await Promise.all([
46
- this.#getUserOperationGasPrices(this.rpcUrl),
47
- paymasterClient.request({
48
- @@ -1994,7 +1997,8 @@ var GenericFeeEstimator = class {
49
- const sponsoredData = await paymasterClient.request({
50
- method: "pm_getPaymasterData" /* GET_PAYMASTER_DATA */,
51
- params
52
- });
53
- - return sponsoredData;
54
- + sponsoredData.callGasLimit = userOperation.callGasLimit.toString();
55
- + return sponsoredData;
56
- }
57
- const erc20PaymasterData = await paymasterClient.request({
58
- method: "pm_getPaymasterData" /* GET_PAYMASTER_DATA */,
59
- @@ -2009,7 +2013,8 @@ var GenericFeeEstimator = class {
60
- const threshold = await protocolKit.getThreshold();
61
- erc20PaymasterData.verificationGasLimit = (BigInt(erc20PaymasterData.verificationGasLimit) + BigInt(threshold) * this.defaultVerificationGasLimitOverhead).toString();
62
- }
63
- - return erc20PaymasterData;
64
- + erc20PaymasterData.callGasLimit = userOperation.callGasLimit.toString();
65
- + return erc20PaymasterData;
66
- }
67
- async #getUserOperationGasPrices(rpcUrl) {
68
- const client = createPublicClient2({
@@ -1,101 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Postinstall script for @gasfree-kit/evm-4337.
5
- *
6
- * Applies a critical patch to @tetherto/wdk-safe-relay-kit that fixes:
7
- * 1. sponsorshipPolicyId not being passed to Candide paymaster context
8
- * 2. callGasLimit being dropped by paymaster response (both sponsored & ERC-20)
9
- *
10
- * Without this patch, gas estimation fails on Candide-sponsored transactions.
11
- *
12
- * Works with npm, pnpm, and yarn.
13
- * pnpm users can also use patchedDependencies in package.json instead.
14
- */
15
-
16
- const { spawnSync } = require('child_process');
17
- const fs = require('fs');
18
- const path = require('path');
19
- const packageRoot = path.resolve(__dirname, '..');
20
-
21
- function findProjectRoot(startDir) {
22
- let current = startDir;
23
- while (true) {
24
- const parent = path.dirname(current);
25
- if (parent === current) {
26
- return startDir;
27
- }
28
- if (fs.existsSync(path.join(parent, 'package.json'))) {
29
- return parent;
30
- }
31
- current = parent;
32
- }
33
- }
34
-
35
- function runOrThrow(command, args, options) {
36
- const result = spawnSync(command, args, {
37
- stdio: 'pipe',
38
- windowsHide: true,
39
- ...options,
40
- });
41
-
42
- if (result.error) {
43
- throw result.error;
44
- }
45
-
46
- if (result.status !== 0) {
47
- const stderr = result.stderr ? result.stderr.toString().trim() : '';
48
- throw new Error(stderr || `${command} exited with code ${result.status}`);
49
- }
50
- }
51
-
52
- const patchFile = path.join(
53
- __dirname,
54
- '..',
55
- 'patches',
56
- '@tetherto__wdk-safe-relay-kit@4.1.5.patch',
57
- );
58
-
59
- if (!fs.existsSync(patchFile)) {
60
- // Patch file not found — skip (might be in a CI environment or already applied)
61
- process.exit(0);
62
- }
63
-
64
- // Find the target package
65
- const projectRoot = findProjectRoot(packageRoot);
66
- const possiblePaths = [
67
- path.join(projectRoot, 'node_modules', '@tetherto', 'wdk-safe-relay-kit'),
68
- path.join(packageRoot, 'node_modules', '@tetherto', 'wdk-safe-relay-kit'),
69
- ];
70
-
71
- const targetDir = possiblePaths.find((p) => fs.existsSync(p));
72
-
73
- if (!targetDir) {
74
- // @tetherto/wdk-safe-relay-kit not installed yet — skip
75
- // The user's package manager will install peer deps and this runs again
76
- process.exit(0);
77
- }
78
-
79
- // Check if patch is already applied by looking for our marker
80
- const cjsFile = path.join(targetDir, 'dist', 'cjs', 'src', 'index.cjs');
81
- if (fs.existsSync(cjsFile)) {
82
- const content = fs.readFileSync(cjsFile, 'utf8');
83
- if (content.includes('context.sponsorshipPolicyId')) {
84
- // Patch already applied
85
- process.exit(0);
86
- }
87
- }
88
-
89
- // Apply the patch using git apply without shell interpolation.
90
- try {
91
- runOrThrow('git', ['apply', '--unsafe-paths', `--directory=${targetDir}`, patchFile], {
92
- cwd: projectRoot,
93
- });
94
- console.log('@gasfree-kit/evm-4337: Applied wdk-safe-relay-kit patch (Candide paymaster fix)');
95
- } catch {
96
- console.warn(
97
- '@gasfree-kit/evm-4337: Could not auto-apply wdk-safe-relay-kit patch.\n' +
98
- 'Please apply manually: patches/@tetherto__wdk-safe-relay-kit@4.1.5.patch\n' +
99
- 'See: https://github.com/gasfree-kit/evm-4337#patch',
100
- );
101
- }