@1llet.xyz/erc4337-gasless-sdk 0.4.29 → 0.4.31
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 +79 -195
- package/dist/index.d.mts +1 -10
- package/dist/index.d.ts +1 -10
- package/dist/index.js +234 -329
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +235 -330
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ERC-4337 Gasless SDK ⛽️
|
|
2
2
|
|
|
3
|
-
A lightweight, typed SDK to integrate Account Abstraction (ERC-4337) into your dApp. It handles Smart Account creation, gasless transactions, and
|
|
3
|
+
A lightweight, typed SDK to integrate Account Abstraction (ERC-4337) and Cross-Chain transfers into your dApp. It handles Smart Account creation, gasless transactions, and orchestrates cross-chain bridges.
|
|
4
4
|
|
|
5
5
|
## 📦 Installation
|
|
6
6
|
|
|
@@ -10,243 +10,127 @@ npm install @1llet.xyz/erc4337-gasless-sdk viem
|
|
|
10
10
|
yarn add @1llet.xyz/erc4337-gasless-sdk viem
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
## 🚀 Quick Start
|
|
13
|
+
## 🚀 Quick Start (Account Abstraction)
|
|
14
14
|
|
|
15
|
-
### 1. Configuration
|
|
15
|
+
### 1. Configuration & Initialization
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Import chain configurations directly from the SDK.
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
|
-
|
|
21
|
-
import { BASE_SEPOLIA, type ChainConfig } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
22
|
-
import { AccountAbstraction } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
20
|
+
import { BASE_MAINNET, AccountAbstraction } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
23
21
|
|
|
24
|
-
//
|
|
25
|
-
const aa = new AccountAbstraction(
|
|
26
|
-
|
|
27
|
-
await aa.connect();
|
|
22
|
+
// Initialize with a supported chain
|
|
23
|
+
const aa = new AccountAbstraction(BASE_MAINNET);
|
|
28
24
|
```
|
|
29
25
|
|
|
30
|
-
### 2.
|
|
31
|
-
|
|
32
|
-
Two modes are supported: **Browser (MetaMask)** and **Server/Script (Private Key)**.
|
|
26
|
+
### 2. Connect Wallet
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
Supports **Browser (MetaMask)** and **Private Key (Server)**.
|
|
35
29
|
|
|
36
30
|
```typescript
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const aa = new AccountAbstraction(config);
|
|
40
|
-
|
|
41
|
-
// Connect to MetaMask (or any injected provider)
|
|
42
|
-
// This calculates the Smart Account address deterministically (Counterfactual)
|
|
31
|
+
// A. Browser (MetaMask / Injected)
|
|
43
32
|
const { owner, smartAccount } = await aa.connect();
|
|
44
33
|
|
|
45
|
-
|
|
34
|
+
// B. Private Key (Backend / Bots)
|
|
35
|
+
const { owner, smartAccount } = await aa.connect("0xMY_PRIVATE_KEY");
|
|
36
|
+
|
|
37
|
+
console.log("EOA:", owner);
|
|
46
38
|
console.log("Smart Account:", smartAccount);
|
|
47
39
|
```
|
|
48
40
|
|
|
49
|
-
|
|
41
|
+
### 3. Send Gasless Transactions
|
|
50
42
|
|
|
51
|
-
|
|
43
|
+
Transactions are sponsored by the Paymaster automatically.
|
|
52
44
|
|
|
53
45
|
```typescript
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// Connect using the private key
|
|
57
|
-
const { owner, smartAccount } = await aa.connect(PRIVATE_KEY);
|
|
58
|
-
|
|
59
|
-
console.log("Local Signer:", owner);
|
|
60
|
-
// seamless transaction execution...
|
|
61
|
-
await aa.transfer("USDC", recipient, amount);
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### 3. Send a Gasless Transaction
|
|
46
|
+
// 1. Transfer ERC-20 (USDC)
|
|
47
|
+
await aa.transfer("USDC", recipientAddress, 1000000n); // 1 USDC (6 decimals)
|
|
65
48
|
|
|
66
|
-
|
|
49
|
+
// 2. Transfer Native Token (ETH/DAI/MATIC)
|
|
50
|
+
// The SDK detects the native asset from chain config
|
|
51
|
+
await aa.transfer("ETH", recipientAddress, parseEther("0.1"));
|
|
67
52
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const myContractAbi = parseAbi(["function safeMint(address to)"]);
|
|
73
|
-
const callData = encodeFunctionData({
|
|
74
|
-
abi: myContractAbi,
|
|
75
|
-
functionName: "safeMint",
|
|
76
|
-
args: [smartAccount]
|
|
53
|
+
// 3. Any Contract Call (e.g. Mint NFT)
|
|
54
|
+
await aa.sendTransaction({
|
|
55
|
+
target: "0xNftContract",
|
|
56
|
+
data: encodeFunctionData({ ... })
|
|
77
57
|
});
|
|
78
|
-
|
|
79
|
-
// Build the UserOperation
|
|
80
|
-
// This automatically handles: InitCode (if not deployed), Gas Estimation, and Paymaster data
|
|
81
|
-
const userOp = await aa.buildUserOperationBatch([
|
|
82
|
-
{
|
|
83
|
-
target: "0xMyNftContract...",
|
|
84
|
-
value: 0n,
|
|
85
|
-
data: callData
|
|
86
|
-
}
|
|
87
|
-
]);
|
|
88
|
-
|
|
89
|
-
// Sign with the EOA (MetaMask)
|
|
90
|
-
const signedOp = await aa.signUserOperation(userOp);
|
|
91
|
-
|
|
92
|
-
// Send to Bundler
|
|
93
|
-
const userOpHash = await aa.sendUserOperation(signedOp);
|
|
94
|
-
console.log("Transaction sent! Hash:", userOpHash);
|
|
95
|
-
|
|
96
|
-
// Wait for confirmation
|
|
97
|
-
const receipt = await aa.waitForUserOperation(userOpHash);
|
|
98
|
-
console.log("Transaction confirmed in block:", receipt.receipt.blockNumber);
|
|
99
58
|
```
|
|
100
59
|
|
|
101
|
-
|
|
60
|
+
---
|
|
102
61
|
|
|
103
|
-
|
|
62
|
+
## 🌉 Cross-Chain Transfer Manager
|
|
104
63
|
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
const result = await aa.requestApprovalSupport(
|
|
108
|
-
usdcAddress,
|
|
109
|
-
spenderAddress,
|
|
110
|
-
amount
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
if (result.fundingNeeded) {
|
|
114
|
-
console.log(`User was funded with ${result.fundedAmount} ETH to pay for gas!`);
|
|
115
|
-
}
|
|
116
|
-
} catch (e) {
|
|
117
|
-
console.error("Failed to fund user:", e);
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## 🛠️ Build Locally
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
git clone https://github.com/your-repo/erc4337-gasless-sdk.git
|
|
125
|
-
cd erc4337-gasless-sdk
|
|
126
|
-
npm install
|
|
127
|
-
npm run build
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## � API Reference
|
|
131
|
-
|
|
132
|
-
### Balances & Allowances
|
|
64
|
+
The `TransferManager` orchestrates transfers between chains, choosing the best strategy (CCTP, Near Intents) or signaling a direct transfer if on the same chain.
|
|
133
65
|
|
|
134
66
|
```typescript
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
// 1. Send ETH or Call Contract (Single)
|
|
165
|
-
const receipt = await aa.sendTransaction({
|
|
166
|
-
target: "0x123...",
|
|
167
|
-
value: 1000000000000000000n, // 1 ETH
|
|
168
|
-
data: "0x..." // Optional callData
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// 2. Send Multiple Transactions (Batch)
|
|
172
|
-
// Great for approving + swapping, or multiple transfers
|
|
173
|
-
const receipt = await aa.sendBatchTransaction([
|
|
174
|
-
{ target: "0xToken...", data: encodeApproveData },
|
|
175
|
-
{ target: "0xSwap...", data: encodeSwapData }
|
|
176
|
-
]);
|
|
177
|
-
|
|
178
|
-
// 3. Transfer ERC-20 Tokens (Helper)
|
|
179
|
-
// Automatically encodes the
|
|
180
|
-
// 1. Transfer ERC-20 (USDC)
|
|
181
|
-
await aa.transfer("USDC", recipient, amount);
|
|
182
|
-
|
|
183
|
-
// 2. Transfer Native Token (ETH)
|
|
184
|
-
// The SDK detects the "ETH" symbol and sends a native transaction
|
|
185
|
-
await aa.transfer("ETH", recipient, amount);
|
|
67
|
+
import { TransferManager, BridgeContext } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
68
|
+
|
|
69
|
+
const transferManager = new TransferManager();
|
|
70
|
+
|
|
71
|
+
const context: BridgeContext = {
|
|
72
|
+
sourceChain: "Base",
|
|
73
|
+
destChain: "Optimism",
|
|
74
|
+
sourceToken: "USDC",
|
|
75
|
+
destToken: "USDC",
|
|
76
|
+
amount: "10.5", // Human readable string
|
|
77
|
+
recipient: "0xRecipient...",
|
|
78
|
+
senderAddress: "0xSender...",
|
|
79
|
+
facilitatorPrivateKey: "0x..." // For CCTP/Near verification usage (Backend)
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const result = await transferManager.execute(context);
|
|
83
|
+
|
|
84
|
+
if (result.success) {
|
|
85
|
+
if (result.transactionHash === "DIRECT_TRANSFER_REQUIRED") {
|
|
86
|
+
// Signal to Client: Execute direct transfer on same chain!
|
|
87
|
+
console.log("Execute local transfer:", result.data);
|
|
88
|
+
} else {
|
|
89
|
+
// Cross-chain initiated
|
|
90
|
+
console.log("Bridge Tx:", result.transactionHash);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
console.error("Error:", result.errorReason);
|
|
94
|
+
}
|
|
186
95
|
```
|
|
187
96
|
|
|
188
|
-
|
|
189
|
-
// The SDK detects the "ETH" symbol and sends a native transaction
|
|
190
|
-
await aa.transfer("ETH", recipient, amount);
|
|
191
|
-
```
|
|
97
|
+
## 🛠️ Supported Chains
|
|
192
98
|
|
|
193
|
-
|
|
99
|
+
The SDK exports pre-configured objects:
|
|
194
100
|
|
|
195
|
-
|
|
101
|
+
- `BASE_MAINNET`
|
|
102
|
+
- `BASE_SEPOLIA`
|
|
103
|
+
- `OPTIMISM_MAINNET`
|
|
104
|
+
- `GNOSIS_MAINNET`
|
|
196
105
|
|
|
197
106
|
```typescript
|
|
198
|
-
|
|
199
|
-
const txHash = await aa.deposit(100000000000000000n);
|
|
107
|
+
import { GNOSIS_MAINNET } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
200
108
|
```
|
|
201
109
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
### Error Decoding
|
|
205
|
-
The SDK now automatically tries to decode cryptic "0x..." errors from the EntryPoint into readable messages like:
|
|
206
|
-
- `Smart Account Error: Transfer amount exceeds balance`
|
|
207
|
-
- `Smart Account: Native transfer failed`
|
|
110
|
+
## 📄 API Reference
|
|
208
111
|
|
|
209
|
-
###
|
|
112
|
+
### AccountAbstraction
|
|
210
113
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
114
|
+
| Method | Description |
|
|
115
|
+
|--------|-------------|
|
|
116
|
+
| `connect(privateKey?)` | Connects to wallet and calculates Smart Account address |
|
|
117
|
+
| `isAccountDeployed()` | Checks if Smart Account exists on-chain |
|
|
118
|
+
| `deployAccount()` | Deploys the Smart Account (usually updated automatically on first tx) |
|
|
119
|
+
| `transfer(token, to, amount)` | Simplest way to send tokens or ETH |
|
|
120
|
+
| `sendTransaction(tx)` | Send a raw transaction (target, value, data) |
|
|
121
|
+
| `sendBatchTransaction(txs)` | Send multiple transactions in one UserOp (Atomic) |
|
|
122
|
+
| `approveToken(token, spender, amount)` | Approve a spender (handles gasless logic if needed) |
|
|
123
|
+
| `getSmartAccountAddress(owner)` | Get deterministic address for any EOA |
|
|
220
124
|
|
|
221
125
|
### Utilities
|
|
222
126
|
|
|
223
127
|
```typescript
|
|
224
|
-
|
|
225
|
-
const nonce = await aa.getNonce();
|
|
226
|
-
|
|
227
|
-
// Get UserOp Hash (for manual signing or verification)
|
|
228
|
-
const hash = aa.getUserOpHash(userOp);
|
|
229
|
-
```
|
|
128
|
+
import { CHAIN_CONFIGS } from "@1llet.xyz/erc4337-gasless-sdk";
|
|
230
129
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
The SDK exports useful constants and ABIs so you don't need to redefine them:
|
|
234
|
-
|
|
235
|
-
```typescript
|
|
236
|
-
import {
|
|
237
|
-
DEPLOYMENTS,
|
|
238
|
-
erc20Abi,
|
|
239
|
-
factoryAbi,
|
|
240
|
-
entryPointAbi
|
|
241
|
-
} from "@1llet.xyz/erc4337-gasless-sdk";
|
|
242
|
-
|
|
243
|
-
// Access known contract addresses
|
|
244
|
-
const usdcOnBase = DEPLOYMENTS[8453].usdc;
|
|
245
|
-
|
|
246
|
-
// Use ABIs directly
|
|
247
|
-
console.log(erc20Abi);
|
|
130
|
+
// Access config by Chain ID
|
|
131
|
+
const config = CHAIN_CONFIGS[8453];
|
|
248
132
|
```
|
|
249
133
|
|
|
250
|
-
##
|
|
134
|
+
## License
|
|
251
135
|
|
|
252
136
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -79,17 +79,10 @@ declare class AccountAbstraction {
|
|
|
79
79
|
* Get the Smart Account address for an owner
|
|
80
80
|
*/
|
|
81
81
|
getSmartAccountAddress(owner: Address): Promise<Address>;
|
|
82
|
-
/**
|
|
83
|
-
* Check if the Smart Account is deployed
|
|
84
|
-
*/
|
|
85
|
-
isAccountDeployed(): Promise<boolean>;
|
|
86
82
|
getTokenAddress(token: string | Address): Address;
|
|
87
83
|
getBalance(token: string | Address): Promise<bigint>;
|
|
88
84
|
getEoaBalance(token: string | Address): Promise<bigint>;
|
|
89
|
-
getUsdcBalance(): Promise<bigint>;
|
|
90
|
-
getEoaUsdcBalance(): Promise<bigint>;
|
|
91
85
|
getAllowance(token?: string | Address): Promise<bigint>;
|
|
92
|
-
deployAccount(): Promise<UserOpReceipt>;
|
|
93
86
|
sendTransaction(tx: {
|
|
94
87
|
target: Address;
|
|
95
88
|
value?: bigint;
|
|
@@ -106,7 +99,6 @@ declare class AccountAbstraction {
|
|
|
106
99
|
* Approve a token for the Smart Account
|
|
107
100
|
*/
|
|
108
101
|
approveToken(token: Address, spender: Address, amount?: bigint): Promise<Hash | "NOT_NEEDED">;
|
|
109
|
-
buildUserOperationBatch(transactions: any[]): Promise<UserOperation>;
|
|
110
102
|
signUserOperation(userOp: UserOperation): Promise<UserOperation>;
|
|
111
103
|
sendUserOperation(userOp: UserOperation): Promise<Hash>;
|
|
112
104
|
waitForUserOperation(hash: Hash, timeout?: number): Promise<UserOpReceipt>;
|
|
@@ -130,7 +122,6 @@ declare global {
|
|
|
130
122
|
|
|
131
123
|
declare class BundlerClient {
|
|
132
124
|
private bundlerUrl;
|
|
133
|
-
private chainId;
|
|
134
125
|
private entryPointAddress;
|
|
135
126
|
constructor(config: ChainConfig, entryPointAddress: Address);
|
|
136
127
|
private call;
|
|
@@ -282,9 +273,9 @@ declare const erc20Abi: readonly [{
|
|
|
282
273
|
declare const CHAIN_ID_TO_KEY: Record<string, string>;
|
|
283
274
|
|
|
284
275
|
declare const ChainKeyEnum: z.ZodEnum<{
|
|
285
|
-
Base: "Base";
|
|
286
276
|
Optimism: "Optimism";
|
|
287
277
|
Arbitrum: "Arbitrum";
|
|
278
|
+
Base: "Base";
|
|
288
279
|
Unichain: "Unichain";
|
|
289
280
|
Polygon: "Polygon";
|
|
290
281
|
Avalanche: "Avalanche";
|
package/dist/index.d.ts
CHANGED
|
@@ -79,17 +79,10 @@ declare class AccountAbstraction {
|
|
|
79
79
|
* Get the Smart Account address for an owner
|
|
80
80
|
*/
|
|
81
81
|
getSmartAccountAddress(owner: Address): Promise<Address>;
|
|
82
|
-
/**
|
|
83
|
-
* Check if the Smart Account is deployed
|
|
84
|
-
*/
|
|
85
|
-
isAccountDeployed(): Promise<boolean>;
|
|
86
82
|
getTokenAddress(token: string | Address): Address;
|
|
87
83
|
getBalance(token: string | Address): Promise<bigint>;
|
|
88
84
|
getEoaBalance(token: string | Address): Promise<bigint>;
|
|
89
|
-
getUsdcBalance(): Promise<bigint>;
|
|
90
|
-
getEoaUsdcBalance(): Promise<bigint>;
|
|
91
85
|
getAllowance(token?: string | Address): Promise<bigint>;
|
|
92
|
-
deployAccount(): Promise<UserOpReceipt>;
|
|
93
86
|
sendTransaction(tx: {
|
|
94
87
|
target: Address;
|
|
95
88
|
value?: bigint;
|
|
@@ -106,7 +99,6 @@ declare class AccountAbstraction {
|
|
|
106
99
|
* Approve a token for the Smart Account
|
|
107
100
|
*/
|
|
108
101
|
approveToken(token: Address, spender: Address, amount?: bigint): Promise<Hash | "NOT_NEEDED">;
|
|
109
|
-
buildUserOperationBatch(transactions: any[]): Promise<UserOperation>;
|
|
110
102
|
signUserOperation(userOp: UserOperation): Promise<UserOperation>;
|
|
111
103
|
sendUserOperation(userOp: UserOperation): Promise<Hash>;
|
|
112
104
|
waitForUserOperation(hash: Hash, timeout?: number): Promise<UserOpReceipt>;
|
|
@@ -130,7 +122,6 @@ declare global {
|
|
|
130
122
|
|
|
131
123
|
declare class BundlerClient {
|
|
132
124
|
private bundlerUrl;
|
|
133
|
-
private chainId;
|
|
134
125
|
private entryPointAddress;
|
|
135
126
|
constructor(config: ChainConfig, entryPointAddress: Address);
|
|
136
127
|
private call;
|
|
@@ -282,9 +273,9 @@ declare const erc20Abi: readonly [{
|
|
|
282
273
|
declare const CHAIN_ID_TO_KEY: Record<string, string>;
|
|
283
274
|
|
|
284
275
|
declare const ChainKeyEnum: z.ZodEnum<{
|
|
285
|
-
Base: "Base";
|
|
286
276
|
Optimism: "Optimism";
|
|
287
277
|
Arbitrum: "Arbitrum";
|
|
278
|
+
Base: "Base";
|
|
288
279
|
Unichain: "Unichain";
|
|
289
280
|
Polygon: "Polygon";
|
|
290
281
|
Avalanche: "Avalanche";
|