@dag-kit/kit 1.0.0 → 1.0.4-alpha.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.
@@ -0,0 +1,145 @@
1
+ // import {
2
+ // createPublicClient,
3
+ // createWalletClient,
4
+ // encodeFunctionData,
5
+ // formatEther,
6
+ // http,
7
+ // parseEther,
8
+ // parseGwei,
9
+ // } from "viem";
10
+ // import { awakening } from "../chains";
11
+ // import { privateKeyToAccount } from "viem/accounts";
12
+ // import { entryPoint06Address } from "viem/account-abstraction";
13
+ // import { toSimpleSmartAccount } from "permissionless/accounts";
14
+ // import { createSmartAccountClient } from "permissionless";
15
+ // import { createPimlicoClient } from "permissionless/clients/pimlico";
16
+ // import { abi } from "./contract";
17
+
18
+ // const { bundler_rpc, chain_config } = awakening;
19
+ // const FACTORY_ADDRESS = "0x8FaB6DF00085eb05D5F2C1FA46a6E539587ae3f3";
20
+ // const adminKey =
21
+ // "0x6b0f66a03b67d7b9eaa6c31123ffe5bf2ee58eb40ab86c8a14d6f1294838b0c8";
22
+
23
+ // const publicClient = createPublicClient({
24
+ // chain: awakening.chain_config,
25
+ // transport: http(awakening.chain_config.rpcUrls.default.http[0]),
26
+ // });
27
+
28
+ // const walletClient = createWalletClient({
29
+ // account: privateKeyToAccount(adminKey),
30
+ // chain: chain_config,
31
+ // transport: http(chain_config.rpcUrls.default.http[0]),
32
+ // });
33
+
34
+ // const account = await toSimpleSmartAccount({
35
+ // client: publicClient,
36
+ // owner: privateKeyToAccount(adminKey),
37
+ // factoryAddress: FACTORY_ADDRESS,
38
+ // entryPoint: {
39
+ // address: entryPoint06Address,
40
+ // version: "0.6",
41
+ // },
42
+ // index: 100n,
43
+ // });
44
+
45
+ // console.log("Account Address: %s", account.address);
46
+ // // Check if account is deployed
47
+ // let code = await publicClient.getCode({
48
+ // address: account.address,
49
+ // });
50
+
51
+ // let isDeployed = code && code !== "0x";
52
+ // console.log(
53
+ // `Deployment Status: ${isDeployed ? "✅ Deployed" : "⚠️ Not deployed"}`
54
+ // );
55
+
56
+ // if (!isDeployed) {
57
+ // const fundTx = await walletClient.sendTransaction({
58
+ // to: account.address,
59
+ // value: parseEther("10"),
60
+ // chain: undefined,
61
+ // });
62
+
63
+ // await publicClient.waitForTransactionReceipt({
64
+ // hash: fundTx,
65
+ // timeout: 120_000,
66
+ // pollingInterval: 5_000,
67
+ // });
68
+ // console.log("Account funded");
69
+ // }
70
+
71
+ // console.log("\n==== Sending Test UserOperation =====");
72
+ // const cd = encodeFunctionData({
73
+ // abi,
74
+ // functionName: "increment",
75
+ // args: [],
76
+ // });
77
+
78
+ // const smartAccountClient = createSmartAccountClient({
79
+ // bundlerTransport: http(bundler_rpc),
80
+ // chain: awakening,
81
+ // account,
82
+ // });
83
+
84
+ // // Simple test: send 0 ETH to self (just to test the flow)
85
+ // try {
86
+ // // Get current gas prices from the bundler
87
+ // const dagClient = createPimlicoClient({
88
+ // transport: http(bundler_rpc),
89
+ // entryPoint: {
90
+ // address: entryPoint06Address,
91
+ // version: "0.6",
92
+ // },
93
+ // });
94
+
95
+ // const balance = await publicClient.getBalance({
96
+ // address: account.address,
97
+ // });
98
+ // const balanceInETH = Number(balance) / 1e18;
99
+
100
+ // const gasPrices = await dagClient.getUserOperationGasPrice();
101
+ // console.log("Using gas prices:", gasPrices.fast);
102
+
103
+ // const SAFE_GAS_PRICE = parseGwei("50"); // 100 Gwei
104
+
105
+ // console.log("SAFE gas prices:", formatEther(SAFE_GAS_PRICE));
106
+
107
+ // const txHash = await smartAccountClient.sendTransaction({
108
+ // to: "0x8FaB6DF00085eb05D5F2C1FA46a6E539587ae3f3", // Send to self
109
+ // value: 0n,
110
+ // data: cd,
111
+ // maxFeePerGas: SAFE_GAS_PRICE,
112
+ // maxPriorityFeePerGas: SAFE_GAS_PRICE,
113
+ // // Keep your high limits
114
+ // callGasLimit: 150000n,
115
+ // verificationGasLimit: 500000n, // Bumped for safety
116
+ // preVerificationGas: 100000n,
117
+ // });
118
+
119
+ // console.log(`\n✅ Success!`);
120
+ // console.log(`UserOperation Hash: ${txHash}`);
121
+ // console.log(`Transaction: https://awakening.bdagscan.com/tx/${txHash}`);
122
+
123
+ // // Wait a moment for the transaction to be included
124
+ // console.log("\nWaiting for transaction to be mined...");
125
+ // await new Promise((resolve) => setTimeout(resolve, 5000));
126
+
127
+ // const newBalance = await publicClient.getBalance({
128
+ // address: account.address,
129
+ // });
130
+ // const newBalanceInETH = Number(newBalance) / 1e18;
131
+ // console.log(`\nFinal Balance: ${newBalanceInETH} ETH`);
132
+ // console.log(`Gas Cost: ${balanceInETH - newBalanceInETH} ETH`);
133
+
134
+ // console.log("\n🎉 Account Abstraction is working on Awakening!");
135
+ // console.log(
136
+ // "This proves your setup is correct - the issue is specific to Awakening testnet."
137
+ // );
138
+ // } catch (error: any) {
139
+ // console.error("\n❌ Transaction failed:");
140
+ // console.error(error.message);
141
+
142
+ // if (error.details) {
143
+ // console.error("\nDetails:", error.details);
144
+ // }
145
+ // }
@@ -14,6 +14,8 @@ import {
14
14
  type Address,
15
15
  encodeFunctionData,
16
16
  parseEther,
17
+ Client,
18
+ ByteArray,
17
19
  } from "viem";
