@dag-kit/kit 1.0.0

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,376 @@
1
+ // ==============================================================================
2
+ // DAG AA SDK - BlockDAG Account Abstraction SDK
3
+ // Inspired by Alchemy AA SDK
4
+ // ==============================================================================
5
+
6
+ import {
7
+ createPublicClient,
8
+ createWalletClient,
9
+ http,
10
+ type Chain,
11
+ type Transport,
12
+ type Account,
13
+ type Hash,
14
+ type Address,
15
+ encodeFunctionData,
16
+ parseEther,
17
+ } from "viem";
18
+ import { privateKeyToAccount } from "viem/accounts";
19
+ import { toSimpleSmartAccount } from "permissionless/accounts";
20
+ import { createPimlicoClient } from "permissionless/clients/pimlico";
21
+ import { entryPoint06Address } from "viem/account-abstraction";
22
+ import { createSmartAccountClient } from "permissionless";
23
+ import {
24
+ DagAAConfig,
25
+ SmartAccountConfig,
26
+ SendUserOperationParams,
27
+ UserOperationReceipt,
28
+ } from "../types";
29
+
30
+ // ==============================================================================
31
+ // Main SDK Class
32
+ // ==============================================================================
33
+
34
+ export class DagAAClient {
35
+ 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 smartAccount: any | null = null;
40
+ private smartAccountClient: ReturnType<
41
+ typeof createSmartAccountClient
42
+ > | null = null;
43
+
44
+ constructor(config: DagAAConfig) {
45
+ this.config = {
46
+ ...config,
47
+ entryPointAddress: config.entryPointAddress || entryPoint06Address,
48
+ };
49
+
50
+ this.publicClient = createPublicClient({
51
+ chain: config.chain,
52
+ transport: http(config.rpcUrl),
53
+ });
54
+
55
+ this.walletClient = createWalletClient({
56
+ chain: config.chain,
57
+ transport: http(config.rpcUrl),
58
+ });
59
+ }
60
+
61
+ // ==============================================================================
62
+ // Smart Account Management
63
+ // ==============================================================================
64
+
65
+ async connectSmartAccount(
66
+ accountConfig: SmartAccountConfig
67
+ ): Promise<Address> {
68
+ const owner = privateKeyToAccount(accountConfig.owner);
69
+
70
+ const signingClient = createWalletClient({
71
+ account: owner,
72
+ chain: this.config.chain,
73
+ transport: http(this.config.rpcUrl),
74
+ });
75
+
76
+ if (accountConfig.accountAddress) {
77
+ // Use existing account
78
+ this.smartAccount = await toSimpleSmartAccount({
79
+ client: signingClient,
80
+ owner: owner,
81
+ factoryAddress: this.config.factoryAddress,
82
+ entryPoint: {
83
+ address: this.config.entryPointAddress!,
84
+ version: "0.6",
85
+ },
86
+ address: accountConfig.accountAddress,
87
+ });
88
+ } else {
89
+ // Create new account
90
+ this.smartAccount = await toSimpleSmartAccount({
91
+ client: signingClient,
92
+ owner: owner,
93
+ factoryAddress: this.config.factoryAddress,
94
+ entryPoint: {
95
+ address: this.config.entryPointAddress!,
96
+ version: "0.6",
97
+ },
98
+ });
99
+ }
100
+
101
+ // Create bundler client
102
+ this.bundlerClient = createPimlicoClient({
103
+ transport: http(this.config.bundlerUrl),
104
+ entryPoint: {
105
+ address: this.config.entryPointAddress!,
106
+ version: "0.6",
107
+ },
108
+ });
109
+
110
+ // Create smart account client
111
+ this.smartAccountClient = createSmartAccountClient({
112
+ bundlerTransport: http(this.config.bundlerUrl),
113
+ chain: this.config.chain,
114
+ account: this.smartAccount,
115
+ });
116
+
117
+ console.log(`✅ Connected to smart account: ${this.smartAccount.address}`);
118
+ return this.smartAccount.address;
119
+ }
120
+
121
+ // ==============================================================================
122
+ // Account Information
123
+ // ==============================================================================
124
+
125
+ getAddress(): Address {
126
+ if (!this.smartAccount) {
127
+ throw new Error(
128
+ "Smart account not connected. Call connectSmartAccount() first."
129
+ );
130
+ }
131
+ return this.smartAccount.address;
132
+ }
133
+
134
+ async getBalance(): Promise<bigint> {
135
+ if (!this.smartAccount) {
136
+ throw new Error("Smart account not connected");
137
+ }
138
+
139
+ return await this.publicClient.getBalance({
140
+ address: this.smartAccount.address,
141
+ });
142
+ }
143
+
144
+ async isDeployed(): Promise<boolean> {
145
+ if (!this.smartAccount) {
146
+ throw new Error("Smart account not connected");
147
+ }
148
+
149
+ const code = await this.publicClient.getCode({
150
+ address: this.smartAccount.address,
151
+ });
152
+
153
+ return code !== undefined && code !== "0x";
154
+ }
155
+
156
+ async getNonce(): Promise<bigint> {
157
+ if (!this.smartAccount) {
158
+ throw new Error("Smart account not connected");
159
+ }
160
+
161
+ return await this.publicClient.readContract({
162
+ address: this.config.entryPointAddress!,
163
+ abi: [
164
+ {
165
+ name: "getNonce",
166
+ type: "function",
167
+ stateMutability: "view",
168
+ inputs: [
169
+ { name: "sender", type: "address" },
170
+ { name: "key", type: "uint192" },
171
+ ],
172
+ outputs: [{ name: "nonce", type: "uint256" }],
173
+ },
174
+ ],
175
+ functionName: "getNonce",
176
+ args: [this.smartAccount.address, 0n],
177
+ });
178
+ }
179
+
180
+ // ==============================================================================
181
+ // Send UserOperations
182
+ // ==============================================================================
183
+
184
+ async sendUserOperation(params: SendUserOperationParams): Promise<Hash> {
185
+ if (!this.smartAccountClient) {
186
+ throw new Error("Smart account not connected");
187
+ }
188
+
189
+ const {
190
+ target,
191
+ data = "0x",
192
+ value = 0n,
193
+ maxFeePerGas,
194
+ maxPriorityFeePerGas,
195
+ callGasLimit = 150000n,
196
+ verificationGasLimit = 300000n,
197
+ preVerificationGas = 100000n,
198
+ } = params;
199
+
200
+ // Get gas prices if not provided
201
+ let gasPrices = {
202
+ maxFeePerGas: maxFeePerGas,
203
+ maxPriorityFeePerGas: maxPriorityFeePerGas,
204
+ };
205
+
206
+ if (!maxFeePerGas || !maxPriorityFeePerGas) {
207
+ const estimatedGas = await this.bundlerClient!.getUserOperationGasPrice();
208
+ gasPrices = {
209
+ maxFeePerGas: maxFeePerGas || estimatedGas.fast.maxFeePerGas,
210
+ maxPriorityFeePerGas:
211
+ maxPriorityFeePerGas || estimatedGas.fast.maxPriorityFeePerGas,
212
+ };
213
+ }
214
+
215
+ console.log("Sending UserOperation...");
216
+ console.log(` Target: ${target}`);
217
+ console.log(` Value: ${value}`);
218
+ console.log(
219
+ ` Gas: ${gasPrices.maxFeePerGas} / ${gasPrices.maxPriorityFeePerGas}`
220
+ );
221
+
222
+ const userOpHash = await this.smartAccountClient.sendTransaction({
223
+ calls: [
224
+ {
225
+ to: target,
226
+ value: value,
227
+ data: data,
228
+ },
229
+ ],
230
+ maxFeePerGas: gasPrices.maxFeePerGas,
231
+ maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas,
232
+ callGasLimit,
233
+ verificationGasLimit,
234
+ preVerificationGas,
235
+ });
236
+
237
+ console.log(`✅ UserOperation sent: ${userOpHash}`);
238
+ return userOpHash;
239
+ }
240
+
241
+ // ==============================================================================
242
+ // Contract Interactions
243
+ // ==============================================================================
244
+
245
+ async writeContract(params: {
246
+ address: Address;
247
+ abi: any[];
248
+ functionName: string;
249
+ args?: any[];
250
+ value?: bigint;
251
+ maxFeePerGas?: bigint;
252
+ maxPriorityFeePerGas?: bigint;
253
+ }): Promise<Hash> {
254
+ const { address, abi, functionName, args = [], value = 0n } = params;
255
+
256
+ const data = encodeFunctionData({
257
+ abi,
258
+ functionName,
259
+ args,
260
+ });
261
+
262
+ return await this.sendUserOperation({
263
+ target: address,
264
+ data,
265
+ value,
266
+ maxFeePerGas: params.maxFeePerGas,
267
+ maxPriorityFeePerGas: params.maxPriorityFeePerGas,
268
+ });
269
+ }
270
+
271
+ async readContract(params: {
272
+ address: Address;
273
+ abi: any[];
274
+ functionName: string;
275
+ args?: any[];
276
+ }): Promise<any> {
277
+ return await this.publicClient.readContract({
278
+ address: params.address,
279
+ abi: params.abi,
280
+ functionName: params.functionName,
281
+ args: params.args || [],
282
+ });
283
+ }
284
+
285
+ // ==============================================================================
286
+ // Utilities
287
+ // ==============================================================================
288
+
289
+ async waitForUserOperationReceipt(
290
+ userOpHash: Hash,
291
+ timeout: number = 30000
292
+ ): Promise<UserOperationReceipt> {
293
+ console.log(`Waiting for UserOperation receipt...`);
294
+
295
+ const startTime = Date.now();
296
+
297
+ while (Date.now() - startTime < timeout) {
298
+ await new Promise((resolve) => setTimeout(resolve, 2000));
299
+
300
+ // In a real implementation, you'd query the bundler for receipt
301
+ // For now, we'll return a basic receipt structure
302
+ console.log("Checking for receipt...");
303
+ }
304
+
305
+ return {
306
+ userOpHash,
307
+ success: true,
308
+ };
309
+ }
310
+
311
+ async fundAccount(
312
+ amount: bigint,
313
+ fromPrivateKey: `0x${string}`
314
+ ): Promise<Hash> {
315
+ if (!this.smartAccount) {
316
+ throw new Error("Smart account not connected");
317
+ }
318
+
319
+ const signer = privateKeyToAccount(fromPrivateKey);
320
+ const client = createWalletClient({
321
+ account: signer,
322
+ chain: this.config.chain,
323
+ transport: http(this.config.rpcUrl),
324
+ });
325
+
326
+ console.log(`Funding account with ${amount} wei...`);
327
+
328
+ const hash = await client.sendTransaction({
329
+ to: this.smartAccount.address,
330
+ value: amount,
331
+ });
332
+
333
+ console.log(`✅ Funded: ${hash}`);
334
+ return hash;
335
+ }
336
+
337
+ // ==============================================================================
338
+ // Batch Operations
339
+ // ==============================================================================
340
+
341
+ async sendBatchUserOperations(
342
+ operations: SendUserOperationParams[]
343
+ ): Promise<Hash[]> {
344
+ const results: Hash[] = [];
345
+
346
+ for (const op of operations) {
347
+ const hash = await this.sendUserOperation(op);
348
+ results.push(hash);
349
+ }
350
+
351
+ return results;
352
+ }
353
+ }
354
+
355
+ // ==============================================================================
356
+ // Helper Functions
357
+ // ==============================================================================
358
+
359
+ export function createDagAAClient(config: DagAAConfig): DagAAClient {
360
+ return new DagAAClient(config);
361
+ }
362
+
363
+ export function parseDAG(amount: string): bigint {
364
+ return parseEther(amount);
365
+ }
366
+
367
+ // ==============================================================================
368
+ // Export Types
369
+ // ==============================================================================
370
+
371
+ // export type {
372
+ // DagAAConfig,
373
+ // SmartAccountConfig,
374
+ // SendUserOperationParams,
375
+ // UserOperationReceipt,
376
+ // };
File without changes
@@ -0,0 +1,16 @@
1
+ import { defineChain } from "viem";
2
+
3
+ const awakening_ = defineChain({
4
+ id: 1043,
5
+ name: "Awakening Testnet",
6
+ nativeCurrency: { decimals: 18, name: "Dag", symbol: "DAG" },
7
+ rpcUrls: { default: { http: ["https://public-bdag.nownodes.io"] } },
8
+ blockExplorers: {
9
+ default: { name: "Explorer", url: "https://awakening.bdagscan.com/" },
10
+ },
11
+ });
12
+
13
+ export const awakening = {
14
+ bundler_rpc: "http://0.0.0.0:3000/",
15
+ chain_config: awakening_,
16
+ };
@@ -0,0 +1,44 @@
1
+ import {
2
+ createPublicClient,
3
+ createWalletClient,
4
+ http,
5
+ type Chain,
6
+ type Transport,
7
+ type Account,
8
+ type Hash,
9
+ type Address,
10
+ encodeFunctionData,
11
+ parseEther,
12
+ } from "viem";
13
+
14
+ export interface DagAAConfig {
15
+ chain: Chain;
16
+ rpcUrl: string;
17
+ bundlerUrl: string;
18
+ factoryAddress: Address;
19
+ entryPointAddress?: Address;
20
+ }
21
+
22
+ export interface SmartAccountConfig {
23
+ owner: `0x${string}`;
24
+ accountAddress?: Address;
25
+ }
26
+
27
+ export interface SendUserOperationParams {
28
+ target: Address;
29
+ data?: `0x${string}`;
30
+ value?: bigint;
31
+ maxFeePerGas?: bigint;
32
+ maxPriorityFeePerGas?: bigint;
33
+ callGasLimit?: bigint;
34
+ verificationGasLimit?: bigint;
35
+ preVerificationGas?: bigint;
36
+ }
37
+
38
+ export interface UserOperationReceipt {
39
+ userOpHash: Hash;
40
+ transactionHash?: Hash;
41
+ success: boolean;
42
+ blockNumber?: bigint;
43
+ blockHash?: Hash;
44
+ }
@@ -0,0 +1,8 @@
1
+ export { createDagAAClient, parseDAG } from "../clients/actions/main";
2
+
3
+ export {
4
+ DagAAConfig,
5
+ SmartAccountConfig,
6
+ SendUserOperationParams,
7
+ UserOperationReceipt,
8
+ } from "../clients/types";