@1llet.xyz/erc4337-gasless-sdk 0.4.0 → 0.4.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.
@@ -1,173 +0,0 @@
1
- import {
2
- type Address,
3
- type Hash,
4
- type Hex,
5
- type PublicClient,
6
- encodeFunctionData,
7
- encodeAbiParameters,
8
- keccak256
9
- } from "viem";
10
- import { type ChainConfig, type UserOperation, type GasEstimate } from "./types";
11
- import { BundlerClient } from "./BundlerClient";
12
- import { factoryAbi, smartAccountAbi, entryPointAbi } from "./constants";
13
-
14
- export class UserOpBuilder {
15
- private chainConfig: ChainConfig;
16
- private bundlerClient: BundlerClient;
17
- private publicClient: PublicClient;
18
- private entryPointAddress: Address;
19
- private factoryAddress: Address;
20
-
21
- constructor(
22
- chainConfig: ChainConfig,
23
- bundlerClient: BundlerClient,
24
- publicClient: PublicClient
25
- ) {
26
- this.chainConfig = chainConfig;
27
- this.bundlerClient = bundlerClient;
28
- this.publicClient = publicClient;
29
-
30
- // Resolved in AA or here? Let's assume passed valid config or resolve again
31
- // Ideally we shouldn't duplicate logic. AA resolves them.
32
- // Let's rely on config having them or resolving valid ones.
33
- // For now take from config or defaults.
34
- this.entryPointAddress = chainConfig.entryPointAddress!; // Assumed validated by AA
35
- this.factoryAddress = chainConfig.factoryAddress!;
36
- }
37
-
38
- async getNonce(smartAccountAddress: Address): Promise<bigint> {
39
- return await this.publicClient.readContract({
40
- address: this.entryPointAddress,
41
- abi: entryPointAbi,
42
- functionName: "getNonce",
43
- args: [smartAccountAddress, 0n],
44
- }) as bigint;
45
- }
46
-
47
- buildInitCode(owner: Address): Hex {
48
- const createAccountData = encodeFunctionData({
49
- abi: factoryAbi,
50
- functionName: "createAccount",
51
- args: [owner, 0n],
52
- });
53
- return `${this.factoryAddress}${createAccountData.slice(2)}` as Hex;
54
- }
55
-
56
- async isAccountDeployed(smartAccountAddress: Address): Promise<boolean> {
57
- const code = await this.publicClient.getCode({
58
- address: smartAccountAddress,
59
- });
60
- return code !== undefined && code !== "0x";
61
- }
62
-
63
- async buildUserOperationBatch(
64
- owner: Address,
65
- smartAccountAddress: Address,
66
- transactions: { target: Address; value: bigint; data: Hex }[]
67
- ): Promise<UserOperation> {
68
- const isDeployed = await this.isAccountDeployed(smartAccountAddress);
69
- const initCode = isDeployed ? "0x" : this.buildInitCode(owner);
70
-
71
- const targets = transactions.map((tx) => tx.target);
72
- const values = transactions.map((tx) => tx.value);
73
- const datas = transactions.map((tx) => tx.data);
74
-
75
- const callData = encodeFunctionData({
76
- abi: smartAccountAbi,
77
- functionName: "executeBatch",
78
- args: [targets, values, datas],
79
- });
80
-
81
- const nonce = await this.getNonce(smartAccountAddress);
82
-
83
- const partialOp = {
84
- sender: smartAccountAddress,
85
- nonce,
86
- initCode: initCode as Hex,
87
- callData,
88
- paymasterAndData: (this.chainConfig.paymasterAddress || "0x") as Hex,
89
- };
90
-
91
- const gasEstimate = await this.bundlerClient.estimateGas(partialOp);
92
-
93
- return {
94
- ...partialOp,
95
- callGasLimit: BigInt(gasEstimate.callGasLimit),
96
- verificationGasLimit: BigInt(gasEstimate.verificationGasLimit),
97
- preVerificationGas: BigInt(gasEstimate.preVerificationGas),
98
- maxFeePerGas: BigInt(gasEstimate.maxFeePerGas),
99
- maxPriorityFeePerGas: BigInt(gasEstimate.maxPriorityFeePerGas),
100
- signature: "0x",
101
- };
102
- }
103
-
104
- async buildDeployUserOp(
105
- owner: Address,
106
- smartAccountAddress: Address
107
- ): Promise<UserOperation> {
108
- const isDeployed = await this.isAccountDeployed(smartAccountAddress);
109
- if (isDeployed) throw new Error("Account already deployed");
110
-
111
- const initCode = this.buildInitCode(owner);
112
- const callData = "0x";
113
- const nonce = await this.getNonce(smartAccountAddress);
114
-
115
- const partialOp = {
116
- sender: smartAccountAddress,
117
- nonce,
118
- initCode: initCode as Hex,
119
- callData: callData as Hex,
120
- paymasterAndData: (this.chainConfig.paymasterAddress || "0x") as Hex,
121
- };
122
-
123
- const gasEstimate = await this.bundlerClient.estimateGas(partialOp);
124
-
125
- return {
126
- ...partialOp,
127
- callGasLimit: BigInt(gasEstimate.callGasLimit),
128
- verificationGasLimit: BigInt(gasEstimate.verificationGasLimit),
129
- preVerificationGas: BigInt(gasEstimate.preVerificationGas),
130
- maxFeePerGas: BigInt(gasEstimate.maxFeePerGas),
131
- maxPriorityFeePerGas: BigInt(gasEstimate.maxPriorityFeePerGas),
132
- signature: "0x",
133
- };
134
- }
135
-
136
- getUserOpHash(userOp: UserOperation): Hex {
137
- const packed = encodeAbiParameters(
138
- [
139
- { type: "address" },
140
- { type: "uint256" },
141
- { type: "bytes32" },
142
- { type: "bytes32" },
143
- { type: "uint256" },
144
- { type: "uint256" },
145
- { type: "uint256" },
146
- { type: "uint256" },
147
- { type: "uint256" },
148
- { type: "bytes32" },
149
- ],
150
- [
151
- userOp.sender,
152
- userOp.nonce,
153
- keccak256(userOp.initCode),
154
- keccak256(userOp.callData),
155
- userOp.callGasLimit,
156
- userOp.verificationGasLimit,
157
- userOp.preVerificationGas,
158
- userOp.maxFeePerGas,
159
- userOp.maxPriorityFeePerGas,
160
- keccak256(userOp.paymasterAndData),
161
- ]
162
- );
163
-
164
- const packedHash = keccak256(packed);
165
-
166
- return keccak256(
167
- encodeAbiParameters(
168
- [{ type: "bytes32" }, { type: "address" }, { type: "uint256" }],
169
- [packedHash, this.entryPointAddress, BigInt(this.chainConfig.chain.id)]
170
- )
171
- );
172
- }
173
- }
package/src/chains.ts DELETED
@@ -1,54 +0,0 @@
1
- import { type ChainConfig } from "./types";
2
- import { base, baseSepolia } from "viem/chains";
3
-
4
- export const BASE_MAINNET: ChainConfig = {
5
- chain: base,
6
- bundlerUrl: "http://localhost:3000/rpc?chain=base", // Default to local bundler pattern
7
-
8
- // Addresses
9
- entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
10
- factoryAddress: "0xe2584152891E4769025807DEa0cD611F135aDC68",
11
- paymasterAddress: "0x1e13Eb16C565E3f3FDe49A011755e50410bb1F95",
12
-
13
- tokens: [
14
- {
15
- symbol: "USDC",
16
- decimals: 6,
17
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
18
- },
19
- {
20
- symbol: "ETH",
21
- decimals: 18,
22
- address: "0x0000000000000000000000000000000000000000"
23
- }
24
- ]
25
- };
26
-
27
- export const BASE_SEPOLIA: ChainConfig = {
28
- chain: baseSepolia,
29
- bundlerUrl: "http://localhost:3000/rpc?chain=baseSepolia", // Default to local bundler pattern
30
-
31
- // Addresses
32
- entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
33
- factoryAddress: "0x9406Cc6185a346906296840746125a0E44976454",
34
- // Paymaster not configured in deployments.ts for Sepolia?
35
-
36
- tokens: [
37
- {
38
- symbol: "USDC",
39
- decimals: 6,
40
- address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
41
- },
42
- {
43
- symbol: "ETH",
44
- decimals: 18,
45
- address: "0x0000000000000000000000000000000000000000"
46
- }
47
- ]
48
- };
49
-
50
- // Map accessible by ChainID
51
- export const CHAIN_CONFIGS: Record<number, ChainConfig> = {
52
- [base.id]: BASE_MAINNET,
53
- [baseSepolia.id]: BASE_SEPOLIA
54
- };
package/src/constants.ts DELETED
@@ -1,131 +0,0 @@
1
- export const DEFAULT_ENTRYPOINT = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
2
- export const DEFAULT_FACTORY = "0x9406Cc6185a346906296840746125a0E44976454"; // SimpleAccountFactory v0.6
3
-
4
- export const factoryAbi = [
5
- {
6
- inputs: [
7
- { name: "owner", type: "address" },
8
- { name: "salt", type: "uint256" },
9
- ],
10
- name: "getAccountAddress",
11
- outputs: [{ name: "", type: "address" }],
12
- stateMutability: "view",
13
- type: "function",
14
- },
15
- {
16
- inputs: [
17
- { name: "owner", type: "address" },
18
- { name: "salt", type: "uint256" },
19
- ],
20
- name: "isAccountDeployed",
21
- outputs: [{ name: "", type: "bool" }],
22
- stateMutability: "view",
23
- type: "function",
24
- },
25
- {
26
- inputs: [
27
- { name: "owner", type: "address" },
28
- { name: "salt", type: "uint256" },
29
- ],
30
- name: "createAccount",
31
- outputs: [{ name: "account", type: "address" }],
32
- stateMutability: "nonpayable",
33
- type: "function",
34
- },
35
- ] as const;
36
-
37
- export const entryPointAbi = [
38
- {
39
- inputs: [
40
- { name: "sender", type: "address" },
41
- { name: "key", type: "uint192" },
42
- ],
43
- name: "getNonce",
44
- outputs: [{ name: "nonce", type: "uint256" }],
45
- stateMutability: "view",
46
- type: "function",
47
- },
48
- ] as const;
49
-
50
- export const smartAccountAbi = [
51
- {
52
- inputs: [
53
- { name: "target", type: "address" },
54
- { name: "value", type: "uint256" },
55
- { name: "data", type: "bytes" },
56
- ],
57
- name: "execute",
58
- outputs: [],
59
- stateMutability: "nonpayable",
60
- type: "function",
61
- },
62
- {
63
- inputs: [
64
- { name: "targets", type: "address[]" },
65
- { name: "values", type: "uint256[]" },
66
- { name: "datas", type: "bytes[]" },
67
- ],
68
- name: "executeBatch",
69
- outputs: [],
70
- stateMutability: "nonpayable",
71
- type: "function",
72
- },
73
- ] as const;
74
-
75
- export const erc20Abi = [
76
- {
77
- inputs: [{ name: "account", type: "address" }],
78
- name: "balanceOf",
79
- outputs: [{ name: "", type: "uint256" }],
80
- stateMutability: "view",
81
- type: "function",
82
- },
83
- {
84
- inputs: [
85
- { name: "to", type: "address" },
86
- { name: "amount", type: "uint256" },
87
- ],
88
- name: "transfer",
89
- outputs: [{ name: "", type: "bool" }],
90
- stateMutability: "nonpayable",
91
- type: "function",
92
- },
93
- {
94
- inputs: [
95
- { name: "spender", type: "address" },
96
- { name: "amount", type: "uint256" },
97
- ],
98
- name: "approve",
99
- outputs: [{ name: "", type: "bool" }],
100
- stateMutability: "nonpayable",
101
- type: "function",
102
- },
103
- {
104
- inputs: [
105
- { name: "owner", type: "address" },
106
- { name: "spender", type: "address" },
107
- ],
108
- name: "allowance",
109
- outputs: [{ name: "", type: "uint256" }],
110
- stateMutability: "view",
111
- type: "function",
112
- },
113
- {
114
- inputs: [
115
- { name: "from", type: "address" },
116
- { name: "to", type: "address" },
117
- { name: "amount", type: "uint256" },
118
- ],
119
- name: "transferFrom",
120
- outputs: [{ name: "", type: "bool" }],
121
- stateMutability: "nonpayable",
122
- type: "function",
123
- },
124
- {
125
- inputs: [],
126
- name: "decimals",
127
- outputs: [{ name: "", type: "uint8" }],
128
- stateMutability: "view",
129
- type: "function",
130
- },
131
- ] as const;
package/src/index.ts DELETED
@@ -1,12 +0,0 @@
1
- // Core
2
- export { AccountAbstraction } from "./AccountAbstraction";
3
- export { BundlerClient } from "./BundlerClient";
4
-
5
- // Config & Registry
6
- export { BASE_MAINNET, BASE_SEPOLIA, CHAIN_CONFIGS } from "./chains";
7
-
8
- // Types
9
- export type { ChainConfig, Token, UserOperation, UserOpReceipt } from "./types";
10
-
11
- // Constants (ABIs)
12
- export { erc20Abi, smartAccountAbi, entryPointAbi } from "./constants";
package/src/types.ts DELETED
@@ -1,57 +0,0 @@
1
- import { type Address, type Chain, type Hash, type Hex } from "viem";
2
-
3
- export interface Token {
4
- symbol: string;
5
- decimals: number;
6
- address: Address;
7
- }
8
-
9
- export interface ChainConfig {
10
- chain: Chain;
11
- rpcUrl?: string; // Optional, defaults to chain.rpcUrls.default
12
- bundlerUrl: string;
13
- entryPointAddress?: Address;
14
- factoryAddress?: Address;
15
- paymasterAddress?: Address;
16
- tokens: Token[];
17
- }
18
-
19
- export interface UserOperation {
20
- sender: Address;
21
- nonce: bigint;
22
- initCode: Hex;
23
- callData: Hex;
24
- callGasLimit: bigint;
25
- verificationGasLimit: bigint;
26
- preVerificationGas: bigint;
27
- maxFeePerGas: bigint;
28
- maxPriorityFeePerGas: bigint;
29
- paymasterAndData: Hex;
30
- signature: Hex;
31
- }
32
-
33
- export interface GasEstimate {
34
- callGasLimit: string;
35
- verificationGasLimit: string;
36
- preVerificationGas: string;
37
- maxFeePerGas: string;
38
- maxPriorityFeePerGas: string;
39
- }
40
-
41
- export interface UserOpReceipt {
42
- userOpHash: Hash;
43
- sender: Address;
44
- success: boolean;
45
- actualGasCost: string;
46
- receipt: {
47
- transactionHash: Hash;
48
- blockNumber: string;
49
- };
50
- }
51
-
52
- export interface ApprovalSupportResult {
53
- type: "permit" | "approve" | "none";
54
- gasCost?: string;
55
- fundingNeeded?: string;
56
- fundedAmount?: string;
57
- }
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "declaration": true,
7
- "strict": true,
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "forceConsistentCasingInFileNames": true
11
- },
12
- "include": [
13
- "src/**/*"
14
- ],
15
- "exclude": [
16
- "node_modules",
17
- "dist"
18
- ]
19
- }
package/tsup.config.ts DELETED
@@ -1,10 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts"],
5
- format: ["cjs", "esm"], // Build for commonjs and esmodules
6
- dts: true, // Generate declaration file (.d.ts)
7
- splitting: false,
8
- sourcemap: true,
9
- clean: true,
10
- });