18
20
  import { privateKeyToAccount } from "viem/accounts";
19
21
  import { toSimpleSmartAccount } from "permissionless/accounts";
@@ -25,7 +27,8 @@ import {
25
27
  SmartAccountConfig,
26
28
  SendUserOperationParams,
27
29
  UserOperationReceipt,
28
- } from "../types";
30
+ } from "../types.js";
31
+ import { ISigner } from "../../signers/types.js";
29
32
 
30
33
  // ==============================================================================
31
34
  // Main SDK Class
@@ -33,13 +36,12 @@ import {
33
36
 
34
37
  export class DagAAClient {
35
38
  private config: DagAAConfig;
36
- private publicClient: ReturnType<typeof createPublicClient>;
37
- private walletClient: ReturnType<typeof createWalletClient>;
38
- private bundlerClient: ReturnType<typeof createPimlicoClient> | null = null;
39
+ private publicClient: any | null;
40
+ private walletClient: any | null;
41
+ private bundlerClient: any | null = null;
39
42
  private smartAccount: any | null = null;
40
- private smartAccountClient: ReturnType<
41
- typeof createSmartAccountClient
42
- > | null = null;
43
+ private paymasterClient: any | null = null;
44
+ private smartAccountClient: any | null = null;
43
45
 
44
46
  constructor(config: DagAAConfig) {
45
47
  this.config = {
@@ -56,8 +58,112 @@ export class DagAAClient {
56
58
  chain: config.chain,
57
59
  transport: http(config.rpcUrl),
58
60
  });
61
+
62
+ // Initialize paymaster client if URL provided
63
+ if (config.paymasterUrl) {
64
+ this.paymasterClient = this.createPaymasterClient(config.paymasterUrl);
65
+ }
59
66
  }
67
+ // ==============================================================================
68
+ // Paymaster Client (Fixed Serialization)
69
+ // ==============================================================================
70
+
71
+ private createPaymasterClient(paymasterUrl: string) {
72
+ // 1. Define a robust serializer that handles nested BigInts automatically
73
+ const stringify = (data: any) => {
74
+ return JSON.stringify(data, (_, value) =>
75
+ typeof value === "bigint" ? `0x${value.toString(16)}` : value
76
+ );
77
+ };
78
+
79
+ return {
80
+ /**
81
+ * Get paymaster stub data for gas estimation
82
+ */
83
+ async getPaymasterStubData(
84
+ userOp: any,
85
+ entryPoint: Address
86
+ ): Promise<any> {
87
+ try {
88
+ const response = await fetch(paymasterUrl, {
89
+ method: "POST",
90
+ headers: { "Content-Type": "application/json" },
91
+ // 👇 Use the robust stringify helper
92
+ body: stringify({
93
+ jsonrpc: "2.0",
94
+ id: 1,
95
+ method: "pm_getPaymasterStubData",
96
+ params: [userOp, entryPoint, {}],
97
+ }),
98
+ });
99
+
100
+ const data = await response.json();
101
+ if (data.error) throw new Error(data.error.message);
102
+
103
+ return data.result;
104
+ } catch (error) {
105
+ console.warn("Failed to get paymaster stub data:", error);
106
+ // ⚠️ If this fails, the UserOp usually fails with AA21
107
+ return { paymasterAndData: "0x" };
108
+ }
109
+ },
110
+
111
+ /**
112
+ * Get paymaster data for actual transaction
113
+ */
114
+ async getPaymasterData(userOp: any, entryPoint: Address): Promise<any> {
115
+ try {
116
+ const response = await fetch(paymasterUrl, {
117
+ method: "POST",
118
+ headers: { "Content-Type": "application/json" },
119
+ body: stringify({
120
+ jsonrpc: "2.0",
121
+ id: 1,
122
+ method: "pm_getPaymasterData",
123
+ params: [userOp, entryPoint, {}],
124
+ }),
125
+ });
126
+
127
+ const data = await response.json();
128
+ if (data.error) throw new Error(data.error.message);
129
+
130
+ return data.result;
131
+ } catch (error) {
132
+ console.warn("Failed to get paymaster data:", error);
133
+ return null;
134
+ }
135
+ },
60
136
 
137
+ /**
138
+ * Sponsor user operation
139
+ */
140
+ async sponsorUserOperation(
141
+ userOp: any,
142
+ entryPoint: Address
143
+ ): Promise<any> {
144
+ try {
145
+ const response = await fetch(paymasterUrl, {
146
+ method: "POST",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: stringify({
149
+ jsonrpc: "2.0",
150
+ id: 1,
151
+ method: "pm_sponsorUserOperation",
152
+ params: [userOp, entryPoint, {}],
153
+ }),
154
+ });
155
+
156
+ const data = await response.json();
157
+ if (data.error) throw new Error(data.error.message);
158
+
159
+ return data.result;
160
+ } catch (error) {
161
+ console.warn("Failed to sponsor user operation:", error);
162
+ throw error;
163
+ }
164
+ },
165
+ };
166
+ }
61
167
  // ==============================================================================
62
168
  // Smart Account Management
63
169
  // ==============================================================================
@@ -65,30 +171,33 @@ export class DagAAClient {
65
171
  async connectSmartAccount(
66
172
  accountConfig: SmartAccountConfig
67
173
  ): Promise<Address> {
68
- const owner = privateKeyToAccount(accountConfig.owner);
174
+ const { signer, accountAddress } = accountConfig;
69
175
 
70
- const signingClient = createWalletClient({
71
- account: owner,
72
- chain: this.config.chain,
73
- transport: http(this.config.rpcUrl),
74
- });
176
+ const isReady = await signer.isReady();
177
+ if (!isReady) {
178
+ throw new Error("Signer is not ready. Ensure wallet is connected.");
179
+ }
180
+
181
+ const owner = await signer.getAccount();
182
+
183
+ const signingClient = await signer.getWalletClient();
75
184
 
76
- if (accountConfig.accountAddress) {
185
+ if (accountAddress) {
77
186
  // Use existing account
78
187
  this.smartAccount = await toSimpleSmartAccount({
79
- client: signingClient,
188
+ client: signingClient as unknown as Client,
80
189
  owner: owner,
81
190
  factoryAddress: this.config.factoryAddress,
82
191
  entryPoint: {
83
192
  address: this.config.entryPointAddress!,
84
193
  version: "0.6",
85
194
  },
86
- address: accountConfig.accountAddress,
195
+ address: accountAddress,
87
196
  });
88
197
  } else {
89
198
  // Create new account
90
199
  this.smartAccount = await toSimpleSmartAccount({
91
- client: signingClient,
200
+ client: signingClient as unknown as Client,
92
201
  owner: owner,
93
202
  factoryAddress: this.config.factoryAddress,
94
203
  entryPoint: {
@@ -107,12 +216,84 @@ export class DagAAClient {
107
216
  },
108
217
  });
109
218
 
110
- // Create smart account client
111
- this.smartAccountClient = createSmartAccountClient({
219
+ // Create smart account client with optional paymaster
220
+ const clientConfig: any = {
112
221
  bundlerTransport: http(this.config.bundlerUrl),
113
222
  chain: this.config.chain,
114
223
  account: this.smartAccount,
115
- });
224
+ };
225
+
226
+ // Add paymaster if configured
227
+ if (this.paymasterClient) {
228
+ clientConfig.paymaster = {
229
+ getPaymasterData: async (userOperation: any) => {
230
+ console.log("🎫 Requesting paymaster sponsorship...");
231
+ console.log("UserOp sender:", userOperation.sender);
232
+
233
+ try {
234
+ const result = await this.paymasterClient!.sponsorUserOperation(
235
+ userOperation,
236
+ this.config.entryPointAddress!
237
+ );
238
+
239
+ console.log("Paymaster result:", result);
240
+
241
+ if (result && result.paymasterAndData) {
242
+ console.log("✅ Paymaster sponsorship approved!");
243
+ console.log("PaymasterAndData:", result.paymasterAndData);
244
+ return {
245
+ paymasterAndData: result.paymasterAndData,
246
+ ...(result.preVerificationGas && {
247
+ preVerificationGas: BigInt(result.preVerificationGas),
248
+ }),
249
+ ...(result.verificationGasLimit && {
250
+ verificationGasLimit: BigInt(result.verificationGasLimit),
251
+ }),
252
+ ...(result.callGasLimit && {
253
+ callGasLimit: BigInt(result.callGasLimit),
254
+ }),
255
+ };
256
+ } else {
257
+ console.error("❌ No paymasterAndData in response:", result);
258
+ throw new Error("No paymaster data returned");
259
+ }
260
+ } catch (error) {
261
+ console.error("❌ Paymaster sponsorship failed:", error);
262
+ throw error;
263
+ }
264
+ },
265
+
266
+ getPaymasterStubData: async (userOperation: any) => {
267
+ console.log("📝 Getting paymaster stub data for gas estimation...");
268
+
269
+ try {
270
+ const result = await this.paymasterClient!.getPaymasterStubData(
271
+ userOperation,
272
+ this.config.entryPointAddress!
273
+ );
274
+
275
+ console.log("Stub data result:", result);
276
+
277
+ if (result && result.paymasterAndData) {
278
+ console.log("✅ Got paymaster stub data");
279
+ return {
280
+ paymasterAndData: result.paymasterAndData,
281
+ };
282
+ }
283
+ } catch (error) {
284
+ console.warn("⚠️ Failed to get paymaster stub data:", error);
285
+ }
286
+
287
+ // Return default stub if fails
288
+ console.log("⚠️ Using default stub data");
289
+ return {
290
+ paymasterAndData: "0x",
291
+ };
292
+ },
293
+ };
294
+ }
295
+
296
+ this.smartAccountClient = createSmartAccountClient(clientConfig);
116
297
 
117
298
  console.log(`✅ Connected to smart account: ${this.smartAccount.address}`);
118
299
  return this.smartAccount.address;
@@ -192,9 +373,9 @@ export class DagAAClient {
192
373
  value = 0n,
193
374
  maxFeePerGas,
194
375
  maxPriorityFeePerGas,
195
- callGasLimit = 150000n,
196
- verificationGasLimit = 300000n,
197
- preVerificationGas = 100000n,
376
+ callGasLimit,
377
+ verificationGasLimit,
378
+ preVerificationGas,
198
379
  } = params;
199
380
 
200
381
  // Get gas prices if not provided
@@ -219,7 +400,7 @@ export class DagAAClient {
219
400
  ` Gas: ${gasPrices.maxFeePerGas} / ${gasPrices.maxPriorityFeePerGas}`
220
401
  );
221
402
 
222
- const userOpHash = await this.smartAccountClient.sendTransaction({
403
+ const txOptions: any = {
223
404
  calls: [
224
405
  {
225
406
  to: target,
@@ -229,10 +410,16 @@ export class DagAAClient {
229
410
  ],
230
411
  maxFeePerGas: gasPrices.maxFeePerGas,
231
412
  maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas,
232
- callGasLimit,
233
- verificationGasLimit,
234
- preVerificationGas,
235
- });
413
+ };
414
+
415
+ // Add optional gas limits if provided
416
+ if (callGasLimit) txOptions.callGasLimit = callGasLimit;
417
+ if (verificationGasLimit)
418
+ txOptions.verificationGasLimit = verificationGasLimit;
419
+ if (preVerificationGas) txOptions.preVerificationGas = preVerificationGas;
420
+
421
+ // Send transaction - paymaster is automatically called if configured
422
+ const userOpHash = await this.smartAccountClient.sendTransaction(txOptions);
236
423
 
237
424
  console.log(`✅ UserOperation sent: ${userOpHash}`);
238
425
  return userOpHash;
@@ -326,8 +513,21 @@ export class DagAAClient {
326
513
  console.log(`Funding account with ${amount} wei...`);
327
514
 
328
515
  const hash = await client.sendTransaction({
516
+ account: signer, // ✅ Add this line
329
517
  to: this.smartAccount.address,
330
518
  value: amount,
519
+ kzg: {
520
+ blobToKzgCommitment: function (blob: ByteArray): ByteArray {
521
+ throw new Error("Function not implemented.");
522
+ },
523
+ computeBlobKzgProof: function (
524
+ blob: ByteArray,
525
+ commitment: ByteArray
526
+ ): ByteArray {
527
+ throw new Error("Function not implemented.");
528
+ },
529
+ },
530
+ chain: undefined,
331
531
  });
332
532
 
333
533
  console.log(`✅ Funded: ${hash}`);
@@ -363,14 +563,3 @@ export function createDagAAClient(config: DagAAConfig): DagAAClient {
363
563
  export function parseDAG(amount: string): bigint {
364
564
  return parseEther(amount);
365
565
  }
366
-
367
- // ==============================================================================
368
- // Export Types
369
- // ==============================================================================
370
-
371
- // export type {
372
- // DagAAConfig,
373
- // SmartAccountConfig,
374
- // SendUserOperationParams,
375
- // UserOperationReceipt,
376
- // };