@dag-kit/kit 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.
- package/dist/esm/clients/actions/example2.js +24 -21
- package/dist/esm/clients/actions/main.js +167 -18
- package/dist/esm/clients/actions/testPaymasterService.js +88 -0
- package/dist/esm/clients/chains.js +5 -0
- package/dist/esm/exports/index.js +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/types/clients/actions/contract.d.ts +12 -0
- package/dist/types/clients/actions/contract.d.ts.map +1 -0
- package/dist/types/clients/actions/example.d.ts +2 -0
- package/dist/types/clients/actions/example.d.ts.map +1 -0
- package/dist/types/clients/actions/example2.d.ts +2 -0
- package/dist/types/clients/actions/example2.d.ts.map +1 -0
- package/dist/types/clients/actions/index.d.ts +1 -0
- package/dist/types/clients/actions/index.d.ts.map +1 -0
- package/dist/types/clients/actions/main.d.ts +40 -0
- package/dist/types/clients/actions/main.d.ts.map +1 -0
- package/dist/types/clients/actions/test.d.ts +1 -0
- package/dist/types/clients/actions/test.d.ts.map +1 -0
- package/dist/types/clients/actions/testPaymasterService.d.ts +2 -0
- package/dist/types/clients/actions/testPaymasterService.d.ts.map +1 -0
- package/dist/types/clients/chains.d.ts +81 -0
- package/dist/types/clients/chains.d.ts.map +1 -0
- package/dist/types/clients/types.d.ts +31 -0
- package/dist/types/clients/types.d.ts.map +1 -0
- package/dist/types/exports/index.d.ts +4 -0
- package/dist/types/exports/index.d.ts.map +1 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/types/version.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/clients/actions/example2.ts +26 -23
- package/src/clients/actions/main.ts +194 -22
- package/src/clients/actions/test.ts +210 -0
- package/src/clients/actions/testPaymasterService.ts +94 -0
- package/src/clients/chains.ts +6 -1
- package/src/clients/types.ts +1 -0
- package/src/exports/index.ts +2 -0
- package/src/version.ts +3 -0
- package/dist/esm/script.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dag-kit/kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Abstract",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"exports": {
|
|
26
26
|
".": {
|
|
27
27
|
"types": "./dist/types/exports/index.d.ts",
|
|
28
|
-
"
|
|
28
|
+
"default": "./dist/esm/exports/index.js",
|
|
29
29
|
"import": "./dist/esm/exports/index.js"
|
|
30
30
|
},
|
|
31
31
|
"./experimental": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
|
|
59
59
|
"scripts": {
|
|
60
60
|
"prebuild": "tsx ./inject-version.ts",
|
|
61
|
-
"build": "
|
|
61
|
+
"build": "pnpm clean && pnpm build:esm && pnpm build:types",
|
|
62
62
|
"build:esm": "tsc --project tsconfig.build.json --outDir ./dist/esm",
|
|
63
63
|
"build:types": "tsc --project tsconfig.build.json --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap",
|
|
64
64
|
"clean": "rm -rf ./dist",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { awakening } from "../chains";
|
|
2
2
|
import { createDagAAClient, parseDAG } from "./main";
|
|
3
|
+
import { generatePrivateKey } from "viem/accounts";
|
|
3
4
|
import { config as dotenvConfig } from "dotenv";
|
|
4
5
|
dotenvConfig();
|
|
5
6
|
|
|
6
7
|
const PRIVATE_KEY_2 = process.env.PRIVATE_KEY_1 as `0x${string}`;
|
|
8
|
+
const ownerPrivy = generatePrivateKey();
|
|
7
9
|
|
|
8
10
|
(async () => {
|
|
9
11
|
console.log("Sending Simple Transaction");
|
|
@@ -13,17 +15,18 @@ const PRIVATE_KEY_2 = process.env.PRIVATE_KEY_1 as `0x${string}`;
|
|
|
13
15
|
rpcUrl: "https://rpc.awakening.bdagscan.com",
|
|
14
16
|
bundlerUrl: awakening.bundler_rpc,
|
|
15
17
|
factoryAddress: "0x8FaB6DF00085eb05D5F2C1FA46a6E539587ae3f3",
|
|
18
|
+
paymasterUrl: "http://localhost:3001/rpc",
|
|
16
19
|
});
|
|
17
20
|
|
|
18
21
|
await client.connectSmartAccount({
|
|
19
22
|
owner: "0x6b0f66a03b67d7b9eaa6c31123ffe5bf2ee58eb40ab86c8a14d6f1294838b0c8",
|
|
20
|
-
accountAddress: "0xDe10aaC59f659fA154C063153AB3f7Cca1fb23A5",
|
|
23
|
+
// accountAddress: "0xDe10aaC59f659fA154C063153AB3f7Cca1fb23A5",
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
// Send 0.01 DAG to an address
|
|
24
27
|
const txHash = await client.sendUserOperation({
|
|
25
28
|
target: "0x1749be926ef79a63a285b01263f7ddc350d435e6",
|
|
26
|
-
value: parseDAG("
|
|
29
|
+
value: parseDAG("0"), // 0.01 DAG
|
|
27
30
|
maxFeePerGas: 50000000000n,
|
|
28
31
|
maxPriorityFeePerGas: 50000000000n,
|
|
29
32
|
});
|
|
@@ -33,25 +36,25 @@ const PRIVATE_KEY_2 = process.env.PRIVATE_KEY_1 as `0x${string}`;
|
|
|
33
36
|
console.log("\nš¦ Example : Batch Operations");
|
|
34
37
|
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
35
38
|
|
|
36
|
-
await client.connectSmartAccount({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Send multiple operations
|
|
42
|
-
const hashes = await client.sendBatchUserOperations([
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
]);
|
|
52
|
-
|
|
53
|
-
console.log(`Sent ${hashes.length} operations`);
|
|
54
|
-
hashes.forEach((hash, i) => {
|
|
55
|
-
|
|
56
|
-
});
|
|
39
|
+
// await client.connectSmartAccount({
|
|
40
|
+
// owner: PRIVATE_KEY_2,
|
|
41
|
+
// accountAddress: "0x7fd5385efcB7B2898933288948a9496CDc0fA8ee",
|
|
42
|
+
// });
|
|
43
|
+
|
|
44
|
+
// // Send multiple operations
|
|
45
|
+
// const hashes = await client.sendBatchUserOperations([
|
|
46
|
+
// {
|
|
47
|
+
// target: "0x1749be926ef79a63a285b01263f7ddc350d435e6",
|
|
48
|
+
// value: parseDAG("0.5"),
|
|
49
|
+
// },
|
|
50
|
+
// {
|
|
51
|
+
// target: "0x8371e519177f81b93287f750dcd06ce894c12cc5",
|
|
52
|
+
// value: parseDAG("0.5"),
|
|
53
|
+
// },
|
|
54
|
+
// ]);
|
|
55
|
+
|
|
56
|
+
// console.log(`Sent ${hashes.length} operations`);
|
|
57
|
+
// hashes.forEach((hash, i) => {
|
|
58
|
+
// console.log(` ${i + 1}. ${hash}`);
|
|
59
|
+
// });
|
|
57
60
|
})();
|
|
@@ -37,6 +37,7 @@ export class DagAAClient {
|
|
|
37
37
|
private walletClient: ReturnType<typeof createWalletClient>;
|
|
38
38
|
private bundlerClient: ReturnType<typeof createPimlicoClient> | null = null;
|
|
39
39
|
private smartAccount: any | null = null;
|
|
40
|
+
private paymasterClient: any | null = null;
|
|
40
41
|
private smartAccountClient: ReturnType<
|
|
41
42
|
typeof createSmartAccountClient
|
|
42
43
|
> | null = null;
|
|
@@ -56,8 +57,112 @@ export class DagAAClient {
|
|
|
56
57
|
chain: config.chain,
|
|
57
58
|
transport: http(config.rpcUrl),
|
|
58
59
|
});
|
|
60
|
+
|
|
61
|
+
// Initialize paymaster client if URL provided
|
|
62
|
+
if (config.paymasterUrl) {
|
|
63
|
+
this.paymasterClient = this.createPaymasterClient(config.paymasterUrl);
|
|
64
|
+
}
|
|
59
65
|
}
|
|
66
|
+
// ==============================================================================
|
|
67
|
+
// Paymaster Client (Fixed Serialization)
|
|
68
|
+
// ==============================================================================
|
|
69
|
+
|
|
70
|
+
private createPaymasterClient(paymasterUrl: string) {
|
|
71
|
+
// 1. Define a robust serializer that handles nested BigInts automatically
|
|
72
|
+
const stringify = (data: any) => {
|
|
73
|
+
return JSON.stringify(data, (_, value) =>
|
|
74
|
+
typeof value === "bigint" ? `0x${value.toString(16)}` : value
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
/**
|
|
80
|
+
* Get paymaster stub data for gas estimation
|
|
81
|
+
*/
|
|
82
|
+
async getPaymasterStubData(
|
|
83
|
+
userOp: any,
|
|
84
|
+
entryPoint: Address
|
|
85
|
+
): Promise<any> {
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(paymasterUrl, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: { "Content-Type": "application/json" },
|
|
90
|
+
// š Use the robust stringify helper
|
|
91
|
+
body: stringify({
|
|
92
|
+
jsonrpc: "2.0",
|
|
93
|
+
id: 1,
|
|
94
|
+
method: "pm_getPaymasterStubData",
|
|
95
|
+
params: [userOp, entryPoint, {}],
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const data = await response.json();
|
|
100
|
+
if (data.error) throw new Error(data.error.message);
|
|
101
|
+
|
|
102
|
+
return data.result;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.warn("Failed to get paymaster stub data:", error);
|
|
105
|
+
// ā ļø If this fails, the UserOp usually fails with AA21
|
|
106
|
+
return { paymasterAndData: "0x" };
|
|
107
|
+
}
|
|
108
|
+
},
|
|
60
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Get paymaster data for actual transaction
|
|
112
|
+
*/
|
|
113
|
+
async getPaymasterData(userOp: any, entryPoint: Address): Promise<any> {
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(paymasterUrl, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { "Content-Type": "application/json" },
|
|
118
|
+
body: stringify({
|
|
119
|
+
jsonrpc: "2.0",
|
|
120
|
+
id: 1,
|
|
121
|
+
method: "pm_getPaymasterData",
|
|
122
|
+
params: [userOp, entryPoint, {}],
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const data = await response.json();
|
|
127
|
+
if (data.error) throw new Error(data.error.message);
|
|
128
|
+
|
|
129
|
+
return data.result;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.warn("Failed to get paymaster data:", error);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Sponsor user operation
|
|
138
|
+
*/
|
|
139
|
+
async sponsorUserOperation(
|
|
140
|
+
userOp: any,
|
|
141
|
+
entryPoint: Address
|
|
142
|
+
): Promise<any> {
|
|
143
|
+
try {
|
|
144
|
+
const response = await fetch(paymasterUrl, {
|
|
145
|
+
method: "POST",
|
|
146
|
+
headers: { "Content-Type": "application/json" },
|
|
147
|
+
body: stringify({
|
|
148
|
+
jsonrpc: "2.0",
|
|
149
|
+
id: 1,
|
|
150
|
+
method: "pm_sponsorUserOperation",
|
|
151
|
+
params: [userOp, entryPoint, {}],
|
|
152
|
+
}),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const data = await response.json();
|
|
156
|
+
if (data.error) throw new Error(data.error.message);
|
|
157
|
+
|
|
158
|
+
return data.result;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.warn("Failed to sponsor user operation:", error);
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
61
166
|
// ==============================================================================
|
|
62
167
|
// Smart Account Management
|
|
63
168
|
// ==============================================================================
|
|
@@ -107,12 +212,84 @@ export class DagAAClient {
|
|
|
107
212
|
},
|
|
108
213
|
});
|
|
109
214
|
|
|
110
|
-
// Create smart account client
|
|
111
|
-
|
|
215
|
+
// Create smart account client with optional paymaster
|
|
216
|
+
const clientConfig: any = {
|
|
112
217
|
bundlerTransport: http(this.config.bundlerUrl),
|
|
113
218
|
chain: this.config.chain,
|
|
114
219
|
account: this.smartAccount,
|
|
115
|
-
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Add paymaster if configured
|
|
223
|
+
if (this.paymasterClient) {
|
|
224
|
+
clientConfig.paymaster = {
|
|
225
|
+
getPaymasterData: async (userOperation: any) => {
|
|
226
|
+
console.log("š« Requesting paymaster sponsorship...");
|
|
227
|
+
console.log("UserOp sender:", userOperation.sender);
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
const result = await this.paymasterClient!.sponsorUserOperation(
|
|
231
|
+
userOperation,
|
|
232
|
+
this.config.entryPointAddress!
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
console.log("Paymaster result:", result);
|
|
236
|
+
|
|
237
|
+
if (result && result.paymasterAndData) {
|
|
238
|
+
console.log("ā
Paymaster sponsorship approved!");
|
|
239
|
+
console.log("PaymasterAndData:", result.paymasterAndData);
|
|
240
|
+
return {
|
|
241
|
+
paymasterAndData: result.paymasterAndData,
|
|
242
|
+
...(result.preVerificationGas && {
|
|
243
|
+
preVerificationGas: BigInt(result.preVerificationGas),
|
|
244
|
+
}),
|
|
245
|
+
...(result.verificationGasLimit && {
|
|
246
|
+
verificationGasLimit: BigInt(result.verificationGasLimit),
|
|
247
|
+
}),
|
|
248
|
+
...(result.callGasLimit && {
|
|
249
|
+
callGasLimit: BigInt(result.callGasLimit),
|
|
250
|
+
}),
|
|
251
|
+
};
|
|
252
|
+
} else {
|
|
253
|
+
console.error("ā No paymasterAndData in response:", result);
|
|
254
|
+
throw new Error("No paymaster data returned");
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error("ā Paymaster sponsorship failed:", error);
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
getPaymasterStubData: async (userOperation: any) => {
|
|
263
|
+
console.log("š Getting paymaster stub data for gas estimation...");
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const result = await this.paymasterClient!.getPaymasterStubData(
|
|
267
|
+
userOperation,
|
|
268
|
+
this.config.entryPointAddress!
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
console.log("Stub data result:", result);
|
|
272
|
+
|
|
273
|
+
if (result && result.paymasterAndData) {
|
|
274
|
+
console.log("ā
Got paymaster stub data");
|
|
275
|
+
return {
|
|
276
|
+
paymasterAndData: result.paymasterAndData,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.warn("ā ļø Failed to get paymaster stub data:", error);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Return default stub if fails
|
|
284
|
+
console.log("ā ļø Using default stub data");
|
|
285
|
+
return {
|
|
286
|
+
paymasterAndData: "0x",
|
|
287
|
+
};
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
this.smartAccountClient = createSmartAccountClient(clientConfig);
|
|
116
293
|
|
|
117
294
|
console.log(`ā
Connected to smart account: ${this.smartAccount.address}`);
|
|
118
295
|
return this.smartAccount.address;
|
|
@@ -192,9 +369,9 @@ export class DagAAClient {
|
|
|
192
369
|
value = 0n,
|
|
193
370
|
maxFeePerGas,
|
|
194
371
|
maxPriorityFeePerGas,
|
|
195
|
-
callGasLimit
|
|
196
|
-
verificationGasLimit
|
|
197
|
-
preVerificationGas
|
|
372
|
+
callGasLimit,
|
|
373
|
+
verificationGasLimit,
|
|
374
|
+
preVerificationGas,
|
|
198
375
|
} = params;
|
|
199
376
|
|
|
200
377
|
// Get gas prices if not provided
|
|
@@ -219,7 +396,7 @@ export class DagAAClient {
|
|
|
219
396
|
` Gas: ${gasPrices.maxFeePerGas} / ${gasPrices.maxPriorityFeePerGas}`
|
|
220
397
|
);
|
|
221
398
|
|
|
222
|
-
const
|
|
399
|
+
const txOptions: any = {
|
|
223
400
|
calls: [
|
|
224
401
|
{
|
|
225
402
|
to: target,
|
|
@@ -229,10 +406,16 @@ export class DagAAClient {
|
|
|
229
406
|
],
|
|
230
407
|
maxFeePerGas: gasPrices.maxFeePerGas,
|
|
231
408
|
maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Add optional gas limits if provided
|
|
412
|
+
if (callGasLimit) txOptions.callGasLimit = callGasLimit;
|
|
413
|
+
if (verificationGasLimit)
|
|
414
|
+
txOptions.verificationGasLimit = verificationGasLimit;
|
|
415
|
+
if (preVerificationGas) txOptions.preVerificationGas = preVerificationGas;
|
|
416
|
+
|
|
417
|
+
// Send transaction - paymaster is automatically called if configured
|
|
418
|
+
const userOpHash = await this.smartAccountClient.sendTransaction(txOptions);
|
|
236
419
|
|
|
237
420
|
console.log(`ā
UserOperation sent: ${userOpHash}`);
|
|
238
421
|
return userOpHash;
|
|
@@ -363,14 +546,3 @@ export function createDagAAClient(config: DagAAConfig): DagAAClient {
|
|
|
363
546
|
export function parseDAG(amount: string): bigint {
|
|
364
547
|
return parseEther(amount);
|
|
365
548
|
}
|
|
366
|
-
|
|
367
|
-
// ==============================================================================
|
|
368
|
-
// Export Types
|
|
369
|
-
// ==============================================================================
|
|
370
|
-
|
|
371
|
-
// export type {
|
|
372
|
-
// DagAAConfig,
|
|
373
|
-
// SmartAccountConfig,
|
|
374
|
-
// SendUserOperationParams,
|
|
375
|
-
// UserOperationReceipt,
|
|
376
|
-
// };
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { toSimpleSmartAccount } from "permissionless/accounts";
|
|
3
|
+
import {
|
|
4
|
+
createPublicClient,
|
|
5
|
+
createWalletClient,
|
|
6
|
+
http,
|
|
7
|
+
parseEther,
|
|
8
|
+
encodeFunctionData,
|
|
9
|
+
defineChain,
|
|
10
|
+
} from "viem";
|
|
11
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
12
|
+
import { createPimlicoClient } from "permissionless/clients/pimlico";
|
|
13
|
+
import { entryPoint06Address } from "viem/account-abstraction";
|
|
14
|
+
import { createSmartAccountClient } from "permissionless";
|
|
15
|
+
import { abi } from "./contract";
|
|
16
|
+
|
|
17
|
+
// Configuration
|
|
18
|
+
const adminKey =
|
|
19
|
+
"0x5810098e367422376897bb2645c5ada5850a99aeec0505a58d38853ebd7f9f31";
|
|
20
|
+
const FACTORY_ADDRESS = "0x8FaB6DF00085eb05D5F2C1FA46a6E539587ae3f3"; // Your factory
|
|
21
|
+
const TARGET_ADDRESS = "0x7fd5385efcB7B2898933288948a9496CDc0fA8ee"; // Your desired address
|
|
22
|
+
|
|
23
|
+
// BlockDAG Awakening Testnet
|
|
24
|
+
const awakening = defineChain({
|
|
25
|
+
id: 1043,
|
|
26
|
+
name: "Awakening Testnet",
|
|
27
|
+
nativeCurrency: { decimals: 18, name: "Dag", symbol: "DAG" },
|
|
28
|
+
rpcUrls: { default: { http: ["https://relay.awakening.bdagscan.com"] } },
|
|
29
|
+
blockExplorers: {
|
|
30
|
+
default: { name: "Explorer", url: "https://awakening.bdagscan.com/" },
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const localBundler = "http://0.0.0.0:3000/";
|
|
35
|
+
|
|
36
|
+
console.log("\nš Using Your Existing Address");
|
|
37
|
+
console.log("=================================\n");
|
|
38
|
+
|
|
39
|
+
const publicClient = createPublicClient({
|
|
40
|
+
chain: awakening,
|
|
41
|
+
transport: http(awakening.rpcUrls.default.http[0]),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const walletClient = createWalletClient({
|
|
45
|
+
account: privateKeyToAccount(adminKey),
|
|
46
|
+
chain: awakening,
|
|
47
|
+
transport: http(awakening.rpcUrls.default.http[0]),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(`Target Address: ${TARGET_ADDRESS}`);
|
|
51
|
+
console.log(`Owner: ${privateKeyToAccount(adminKey).address}`);
|
|
52
|
+
console.log(`Factory: ${FACTORY_ADDRESS}\n`);
|
|
53
|
+
|
|
54
|
+
// Step 1: Create account using the specific address
|
|
55
|
+
// Since the account is already deployed, we just need to reference it
|
|
56
|
+
const account = await toSimpleSmartAccount({
|
|
57
|
+
client: publicClient,
|
|
58
|
+
owner: privateKeyToAccount(adminKey),
|
|
59
|
+
factoryAddress: FACTORY_ADDRESS,
|
|
60
|
+
entryPoint: {
|
|
61
|
+
address: entryPoint06Address,
|
|
62
|
+
version: "0.6",
|
|
63
|
+
},
|
|
64
|
+
address: TARGET_ADDRESS, // Use the existing address directly
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log("=== Smart Account Information ===");
|
|
68
|
+
console.log(`Address: ${account.address}`);
|
|
69
|
+
console.log(
|
|
70
|
+
`Explorer: https://awakening.bdagscan.com/address/${account.address}`
|
|
71
|
+
);
|
|
72
|
+
console.log("ā
Using your existing account\n");
|
|
73
|
+
|
|
74
|
+
// Check if deployed
|
|
75
|
+
const code = await publicClient.getCode({
|
|
76
|
+
address: account.address,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const isDeployed = code && code !== "0x";
|
|
80
|
+
console.log(
|
|
81
|
+
`Deployment Status: ${isDeployed ? "ā
Deployed" : "ā ļø Not deployed"}`
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Check balance
|
|
85
|
+
const balance = await publicClient.getBalance({
|
|
86
|
+
address: account.address,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const balanceInDAG = Number(balance) / 1e18;
|
|
90
|
+
console.log(`Balance: ${balanceInDAG} DAG`);
|
|
91
|
+
|
|
92
|
+
if (!isDeployed) {
|
|
93
|
+
console.log("\nā ļø Account not deployed yet.");
|
|
94
|
+
console.log("The account should already be deployed based on the explorer.");
|
|
95
|
+
console.log("If you need to deploy it, do so manually first.\n");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Step 3: Test bundler connection
|
|
99
|
+
console.log("=== Testing Bundler ===");
|
|
100
|
+
try {
|
|
101
|
+
const dagClient = createPimlicoClient({
|
|
102
|
+
transport: http(localBundler),
|
|
103
|
+
entryPoint: {
|
|
104
|
+
address: entryPoint06Address,
|
|
105
|
+
version: "0.6",
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const gasPrice = await dagClient.getUserOperationGasPrice();
|
|
110
|
+
console.log("ā
Bundler responding");
|
|
111
|
+
console.log(`Gas Price: ${gasPrice.fast.maxFeePerGas} wei\n`);
|
|
112
|
+
} catch (error: any) {
|
|
113
|
+
console.error("ā Bundler not responding:", error.message);
|
|
114
|
+
console.log("\nš” Start Alto bundler:");
|
|
115
|
+
console.log(`./alto \\
|
|
116
|
+
--entrypoints "${entryPoint06Address}" \\
|
|
117
|
+
--executor-private-keys "${adminKey}" \\
|
|
118
|
+
--utility-private-key "${adminKey}" \\
|
|
119
|
+
--rpc-url "https://relay.awakening.bdagscan.com" \\
|
|
120
|
+
--port 3000 \\
|
|
121
|
+
--safe-mode false \\
|
|
122
|
+
--dangerous-skip-user-operation-validation true`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Step 4: Send test UserOperation
|
|
127
|
+
console.log("=== Sending Test UserOperation ===");
|
|
128
|
+
|
|
129
|
+
const smartAccountClient = createSmartAccountClient({
|
|
130
|
+
bundlerTransport: http(localBundler),
|
|
131
|
+
chain: awakening,
|
|
132
|
+
account,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const cd = encodeFunctionData({
|
|
136
|
+
abi,
|
|
137
|
+
functionName: "decrement",
|
|
138
|
+
args: [],
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// Simple test: send 0 value to self
|
|
143
|
+
const txHash = await smartAccountClient.sendTransaction({
|
|
144
|
+
to: "0x692e69cA1Fe89eF72ca94B0E3a32A92835501a08",
|
|
145
|
+
value: 0n,
|
|
146
|
+
data: cd,
|
|
147
|
+
maxFeePerGas: 50000000000n, // 50 gwei
|
|
148
|
+
maxPriorityFeePerGas: 50000000000n, // 50 gwei
|
|
149
|
+
callGasLimit: 150000n,
|
|
150
|
+
verificationGasLimit: 500000n,
|
|
151
|
+
preVerificationGas: 100000n,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.log(`\nā
Success!`);
|
|
155
|
+
console.log(`UserOperation Hash: ${txHash}`);
|
|
156
|
+
console.log(`Explorer: https://awakening.bdagscan.com/tx/${txHash}`);
|
|
157
|
+
|
|
158
|
+
console.log("\nā³ Waiting for confirmation...");
|
|
159
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
160
|
+
|
|
161
|
+
const newBalance = await publicClient.getBalance({
|
|
162
|
+
address: account.address,
|
|
163
|
+
});
|
|
164
|
+
const newBalanceInDAG = Number(newBalance) / 1e18;
|
|
165
|
+
console.log(`\nFinal Balance: ${newBalanceInDAG} DAG`);
|
|
166
|
+
console.log(`Gas Cost: ${balanceInDAG - newBalanceInDAG} DAG`);
|
|
167
|
+
|
|
168
|
+
console.log("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
169
|
+
console.log("š Success! Your account is ready for reuse.");
|
|
170
|
+
console.log(` Address: ${TARGET_ADDRESS}`);
|
|
171
|
+
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
172
|
+
|
|
173
|
+
const result = await publicClient.readContract({
|
|
174
|
+
address: "0x692e69cA1Fe89eF72ca94B0E3a32A92835501a08",
|
|
175
|
+
abi: abi,
|
|
176
|
+
functionName: "getNum",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
console.log("Result is given as", result);
|
|
180
|
+
} catch (error: any) {
|
|
181
|
+
console.error("\nā Transaction failed:");
|
|
182
|
+
console.error(error.message);
|
|
183
|
+
|
|
184
|
+
if (error.message?.includes("Missing or invalid parameters")) {
|
|
185
|
+
console.log("\nā ļø This is the known Awakening RPC issue.");
|
|
186
|
+
console.log("The RPC cannot properly handle eth_call for UserOperations.");
|
|
187
|
+
console.log(
|
|
188
|
+
"\nYour setup is correct - the issue is with Awakening's RPC implementation."
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (error.details) {
|
|
193
|
+
console.log("\nDetails:", error.details);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Instructions for reuse
|
|
198
|
+
console.log("\nš¾ To reuse this address in future scripts:");
|
|
199
|
+
console.log(`
|
|
200
|
+
const account = await toSimpleSmartAccount({
|
|
201
|
+
client: publicClient,
|
|
202
|
+
owner: privateKeyToAccount(adminKey),
|
|
203
|
+
factoryAddress: "${FACTORY_ADDRESS}",
|
|
204
|
+
entryPoint: {
|
|
205
|
+
address: entryPoint06Address,
|
|
206
|
+
version: "0.6",
|
|
207
|
+
},
|
|
208
|
+
address: "${TARGET_ADDRESS}", // Your existing account
|
|
209
|
+
});
|
|
210
|
+
`);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Test if paymaster service is working
|
|
2
|
+
|
|
3
|
+
async function testPaymasterService() {
|
|
4
|
+
const PAYMASTER_URL = "http://localhost:3001/rpc";
|
|
5
|
+
|
|
6
|
+
console.log("Testing paymaster service...");
|
|
7
|
+
|
|
8
|
+
// Test 1: Health check
|
|
9
|
+
try {
|
|
10
|
+
const healthResponse = await fetch("http://localhost:3001/health");
|
|
11
|
+
const health = await healthResponse.json();
|
|
12
|
+
console.log("ā
Health check passed:", health);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error("ā Health check failed:", error);
|
|
15
|
+
console.error("Is the paymaster service running? Run: pnpm start");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Test 2: Get paymaster info
|
|
20
|
+
try {
|
|
21
|
+
const infoResponse = await fetch("http://localhost:3001/info");
|
|
22
|
+
const info = await infoResponse.json();
|
|
23
|
+
console.log("ā
Paymaster info:", info);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error("ā Failed to get paymaster info:", error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Test 3: Test pm_getPaymasterStubData
|
|
29
|
+
const mockUserOp = {
|
|
30
|
+
sender: "0xCa28afE1e9Fb8B9AF996c97F3dc291bE54EAEe4E",
|
|
31
|
+
nonce: "0x0",
|
|
32
|
+
initCode: "0x",
|
|
33
|
+
callData: "0x",
|
|
34
|
+
callGasLimit: "0x30d40",
|
|
35
|
+
verificationGasLimit: "0x30d40",
|
|
36
|
+
preVerificationGas: "0x30d40",
|
|
37
|
+
maxFeePerGas: "0xba43b7400",
|
|
38
|
+
maxPriorityFeePerGas: "0xba43b7400",
|
|
39
|
+
paymasterAndData: "0x",
|
|
40
|
+
signature: "0x",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(PAYMASTER_URL, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: { "Content-Type": "application/json" },
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
jsonrpc: "2.0",
|
|
49
|
+
id: 1,
|
|
50
|
+
method: "pm_getPaymasterStubData",
|
|
51
|
+
params: [mockUserOp, "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", {}],
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const data = await response.json();
|
|
56
|
+
|
|
57
|
+
if (data.error) {
|
|
58
|
+
console.error("ā pm_getPaymasterStubData failed:", data.error);
|
|
59
|
+
} else {
|
|
60
|
+
console.log("ā
pm_getPaymasterStubData success:", data.result);
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error("ā pm_getPaymasterStubData request failed:", error);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Test 4: Test pm_sponsorUserOperation
|
|
67
|
+
try {
|
|
68
|
+
const response = await fetch(PAYMASTER_URL, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "Content-Type": "application/json" },
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
jsonrpc: "2.0",
|
|
73
|
+
id: 1,
|
|
74
|
+
method: "pm_sponsorUserOperation",
|
|
75
|
+
params: [mockUserOp, "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", {}],
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const data = await response.json();
|
|
80
|
+
|
|
81
|
+
if (data.error) {
|
|
82
|
+
console.error("ā pm_sponsorUserOperation failed:", data.error);
|
|
83
|
+
} else {
|
|
84
|
+
console.log("ā
pm_sponsorUserOperation success:");
|
|
85
|
+
console.log(" paymasterAndData:", data.result.paymasterAndData);
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("ā pm_sponsorUserOperation request failed:", error);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log("\nā
Paymaster tests complete!");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
testPaymasterService().catch(console.error);
|
package/src/clients/chains.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineChain } from "viem";
|
|
2
|
-
|
|
2
|
+
import { arbitrumSepolia } from "viem/chains";
|
|
3
3
|
const awakening_ = defineChain({
|
|
4
4
|
id: 1043,
|
|
5
5
|
name: "Awakening Testnet",
|
|
@@ -14,3 +14,8 @@ export const awakening = {
|
|
|
14
14
|
bundler_rpc: "http://0.0.0.0:3000/",
|
|
15
15
|
chain_config: awakening_,
|
|
16
16
|
};
|
|
17
|
+
|
|
18
|
+
export const arbitrumSep = {
|
|
19
|
+
bundler_rpc: "http://0.0.0.0:3001/",
|
|
20
|
+
chain_config: arbitrumSepolia,
|
|
21
|
+
};
|