@aave-dao/cli 0.2.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.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @aave-dao/cli
2
+
3
+ A cli tool to help with various web3 / solidity tasks. For a full overview of features you can run `@aave-dao/cli --help`
4
+
5
+ ## Installation
6
+
7
+ Make sure to setup your .env
8
+
9
+ ```
10
+ # Used for code and storage diffs
11
+ ETHERSCAN_API_KEY=
12
+
13
+ # Used for creating tenderly vnets
14
+ TENDERLY_ACCESS_TOKEN=
15
+ TENDERLY_PROJECT_SLUG=
16
+ TENDERLY_ACCOUNT=
17
+ ```
18
+
19
+ Local installation
20
+ ```
21
+ npm i @aave-dao/cli
22
+ ```
23
+
24
+ Global installation
25
+ ```
26
+ npm i -g @aave-dao/cli
27
+ ```
28
+
29
+ Once installed you should be able to run commands via the `@aave-dao/cli` or the cli binary.
30
+
31
+ Alteratively you can use `npx @aave-dao/cli` to run the cli via npx.
32
+
33
+ ## Code Diffs
34
+
35
+ `npx @aave-dao/cli codeDiff` can be used to generate code diffs between two verified contracts
36
+
37
+ ```
38
+ Usage: @aave-dao/cli codeDiff [options]
39
+
40
+ generated the diff between any two addresses
41
+
42
+ Options:
43
+ --address1 <address>
44
+ --chainId1 <number>
45
+ --address2 <address>
46
+ --chainId2 <number>
47
+ -f, --flatten
48
+ -o, --output <format> (choices: "stdout", "file", default: "stdout")
49
+ -p, --path <path> (default: "./diffs/code")
50
+ -h, --help display help for command
51
+ ```
52
+
53
+ ## Storage Diffs
54
+
55
+ `npx @aave-dao/cli storageDiff` can be used to generate storage layout diffs between two contracts
56
+
57
+ ```
58
+ Usage: @aave-dao/cli storageDiff [options]
59
+
60
+ generated the storage diff between any two files
61
+
62
+ Options:
63
+ --contract1 <Contract|path>
64
+ --contract2 <Contract|path>
65
+ -h, --help display help for command
66
+ ```
67
+
68
+ ## Aave Tenderly Vnets
69
+
70
+ `npx @aave-dao/cli aave-vnet` can be used to create a tenderly virtual testnet to execute payloads
71
+
72
+ ```
73
+ Usage: @aave-dao/cli aave-vnet [options]
74
+
75
+ creates a tenderly virtual testnet and execute payloads
76
+
77
+ Options:
78
+ -c,--chainId <number>
79
+ -t, --tenderlyAccessToken <string> defaults to env.TENDERLY_ACCESS_TOKEN
80
+ -a, --tenderlyAccountSlug <string> defaults to env.TENDERLY_ACCOUNT_SLUG
81
+ -p, --tenderlyProjectSlug <string> defaults to env.TENDERLY_PROJECT_SLUG
82
+ -h, --help display help for command
83
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,559 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import "dotenv/config";
5
+ import { Command as Command6 } from "@commander-js/extra-typings";
6
+
7
+ // package.json
8
+ var package_default = {
9
+ name: "@aave-dao/cli",
10
+ version: "0.2.0",
11
+ main: "./dist/index.mjs",
12
+ sideEffects: false,
13
+ license: "MIT",
14
+ repository: {
15
+ type: "git",
16
+ url: "https://github.com/aave-dao/toolkit.git",
17
+ directory: "packages/cli"
18
+ },
19
+ files: [
20
+ "dist/**",
21
+ "README.md"
22
+ ],
23
+ type: "module",
24
+ bin: {
25
+ cli: "dist/index.js"
26
+ },
27
+ scripts: {
28
+ build: "tsup src/index.ts",
29
+ dev: "tsup src/index.ts --watch",
30
+ start: "node dist/index.js",
31
+ clean: "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
32
+ },
33
+ devDependencies: {
34
+ "@types/node": "catalog:",
35
+ tsup: "catalog:",
36
+ typescript: "catalog:"
37
+ },
38
+ publishConfig: {
39
+ access: "public"
40
+ },
41
+ dependencies: {
42
+ "@aave-dao/aave-address-book": "^4.30.3",
43
+ "@aave-dao/toolbox": "workspace:*",
44
+ "@commander-js/extra-typings": "^13.1.0",
45
+ "@inquirer/prompts": "^7.3.2",
46
+ dotenv: "^16.4.7",
47
+ viem: "catalog:"
48
+ }
49
+ };
50
+
51
+ // src/tasks/code-diff.ts
52
+ import { Option } from "@commander-js/extra-typings";
53
+ import {
54
+ diffCode,
55
+ getSourceCode,
56
+ parseBlockscoutStyleSourceCode,
57
+ parseEtherscanStyleSourceCode
58
+ } from "@aave-dao/toolbox";
59
+ import { mkdirSync, writeFileSync } from "node:fs";
60
+ function registerCodeDiff(program2) {
61
+ program2.command("codeDiff").description("generated the diff between any two addresses").addOption(new Option("--address1 <address>").makeOptionMandatory()).addOption(new Option("--chainId1 <number>").makeOptionMandatory()).addOption(new Option("--address2 <address>").makeOptionMandatory()).addOption(new Option("--chainId2 <number>").makeOptionMandatory()).addOption(new Option("-f, --flatten")).addOption(
62
+ new Option("-o, --output <format>").choices(["stdout", "file"]).default("stdout")
63
+ ).addOption(new Option("-p, --path <path>").default("./diffs/code")).action(
64
+ async ({
65
+ address1,
66
+ address2,
67
+ chainId1,
68
+ chainId2,
69
+ flatten,
70
+ output,
71
+ path
72
+ }) => {
73
+ const sources = await Promise.all([
74
+ getSourceCode({
75
+ chainId: Number(chainId1),
76
+ address: address1,
77
+ apiKey: process.env.ETHERSCAN_API_KEY,
78
+ apiUrl: process.env.EXPLORER_PROXY
79
+ }),
80
+ getSourceCode({
81
+ chainId: Number(chainId2),
82
+ address: address2,
83
+ apiKey: process.env.ETHERSCAN_API_KEY,
84
+ apiUrl: process.env.EXPLORER_PROXY
85
+ })
86
+ ]);
87
+ const source1 = sources[0].AdditionalSources ? parseBlockscoutStyleSourceCode(
88
+ sources[0]
89
+ ) : parseEtherscanStyleSourceCode(sources[0].SourceCode);
90
+ const source2 = sources[1].AdditionalSources ? parseBlockscoutStyleSourceCode(
91
+ sources[1]
92
+ ) : parseEtherscanStyleSourceCode(sources[1].SourceCode);
93
+ const diff = await diffCode(source1, source2);
94
+ if (flatten || output === "stdout") {
95
+ const flat = Object.keys(diff).reduce((acc, key) => {
96
+ acc += diff[key];
97
+ return acc;
98
+ }, "");
99
+ if (output === "stdout") {
100
+ console.log(flat);
101
+ } else {
102
+ const filePath = `${path}/${chainId1}`;
103
+ mkdirSync(filePath, { recursive: true });
104
+ writeFileSync(`${filePath}/${address1}_${address2}.patch`, flat);
105
+ }
106
+ } else {
107
+ const filePath = `${path}/${chainId1}/${address1}_${address2}`;
108
+ mkdirSync(filePath, { recursive: true });
109
+ Object.keys(diff).map((file) => {
110
+ writeFileSync(`${filePath}/${file}.patch`, diff[file]);
111
+ });
112
+ }
113
+ }
114
+ );
115
+ }
116
+
117
+ // src/tasks/aave-vnet.ts
118
+ import { Option as Option2 } from "@commander-js/extra-typings";
119
+ import {
120
+ getNonFinalizedPayloads,
121
+ getPayloadsController,
122
+ makePayloadExecutableOnTestClient,
123
+ tenderly_createVnet
124
+ } from "@aave-dao/toolbox";
125
+ import { checkbox, select, Separator, input } from "@inquirer/prompts";
126
+ import * as addresses from "@aave-dao/aave-address-book";
127
+ import { parseAbi, zeroAddress } from "viem";
128
+ import { readContract } from "viem/actions";
129
+ import { toAccount } from "viem/accounts";
130
+ function registerAaveVNet(program2) {
131
+ program2.command("aave-vnet").description("creates a tenderly virtual testnet and execute payloads").addOption(new Option2("-c,--chainId <number>").makeOptionMandatory()).addOption(
132
+ new Option2(
133
+ "-t, --tenderlyAccessToken <string>",
134
+ "defaults to env.TENDERLY_ACCESS_TOKEN"
135
+ )
136
+ ).addOption(new Option2("--pc, --payloadsController <address>")).addOption(
137
+ new Option2(
138
+ "-a, --tenderlyAccountSlug <string>",
139
+ "defaults to env.TENDERLY_ACCOUNT_SLUG"
140
+ )
141
+ ).addOption(
142
+ new Option2(
143
+ "-p, --tenderlyProjectSlug <string>",
144
+ "defaults to env.TENDERLY_PROJECT_SLUG"
145
+ )
146
+ ).action(
147
+ async ({
148
+ chainId,
149
+ payloadsController,
150
+ tenderlyAccessToken,
151
+ tenderlyAccountSlug,
152
+ tenderlyProjectSlug
153
+ }) => {
154
+ const vnet = await tenderly_createVnet(
155
+ {
156
+ baseChainId: Number(chainId),
157
+ forkChainId: 3030,
158
+ slug: `${Math.floor(Math.random() * 1e3)}acli-aave-dao-vnet-${chainId}`,
159
+ displayName: "aave-dao cli vnet"
160
+ },
161
+ {
162
+ accessToken: tenderlyAccessToken || process.env.TENDERLY_ACCESS_TOKEN,
163
+ accountSlug: tenderlyAccountSlug || process.env.TENDERLY_ACCOUNT_SLUG,
164
+ projectSlug: tenderlyProjectSlug || process.env.TENDERLY_PROJECT_SLUG
165
+ }
166
+ );
167
+ console.info("Virtual testnet created!");
168
+ console.info("RPC:", vnet.vnet.rpcs[0].url);
169
+ const controllerAddress = payloadsController ? payloadsController : findPayloadsController(Number(chainId));
170
+ const controllerContract = getPayloadsController(
171
+ vnet.walletClient,
172
+ controllerAddress
173
+ );
174
+ while (true) {
175
+ const answer = await select({
176
+ message: "What do you want to do?",
177
+ choices: [
178
+ {
179
+ name: "Execute a registered payload",
180
+ value: 0 /* PAYLOAD_ID */
181
+ },
182
+ {
183
+ name: "Execute a deployed (but not registered) payload",
184
+ value: 1 /* PAYLOAD_ADDRESS */
185
+ },
186
+ {
187
+ name: "Execute a local payload.",
188
+ value: 2 /* PAYLOAD_ARTIFACT */
189
+ },
190
+ new Separator(),
191
+ {
192
+ name: "Exit (this will keep the vnet open - you can delete it via tenderly ui)",
193
+ value: 3 /* EXIT */
194
+ },
195
+ {
196
+ name: "Exit and delete",
197
+ value: 4 /* DELETE */
198
+ }
199
+ ]
200
+ });
201
+ switch (answer) {
202
+ case 0 /* PAYLOAD_ID */:
203
+ const payloadIds = await getNonFinalizedPayloads(
204
+ vnet.testClient,
205
+ controllerAddress
206
+ );
207
+ const answer2 = await checkbox({
208
+ message: "Select the payloads you want to execute",
209
+ choices: payloadIds.map((id) => ({
210
+ name: String(id),
211
+ value: String(id)
212
+ }))
213
+ });
214
+ for (const id of answer2) {
215
+ await makePayloadExecutableOnTestClient(
216
+ vnet.testClient,
217
+ controllerAddress,
218
+ Number(id)
219
+ );
220
+ await controllerContract.write.executePayload([Number(id)]);
221
+ console.info(`Payload ${id} executed`);
222
+ }
223
+ break;
224
+ case 1 /* PAYLOAD_ADDRESS */:
225
+ const address = await input({
226
+ message: "Enter the payload address"
227
+ });
228
+ const currentId = await controllerContract.read.getPayloadsCount();
229
+ let sender = zeroAddress;
230
+ try {
231
+ sender = await readContract(vnet.testClient, {
232
+ address: controllerContract.address,
233
+ abi: parseAbi([
234
+ "function payloadsManager() external view returns (address)"
235
+ ]),
236
+ functionName: "payloadsManager"
237
+ });
238
+ } catch (e) {
239
+ }
240
+ await controllerContract.write.createPayload(
241
+ [
242
+ [
243
+ {
244
+ target: address,
245
+ accessLevel: 1,
246
+ callData: "0x",
247
+ withDelegateCall: true,
248
+ signature: "execute()",
249
+ value: 0n
250
+ }
251
+ ]
252
+ ],
253
+ {
254
+ account: toAccount(sender),
255
+ chain: vnet.walletClient.chain
256
+ }
257
+ );
258
+ await makePayloadExecutableOnTestClient(
259
+ vnet.testClient,
260
+ controllerAddress,
261
+ currentId
262
+ );
263
+ await controllerContract.write.executePayload([currentId]);
264
+ break;
265
+ case 3 /* EXIT */:
266
+ process.exit(0);
267
+ case 4 /* DELETE */:
268
+ await vnet.delete();
269
+ console.info("Virtual testnet deleted!");
270
+ process.exit(0);
271
+ }
272
+ }
273
+ }
274
+ );
275
+ }
276
+ function findPayloadsController(chainId) {
277
+ const key = Object.keys(addresses).find(
278
+ (key2) => addresses[key2].CHAIN_ID === chainId && addresses[key2].PAYLOADS_CONTROLLER
279
+ );
280
+ if (key)
281
+ return addresses[key].PAYLOADS_CONTROLLER;
282
+ }
283
+
284
+ // src/tasks/storage-diff.ts
285
+ import { Option as Option3 } from "@commander-js/extra-typings";
286
+ import {
287
+ diffFoundryStorageLayout,
288
+ foundry_getStorageLayout
289
+ } from "@aave-dao/toolbox";
290
+ function registerStorageDiff(program2) {
291
+ program2.command("storageDiff").description("generated the storage diff between any two files").addOption(new Option3("--contract1 <Contract|path>").makeOptionMandatory()).addOption(new Option3("--contract2 <Contract|path>").makeOptionMandatory()).action(async ({ contract1, contract2 }) => {
292
+ const storage1 = foundry_getStorageLayout(contract1);
293
+ const storage2 = foundry_getStorageLayout(contract2);
294
+ const result = diffFoundryStorageLayout(storage1, storage2);
295
+ console.log(result);
296
+ });
297
+ }
298
+
299
+ // src/tasks/rpcs.ts
300
+ import { Option as Option4 } from "@commander-js/extra-typings";
301
+ import { ChainId, getNetworkEnv, getRPCUrl } from "@aave-dao/toolbox";
302
+ function registerRpcs(program2) {
303
+ program2.command("rpcs").description("generate a list of rpcs to be used in foundry projects").addOption(
304
+ new Option4("--alchemyApiKey <string>", "defaults to env.ALCHEMY_API_KEY")
305
+ ).addOption(
306
+ new Option4(
307
+ "--quicknodeToken <string>",
308
+ "defaults to env.QUICKNODE_TOKEN"
309
+ )
310
+ ).addOption(
311
+ new Option4(
312
+ "--quicknodeEndpointName <string>",
313
+ "defaults to env.QUICKNODE_ENDPOINT_NAME"
314
+ )
315
+ ).action(
316
+ async ({ alchemyApiKey, quicknodeToken, quicknodeEndpointName }) => {
317
+ let env = "";
318
+ let toml = "";
319
+ Object.entries(ChainId).map(([key, chainId]) => {
320
+ const networkEnv = getNetworkEnv(chainId);
321
+ const rpc = getRPCUrl(chainId, {
322
+ alchemyKey: alchemyApiKey || process.env.ALCHEMY_API_KEY,
323
+ quicknodeToken: quicknodeToken || process.env.QUICKNODE_TOKEN,
324
+ quicknodeEndpointName: quicknodeEndpointName || process.env.QUICKNODE_ENDPOINT_NAME
325
+ });
326
+ env += `${networkEnv}=${rpc || ""}
327
+ `;
328
+ toml += `${key}="\${${networkEnv}}"
329
+ `;
330
+ });
331
+ console.log("### .env ###");
332
+ console.log(env);
333
+ console.log("### foundry toml ###");
334
+ console.log(toml);
335
+ }
336
+ );
337
+ }
338
+
339
+ // src/tasks/protocol.ts
340
+ import {
341
+ fetchPoolAddresses,
342
+ getClient,
343
+ getReserveTokens,
344
+ getReserveConfigurations
345
+ } from "@aave-dao/toolbox";
346
+ import { AaveV3Ethereum } from "@aave-dao/aave-address-book";
347
+ function registerProtocol(program2) {
348
+ program2.command("protocol").description("generated the storage diff between any two files").action(async () => {
349
+ const mainnetClient = getClient(1, {
350
+ providerConfig: { alchemyKey: process.env.ALCHEMY_API_KEY }
351
+ });
352
+ const contracts = await fetchPoolAddresses(
353
+ mainnetClient,
354
+ AaveV3Ethereum.POOL_ADDRESSES_PROVIDER
355
+ );
356
+ const reserveTokens = await getReserveTokens(
357
+ mainnetClient,
358
+ contracts.pool
359
+ );
360
+ const reserveConfigs = await getReserveConfigurations(
361
+ mainnetClient,
362
+ contracts.pool,
363
+ reserveTokens
364
+ );
365
+ console.log(reserveConfigs);
366
+ });
367
+ }
368
+
369
+ // src/tasks/seatbelt-report.ts
370
+ import { getAddressBookReferences } from "@aave-dao/aave-address-book/utils";
371
+ import {
372
+ getMdContractName,
373
+ getPayloadsController as getPayloadsController2,
374
+ makePayloadExecutableOnTestClient as makePayloadExecutableOnTestClient2,
375
+ renderTenderlyReport,
376
+ tenderly_createVnet as tenderly_createVnet2,
377
+ IPayloadsController_ABI
378
+ } from "@aave-dao/toolbox";
379
+ import { Option as Option5 } from "@commander-js/extra-typings";
380
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
381
+ import {
382
+ encodeFunctionData,
383
+ parseAbi as parseAbi2,
384
+ zeroAddress as zeroAddress2
385
+ } from "viem";
386
+ import { toAccount as toAccount2 } from "viem/accounts";
387
+ import { readContract as readContract2 } from "viem/actions";
388
+ function registerSeatbeltReport(program2) {
389
+ program2.command("seatbelt-report").description("generates a seatbelt report for the payload").addOption(new Option5("-c,--chainId <number>").makeOptionMandatory()).addOption(new Option5("--pi,--payloadId <number>")).addOption(new Option5("--pa, --payloadAddress <address>")).addOption(new Option5("--pb,--payloadBytecode <hex>")).addOption(new Option5("--pcd,--payloadCalldata <hex>")).addOption(
390
+ new Option5("--pc, --payloadsController <address>").makeOptionMandatory()
391
+ ).addOption(
392
+ new Option5("-o, --output <output path>").default("./reports/seatbelt/")
393
+ ).addOption(
394
+ new Option5(
395
+ "-t, --tenderlyAccessToken <string>",
396
+ "defaults to env.TENDERLY_ACCESS_TOKEN"
397
+ )
398
+ ).addOption(
399
+ new Option5(
400
+ "-a, --tenderlyAccountSlug <string>",
401
+ "defaults to env.TENDERLY_ACCOUNT_SLUG"
402
+ )
403
+ ).addOption(
404
+ new Option5(
405
+ "-p, --tenderlyProjectSlug <string>",
406
+ "defaults to env.TENDERLY_PROJECT_SLUG"
407
+ )
408
+ ).addOption(
409
+ new Option5(
410
+ "-e, --etherscanApiKey <string>",
411
+ "defaults to env.ETHERSCAN_API_KEY"
412
+ )
413
+ ).action(
414
+ async ({
415
+ chainId,
416
+ tenderlyAccessToken,
417
+ tenderlyAccountSlug,
418
+ tenderlyProjectSlug,
419
+ output,
420
+ payloadId,
421
+ payloadAddress,
422
+ payloadBytecode,
423
+ payloadCalldata,
424
+ payloadsController
425
+ }) => {
426
+ const vnet = await tenderly_createVnet2(
427
+ {
428
+ baseChainId: Number(chainId),
429
+ forkChainId: 3030,
430
+ slug: `${Math.floor(Math.random() * 1e3)}acli-aave-dao-vnet-${chainId}`,
431
+ displayName: "seatbelt"
432
+ },
433
+ {
434
+ accessToken: tenderlyAccessToken || process.env.TENDERLY_ACCESS_TOKEN,
435
+ accountSlug: tenderlyAccountSlug || process.env.TENDERLY_ACCOUNT_SLUG,
436
+ projectSlug: tenderlyProjectSlug || process.env.TENDERLY_PROJECT_SLUG
437
+ }
438
+ );
439
+ const controllerContract = getPayloadsController2(
440
+ vnet.walletClient,
441
+ payloadsController
442
+ );
443
+ let currentId = 0;
444
+ let sender = zeroAddress2;
445
+ try {
446
+ sender = await readContract2(vnet.testClient, {
447
+ address: controllerContract.address,
448
+ abi: parseAbi2([
449
+ "function payloadsManager() external view returns (address)"
450
+ ]),
451
+ functionName: "payloadsManager"
452
+ });
453
+ } catch (e) {
454
+ }
455
+ if (payloadId) {
456
+ currentId = Number(payloadId);
457
+ }
458
+ if (payloadBytecode) {
459
+ vnet.testClient.setCode({
460
+ address: "0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8",
461
+ bytecode: payloadBytecode
462
+ });
463
+ payloadAddress = "0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8";
464
+ }
465
+ if (payloadCalldata) {
466
+ currentId = await controllerContract.read.getPayloadsCount();
467
+ await vnet.walletClient.sendTransaction({
468
+ account: toAccount2(sender),
469
+ chain: vnet.walletClient.chain,
470
+ to: payloadsController,
471
+ data: payloadCalldata
472
+ });
473
+ }
474
+ if (payloadAddress) {
475
+ currentId = await controllerContract.read.getPayloadsCount();
476
+ const payload = {
477
+ target: payloadAddress,
478
+ accessLevel: 1,
479
+ callData: "0x",
480
+ withDelegateCall: true,
481
+ signature: "execute()",
482
+ value: 0n
483
+ };
484
+ await controllerContract.write.createPayload([[payload]], {
485
+ account: toAccount2(sender),
486
+ chain: vnet.walletClient.chain
487
+ });
488
+ }
489
+ await makePayloadExecutableOnTestClient2(
490
+ vnet.testClient,
491
+ payloadsController,
492
+ currentId
493
+ );
494
+ const simResult = await vnet.simulate({
495
+ network_id: chainId.toString(),
496
+ from: sender,
497
+ to: payloadsController,
498
+ input: encodeFunctionData({
499
+ abi: IPayloadsController_ABI,
500
+ functionName: "executePayload",
501
+ args: [currentId]
502
+ }),
503
+ block_number: null,
504
+ transaction_index: 0,
505
+ gas: 3e7,
506
+ gas_price: "0",
507
+ value: "0",
508
+ access_list: [],
509
+ generate_access_list: true,
510
+ save: true,
511
+ source: "dashboard"
512
+ });
513
+ await controllerContract.write.executePayload([currentId], {
514
+ account: toAccount2(sender),
515
+ chain: vnet.walletClient.chain
516
+ });
517
+ const report = await renderTenderlyReport({
518
+ client: vnet.walletClient,
519
+ sim: simResult,
520
+ payloadId: currentId,
521
+ payload: await controllerContract.read.getPayloadById([currentId]),
522
+ onchainLogs: {},
523
+ config: {
524
+ etherscanApiKey: process.env.ETHERSCAN_API_KEY
525
+ },
526
+ getContractName: (sim, address) => {
527
+ const references = getAddressBookReferences(
528
+ address,
529
+ Number(sim.simulation.network_id)
530
+ );
531
+ if (references.length > 0)
532
+ return flagAsKnown(
533
+ getMdContractName(sim.contracts, address),
534
+ references[0]
535
+ );
536
+ return getMdContractName(sim.contracts, address);
537
+ }
538
+ });
539
+ const filePath = `${output}/${chainId}_${payloadsController}`;
540
+ mkdirSync2(filePath, { recursive: true });
541
+ writeFileSync2(`${filePath}/${currentId}.md`, report.report);
542
+ }
543
+ );
544
+ }
545
+ function flagAsKnown(value, reference) {
546
+ return `${value} [:ghost:](https://github.com/aave-dao/aave-address-book "${reference}")`;
547
+ }
548
+
549
+ // src/index.ts
550
+ var program = new Command6();
551
+ program.name("@aave-dao/cli").description("A cli to help with web3 / solidity tasks").version(package_default.version).showHelpAfterError();
552
+ registerCodeDiff(program);
553
+ registerAaveVNet(program);
554
+ registerStorageDiff(program);
555
+ registerRpcs(program);
556
+ registerProtocol(program);
557
+ registerSeatbeltReport(program);
558
+ program.parse();
559
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../package.json","../src/tasks/code-diff.ts","../src/tasks/aave-vnet.ts","../src/tasks/storage-diff.ts","../src/tasks/rpcs.ts","../src/tasks/protocol.ts","../src/tasks/seatbelt-report.ts"],"sourcesContent":["#!/usr/bin/env node\nimport \"dotenv/config\";\nimport { Command, Option } from \"@commander-js/extra-typings\";\nimport packageJson from \"../package.json\";\nimport { registerCodeDiff } from \"./tasks/code-diff\";\nimport { registerAaveVNet } from \"./tasks/aave-vnet\";\nimport { registerStorageDiff } from \"./tasks/storage-diff\";\nimport { registerRpcs } from \"./tasks/rpcs\";\nimport { registerProtocol } from \"./tasks/protocol\";\nimport { registerSeatbeltReport } from \"./tasks/seatbelt-report.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"@aave-dao/cli\")\n .description(\"A cli to help with web3 / solidity tasks\")\n .version(packageJson.version)\n .showHelpAfterError();\n\nregisterCodeDiff(program);\nregisterAaveVNet(program);\nregisterStorageDiff(program);\nregisterRpcs(program);\nregisterProtocol(program);\nregisterSeatbeltReport(program);\n\nprogram.parse();\n","{\n \"name\": \"@aave-dao/cli\",\n \"version\": \"0.2.0\",\n \"main\": \"./dist/index.mjs\",\n \"sideEffects\": false,\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/aave-dao/toolkit.git\",\n \"directory\": \"packages/cli\"\n },\n \"files\": [\n \"dist/**\",\n \"README.md\"\n ],\n \"type\": \"module\",\n \"bin\": {\n \"cli\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts\",\n \"dev\": \"tsup src/index.ts --watch\",\n \"start\": \"node dist/index.js\",\n \"clean\": \"rm -rf .turbo && rm -rf node_modules && rm -rf dist\"\n },\n \"devDependencies\": {\n \"@types/node\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"dependencies\": {\n \"@aave-dao/aave-address-book\": \"^4.30.3\",\n \"@aave-dao/toolbox\": \"workspace:*\",\n \"@commander-js/extra-typings\": \"^13.1.0\",\n \"@inquirer/prompts\": \"^7.3.2\",\n \"dotenv\": \"^16.4.7\",\n \"viem\": \"catalog:\"\n }\n}\n","import { Command, Option } from \"@commander-js/extra-typings\";\nimport {\n BlockscoutStyleSourceCode,\n diffCode,\n getSourceCode,\n parseBlockscoutStyleSourceCode,\n parseEtherscanStyleSourceCode,\n StandardJsonInput,\n} from \"@aave-dao/toolbox\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\n\nexport function registerCodeDiff(program: Command) {\n program\n .command(\"codeDiff\")\n .description(\"generated the diff between any two addresses\")\n .addOption(new Option(\"--address1 <address>\").makeOptionMandatory())\n .addOption(new Option(\"--chainId1 <number>\").makeOptionMandatory())\n .addOption(new Option(\"--address2 <address>\").makeOptionMandatory())\n .addOption(new Option(\"--chainId2 <number>\").makeOptionMandatory())\n .addOption(new Option(\"-f, --flatten\"))\n .addOption(\n new Option(\"-o, --output <format>\")\n .choices([\"stdout\", \"file\"])\n .default(\"stdout\"),\n )\n .addOption(new Option(\"-p, --path <path>\").default(\"./diffs/code\"))\n .action(\n async ({\n address1,\n address2,\n chainId1,\n chainId2,\n flatten,\n output,\n path,\n }) => {\n const sources = await Promise.all([\n getSourceCode({\n chainId: Number(chainId1),\n address: address1 as any,\n apiKey: process.env.ETHERSCAN_API_KEY,\n apiUrl: process.env.EXPLORER_PROXY,\n }),\n getSourceCode({\n chainId: Number(chainId2),\n address: address2 as any,\n apiKey: process.env.ETHERSCAN_API_KEY,\n apiUrl: process.env.EXPLORER_PROXY,\n }),\n ]);\n const source1: StandardJsonInput = (\n sources[0] as BlockscoutStyleSourceCode\n ).AdditionalSources\n ? parseBlockscoutStyleSourceCode(\n sources[0] as BlockscoutStyleSourceCode,\n )\n : parseEtherscanStyleSourceCode(sources[0].SourceCode);\n const source2: StandardJsonInput = (\n sources[1] as BlockscoutStyleSourceCode\n ).AdditionalSources\n ? parseBlockscoutStyleSourceCode(\n sources[1] as BlockscoutStyleSourceCode,\n )\n : parseEtherscanStyleSourceCode(sources[1].SourceCode);\n const diff = await diffCode(source1, source2);\n if (flatten || output === \"stdout\") {\n const flat = Object.keys(diff).reduce((acc, key) => {\n acc += diff[key];\n return acc;\n }, \"\");\n if (output === \"stdout\") {\n console.log(flat);\n } else {\n const filePath = `${path}/${chainId1}`;\n mkdirSync(filePath, { recursive: true });\n writeFileSync(`${filePath}/${address1}_${address2}.patch`, flat);\n }\n } else {\n const filePath = `${path}/${chainId1}/${address1}_${address2}`;\n mkdirSync(filePath, { recursive: true });\n Object.keys(diff).map((file) => {\n writeFileSync(`${filePath}/${file}.patch`, diff[file]);\n });\n }\n },\n );\n}\n","import { Command, Option } from \"@commander-js/extra-typings\";\nimport {\n getNonFinalizedPayloads,\n getPayloadsController,\n makePayloadExecutableOnTestClient,\n tenderly_createVnet,\n} from \"@aave-dao/toolbox\";\nimport { checkbox, select, Separator, input } from \"@inquirer/prompts\";\nimport * as addresses from \"@aave-dao/aave-address-book\";\nimport { Address, parseAbi, zeroAddress } from \"viem\";\nimport { readContract } from \"viem/actions\";\nimport { toAccount } from \"viem/accounts\";\n\nenum DialogOptions {\n PAYLOAD_ID,\n PAYLOAD_ADDRESS,\n PAYLOAD_ARTIFACT,\n EXIT,\n DELETE,\n}\n\nexport function registerAaveVNet(program: Command) {\n program\n .command(\"aave-vnet\")\n .description(\"creates a tenderly virtual testnet and execute payloads\")\n .addOption(new Option(\"-c,--chainId <number>\").makeOptionMandatory())\n .addOption(\n new Option(\n \"-t, --tenderlyAccessToken <string>\",\n \"defaults to env.TENDERLY_ACCESS_TOKEN\",\n ),\n )\n .addOption(new Option(\"--pc, --payloadsController <address>\"))\n .addOption(\n new Option(\n \"-a, --tenderlyAccountSlug <string>\",\n \"defaults to env.TENDERLY_ACCOUNT_SLUG\",\n ),\n )\n .addOption(\n new Option(\n \"-p, --tenderlyProjectSlug <string>\",\n \"defaults to env.TENDERLY_PROJECT_SLUG\",\n ),\n )\n .action(\n async ({\n chainId,\n payloadsController,\n tenderlyAccessToken,\n tenderlyAccountSlug,\n tenderlyProjectSlug,\n }) => {\n const vnet = await tenderly_createVnet(\n {\n baseChainId: Number(chainId),\n forkChainId: 3030,\n slug: `${Math.floor(Math.random() * 1000)}acli-aave-dao-vnet-${chainId}`,\n displayName: \"aave-dao cli vnet\",\n },\n {\n accessToken:\n tenderlyAccessToken || process.env.TENDERLY_ACCESS_TOKEN!,\n accountSlug:\n tenderlyAccountSlug || process.env.TENDERLY_ACCOUNT_SLUG!,\n projectSlug:\n tenderlyProjectSlug || process.env.TENDERLY_PROJECT_SLUG!,\n },\n );\n console.info(\"Virtual testnet created!\");\n console.info(\"RPC:\", vnet.vnet.rpcs[0].url);\n const controllerAddress = payloadsController\n ? (payloadsController as Address)\n : findPayloadsController(Number(chainId))!;\n const controllerContract = getPayloadsController(\n vnet.walletClient,\n controllerAddress,\n );\n while (true) {\n const answer = await select({\n message: \"What do you want to do?\",\n choices: [\n {\n name: \"Execute a registered payload\",\n value: DialogOptions.PAYLOAD_ID,\n },\n {\n name: \"Execute a deployed (but not registered) payload\",\n value: DialogOptions.PAYLOAD_ADDRESS,\n },\n {\n name: \"Execute a local payload.\",\n value: DialogOptions.PAYLOAD_ARTIFACT,\n },\n new Separator(),\n {\n name: \"Exit (this will keep the vnet open - you can delete it via tenderly ui)\",\n value: DialogOptions.EXIT,\n },\n {\n name: \"Exit and delete\",\n value: DialogOptions.DELETE,\n },\n ],\n });\n switch (answer) {\n case DialogOptions.PAYLOAD_ID:\n const payloadIds = await getNonFinalizedPayloads(\n vnet.testClient,\n controllerAddress,\n );\n const answer = await checkbox({\n message: \"Select the payloads you want to execute\",\n choices: payloadIds.map((id) => ({\n name: String(id),\n value: String(id),\n })),\n });\n for (const id of answer) {\n await makePayloadExecutableOnTestClient(\n vnet.testClient,\n controllerAddress,\n Number(id),\n );\n await controllerContract.write.executePayload([Number(id)]);\n console.info(`Payload ${id} executed`);\n }\n break;\n case DialogOptions.PAYLOAD_ADDRESS:\n const address = await input({\n message: \"Enter the payload address\",\n });\n const currentId =\n await controllerContract.read.getPayloadsCount();\n\n // in case the controller is permissioned we fetch the manager\n let sender: Address = zeroAddress;\n try {\n sender = await readContract(vnet.testClient, {\n address: controllerContract.address,\n abi: parseAbi([\n \"function payloadsManager() external view returns (address)\",\n ]),\n functionName: \"payloadsManager\",\n });\n } catch (e) {}\n\n await controllerContract.write.createPayload(\n [\n [\n {\n target: address as Address,\n accessLevel: 1,\n callData: \"0x\",\n withDelegateCall: true,\n signature: \"execute()\",\n value: 0n,\n },\n ],\n ],\n {\n account: toAccount(sender),\n chain: vnet.walletClient.chain,\n },\n );\n await makePayloadExecutableOnTestClient(\n vnet.testClient,\n controllerAddress,\n currentId,\n );\n await controllerContract.write.executePayload([currentId]);\n break;\n case DialogOptions.EXIT:\n process.exit(0);\n case DialogOptions.DELETE:\n await vnet.delete();\n console.info(\"Virtual testnet deleted!\");\n process.exit(0);\n }\n }\n },\n );\n}\n\nexport function findPayloadsController(chainId: number): Address | void {\n const key = Object.keys(addresses).find(\n (key) =>\n (addresses[key as keyof typeof addresses] as any).CHAIN_ID === chainId &&\n (addresses[key as keyof typeof addresses] as any).PAYLOADS_CONTROLLER,\n );\n if (key)\n return (addresses[key as keyof typeof addresses] as any)\n .PAYLOADS_CONTROLLER;\n}\n","import { Command, Option } from \"@commander-js/extra-typings\";\nimport {\n diffFoundryStorageLayout,\n foundry_getStorageLayout,\n} from \"@aave-dao/toolbox\";\n\nexport function registerStorageDiff(program: Command) {\n program\n .command(\"storageDiff\")\n .description(\"generated the storage diff between any two files\")\n .addOption(new Option(\"--contract1 <Contract|path>\").makeOptionMandatory())\n .addOption(new Option(\"--contract2 <Contract|path>\").makeOptionMandatory())\n .action(async ({ contract1, contract2 }) => {\n const storage1 = foundry_getStorageLayout(contract1);\n const storage2 = foundry_getStorageLayout(contract2);\n const result = diffFoundryStorageLayout(storage1, storage2);\n console.log(result);\n });\n}\n","import { Command, Option } from \"@commander-js/extra-typings\";\nimport { ChainId, getNetworkEnv, getRPCUrl } from \"@aave-dao/toolbox\";\n\n/**\n * Logs a list of rpcs to be used in your foundry project\n * @param program\n */\nexport function registerRpcs(program: Command) {\n program\n .command(\"rpcs\")\n .description(\"generate a list of rpcs to be used in foundry projects\")\n .addOption(\n new Option(\"--alchemyApiKey <string>\", \"defaults to env.ALCHEMY_API_KEY\"),\n )\n .addOption(\n new Option(\n \"--quicknodeToken <string>\",\n \"defaults to env.QUICKNODE_TOKEN\",\n ),\n )\n .addOption(\n new Option(\n \"--quicknodeEndpointName <string>\",\n \"defaults to env.QUICKNODE_ENDPOINT_NAME\",\n ),\n )\n .action(\n async ({ alchemyApiKey, quicknodeToken, quicknodeEndpointName }) => {\n let env = \"\";\n let toml = \"\";\n Object.entries(ChainId).map(([key, chainId]) => {\n const networkEnv = getNetworkEnv(chainId);\n const rpc = getRPCUrl(chainId, {\n alchemyKey: alchemyApiKey || process.env.ALCHEMY_API_KEY,\n quicknodeToken: quicknodeToken || process.env.QUICKNODE_TOKEN,\n quicknodeEndpointName:\n quicknodeEndpointName || process.env.QUICKNODE_ENDPOINT_NAME,\n });\n env += `${networkEnv}=${rpc || \"\"}\\n`;\n toml += `${key}=\"\\${${networkEnv}}\"\\n`;\n });\n\n console.log(\"### .env ###\");\n console.log(env);\n\n console.log(\"### foundry toml ###\");\n console.log(toml);\n },\n );\n}\n","import { Command, Option } from \"@commander-js/extra-typings\";\nimport {\n fetchPoolAddresses,\n getClient,\n getReserveTokens,\n getReserveConfigurations,\n} from \"@aave-dao/toolbox\";\nimport { AaveV3Ethereum } from \"@aave-dao/aave-address-book\";\n\nexport function registerProtocol(program: Command) {\n program\n .command(\"protocol\")\n .description(\"generated the storage diff between any two files\")\n .action(async () => {\n const mainnetClient = getClient(1, {\n providerConfig: { alchemyKey: process.env.ALCHEMY_API_KEY },\n });\n const contracts = await fetchPoolAddresses(\n mainnetClient,\n AaveV3Ethereum.POOL_ADDRESSES_PROVIDER,\n );\n const reserveTokens = await getReserveTokens(\n mainnetClient,\n contracts.pool,\n );\n const reserveConfigs = await getReserveConfigurations(\n mainnetClient,\n contracts.pool,\n reserveTokens,\n );\n console.log(reserveConfigs);\n });\n}\n","import { getAddressBookReferences } from \"@aave-dao/aave-address-book/utils\";\nimport {\n getMdContractName,\n getPayloadsController,\n makePayloadExecutableOnTestClient,\n renderTenderlyReport,\n tenderly_createVnet,\n IPayloadsController_ABI,\n} from \"@aave-dao/toolbox\";\nimport { Command, Option } from \"@commander-js/extra-typings\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport {\n Address,\n encodeFunctionData,\n Hex,\n isAddress,\n parseAbi,\n zeroAddress,\n} from \"viem\";\nimport { toAccount } from \"viem/accounts\";\nimport { readContract } from \"viem/actions\";\n\nexport function registerSeatbeltReport(program: Command) {\n program\n .command(\"seatbelt-report\")\n .description(\"generates a seatbelt report for the payload\")\n .addOption(new Option(\"-c,--chainId <number>\").makeOptionMandatory())\n .addOption(new Option(\"--pi,--payloadId <number>\"))\n .addOption(new Option(\"--pa, --payloadAddress <address>\"))\n .addOption(new Option(\"--pb,--payloadBytecode <hex>\"))\n .addOption(new Option(\"--pcd,--payloadCalldata <hex>\"))\n .addOption(\n new Option(\"--pc, --payloadsController <address>\").makeOptionMandatory(),\n )\n .addOption(\n new Option(\"-o, --output <output path>\").default(\"./reports/seatbelt/\"),\n )\n .addOption(\n new Option(\n \"-t, --tenderlyAccessToken <string>\",\n \"defaults to env.TENDERLY_ACCESS_TOKEN\",\n ),\n )\n .addOption(\n new Option(\n \"-a, --tenderlyAccountSlug <string>\",\n \"defaults to env.TENDERLY_ACCOUNT_SLUG\",\n ),\n )\n .addOption(\n new Option(\n \"-p, --tenderlyProjectSlug <string>\",\n \"defaults to env.TENDERLY_PROJECT_SLUG\",\n ),\n )\n .addOption(\n new Option(\n \"-e, --etherscanApiKey <string>\",\n \"defaults to env.ETHERSCAN_API_KEY\",\n ),\n )\n .action(\n async ({\n chainId,\n tenderlyAccessToken,\n tenderlyAccountSlug,\n tenderlyProjectSlug,\n output,\n payloadId,\n payloadAddress,\n payloadBytecode,\n payloadCalldata,\n payloadsController,\n }) => {\n const vnet = await tenderly_createVnet(\n {\n baseChainId: Number(chainId),\n forkChainId: 3030,\n slug: `${Math.floor(Math.random() * 1000)}acli-aave-dao-vnet-${chainId}`,\n displayName: \"seatbelt\",\n },\n {\n accessToken:\n tenderlyAccessToken || process.env.TENDERLY_ACCESS_TOKEN!,\n accountSlug:\n tenderlyAccountSlug || process.env.TENDERLY_ACCOUNT_SLUG!,\n projectSlug:\n tenderlyProjectSlug || process.env.TENDERLY_PROJECT_SLUG!,\n },\n );\n const controllerContract = getPayloadsController(\n vnet.walletClient,\n payloadsController as Address,\n );\n\n // the current \"count\" will be the id after creation\n let currentId: number = 0;\n\n // in case the controller is permissioned we fetch the manager\n let sender: Address = zeroAddress;\n try {\n sender = await readContract(vnet.testClient, {\n address: controllerContract.address,\n abi: parseAbi([\n \"function payloadsManager() external view returns (address)\",\n ]),\n functionName: \"payloadsManager\",\n });\n } catch (e) {}\n if (payloadId) {\n currentId = Number(payloadId);\n }\n if (payloadBytecode) {\n vnet.testClient.setCode({\n address: \"0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8\",\n bytecode: payloadBytecode as Hex,\n });\n payloadAddress = \"0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8\";\n }\n if (payloadCalldata) {\n currentId = await controllerContract.read.getPayloadsCount();\n await vnet.walletClient.sendTransaction({\n account: toAccount(sender),\n chain: vnet.walletClient.chain,\n to: payloadsController as Address,\n data: payloadCalldata as Hex,\n });\n }\n if (payloadAddress) {\n currentId = await controllerContract.read.getPayloadsCount();\n const payload = {\n target: payloadAddress as Address,\n accessLevel: 1,\n callData: \"0x\",\n withDelegateCall: true,\n signature: \"execute()\",\n value: 0n,\n } as const;\n await controllerContract.write.createPayload([[payload]], {\n account: toAccount(sender),\n chain: vnet.walletClient.chain,\n });\n }\n\n await makePayloadExecutableOnTestClient(\n vnet.testClient,\n payloadsController as Address,\n currentId as number,\n );\n\n // simulate executing the payload\n const simResult = await vnet.simulate({\n network_id: chainId.toString(),\n from: sender,\n to: payloadsController,\n input: encodeFunctionData({\n abi: IPayloadsController_ABI,\n functionName: \"executePayload\",\n args: [currentId],\n }),\n block_number: null,\n transaction_index: 0,\n gas: 30_000_000,\n gas_price: \"0\",\n value: \"0\",\n access_list: [],\n generate_access_list: true,\n save: true,\n source: \"dashboard\",\n });\n\n // after we simulate the execution, we also execute it\n // this way when we query the chain, we can access data as if it was already executed\n await controllerContract.write.executePayload([currentId], {\n account: toAccount(sender),\n chain: vnet.walletClient.chain,\n });\n\n const report = await renderTenderlyReport({\n client: vnet.walletClient,\n sim: simResult,\n payloadId: currentId,\n payload: await controllerContract.read.getPayloadById([currentId]),\n onchainLogs: {} as any,\n config: {\n etherscanApiKey: process.env.ETHERSCAN_API_KEY!,\n },\n getContractName: (sim, address) => {\n const references = getAddressBookReferences(\n address,\n Number(sim.simulation.network_id),\n );\n if (references.length > 0)\n return flagAsKnown(\n getMdContractName(sim.contracts, address),\n references[0],\n );\n return getMdContractName(sim.contracts, address);\n },\n });\n\n const filePath = `${output}/${chainId}_${payloadsController}`;\n mkdirSync(filePath, { recursive: true });\n writeFileSync(`${filePath}/${currentId}.md`, report.report);\n // await vnet.delete();\n },\n );\n}\n\nfunction flagAsKnown(value: string, reference: string) {\n return `${value} [:ghost:](https://github.com/aave-dao/aave-address-book \"${reference}\")`;\n}\n"],"mappings":"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","names":["Command","program","Option","program","Option","answer","key","Option","program","Option","program","program","getPayloadsController","makePayloadExecutableOnTestClient","tenderly_createVnet","Option","mkdirSync","writeFileSync","parseAbi","zeroAddress","toAccount","readContract","program","Command"]}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@aave-dao/cli",
3
+ "version": "0.2.0",
4
+ "main": "./dist/index.mjs",
5
+ "sideEffects": false,
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/aave-dao/toolkit.git",
10
+ "directory": "packages/cli"
11
+ },
12
+ "files": [
13
+ "dist/**",
14
+ "README.md"
15
+ ],
16
+ "type": "module",
17
+ "bin": {
18
+ "cli": "dist/index.js"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.15.21",
22
+ "tsup": "8.4.0",
23
+ "typescript": "^5.8.3"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "dependencies": {
29
+ "@aave-dao/aave-address-book": "^4.30.3",
30
+ "@commander-js/extra-typings": "^13.1.0",
31
+ "@inquirer/prompts": "^7.3.2",
32
+ "dotenv": "^16.4.7",
33
+ "viem": "^2.45.0",
34
+ "@aave-dao/toolbox": "0.4.0"
35
+ },
36
+ "scripts": {
37
+ "build": "tsup src/index.ts",
38
+ "dev": "tsup src/index.ts --watch",
39
+ "start": "node dist/index.js",
40
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
41
+ }
42
+ }