clanker-sdk 3.9.5 → 3.9.7

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,1353 @@
1
+ #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // node_modules/tsup/assets/esm_shims.js
13
+ var init_esm_shims = __esm({
14
+ "node_modules/tsup/assets/esm_shims.js"() {
15
+ "use strict";
16
+ }
17
+ });
18
+
19
+ // src/constants.ts
20
+ var WETH_ADDRESS, CLANKER_FACTORY_V3_1;
21
+ var init_constants = __esm({
22
+ "src/constants.ts"() {
23
+ "use strict";
24
+ init_esm_shims();
25
+ WETH_ADDRESS = "0x4200000000000000000000000000000000000006";
26
+ CLANKER_FACTORY_V3_1 = "0x2A787b2362021cC3eEa3C24C4748a6cD5B687382";
27
+ }
28
+ });
29
+
30
+ // src/abis/Clanker_V3_1.ts
31
+ var Clanker_v3_1_abi;
32
+ var init_Clanker_V3_1 = __esm({
33
+ "src/abis/Clanker_V3_1.ts"() {
34
+ "use strict";
35
+ init_esm_shims();
36
+ Clanker_v3_1_abi = [
37
+ {
38
+ inputs: [{ internalType: "address", name: "owner_", type: "address" }],
39
+ stateMutability: "nonpayable",
40
+ type: "constructor"
41
+ },
42
+ { inputs: [], name: "Deprecated", type: "error" },
43
+ { inputs: [], name: "InvalidCreatorInfo", type: "error" },
44
+ { inputs: [], name: "InvalidCreatorReward", type: "error" },
45
+ { inputs: [], name: "InvalidInterfaceInfo", type: "error" },
46
+ { inputs: [], name: "InvalidTick", type: "error" },
47
+ { inputs: [], name: "InvalidVaultConfiguration", type: "error" },
48
+ { inputs: [], name: "NotFound", type: "error" },
49
+ { inputs: [], name: "OnlyNonOriginatingChains", type: "error" },
50
+ { inputs: [], name: "OnlyOriginatingChain", type: "error" },
51
+ {
52
+ inputs: [{ internalType: "address", name: "owner", type: "address" }],
53
+ name: "OwnableInvalidOwner",
54
+ type: "error"
55
+ },
56
+ {
57
+ inputs: [{ internalType: "address", name: "account", type: "address" }],
58
+ name: "OwnableUnauthorizedAccount",
59
+ type: "error"
60
+ },
61
+ { inputs: [], name: "ReentrancyGuardReentrantCall", type: "error" },
62
+ { inputs: [], name: "Unauthorized", type: "error" },
63
+ { inputs: [], name: "ZeroTeamRewardRecipient", type: "error" },
64
+ {
65
+ anonymous: false,
66
+ inputs: [
67
+ { indexed: false, internalType: "address", name: "oldClankerDeployer", type: "address" },
68
+ { indexed: false, internalType: "address", name: "newClankerDeployer", type: "address" }
69
+ ],
70
+ name: "ClankerDeployerUpdated",
71
+ type: "event"
72
+ },
73
+ {
74
+ anonymous: false,
75
+ inputs: [
76
+ { indexed: false, internalType: "address", name: "oldLocker", type: "address" },
77
+ { indexed: false, internalType: "address", name: "newLocker", type: "address" }
78
+ ],
79
+ name: "LiquidityLockerUpdated",
80
+ type: "event"
81
+ },
82
+ {
83
+ anonymous: false,
84
+ inputs: [
85
+ { indexed: true, internalType: "address", name: "previousOwner", type: "address" },
86
+ { indexed: true, internalType: "address", name: "newOwner", type: "address" }
87
+ ],
88
+ name: "OwnershipTransferred",
89
+ type: "event"
90
+ },
91
+ {
92
+ anonymous: false,
93
+ inputs: [
94
+ { indexed: false, internalType: "address", name: "admin", type: "address" },
95
+ { indexed: false, internalType: "bool", name: "isAdmin", type: "bool" }
96
+ ],
97
+ name: "SetAdmin",
98
+ type: "event"
99
+ },
100
+ {
101
+ anonymous: false,
102
+ inputs: [{ indexed: false, internalType: "bool", name: "deprecated", type: "bool" }],
103
+ name: "SetDeprecated",
104
+ type: "event"
105
+ },
106
+ {
107
+ anonymous: false,
108
+ inputs: [
109
+ { indexed: true, internalType: "address", name: "tokenAddress", type: "address" },
110
+ { indexed: true, internalType: "address", name: "creatorAdmin", type: "address" },
111
+ { indexed: true, internalType: "address", name: "interfaceAdmin", type: "address" },
112
+ { indexed: false, internalType: "address", name: "creatorRewardRecipient", type: "address" },
113
+ {
114
+ indexed: false,
115
+ internalType: "address",
116
+ name: "interfaceRewardRecipient",
117
+ type: "address"
118
+ },
119
+ { indexed: false, internalType: "uint256", name: "positionId", type: "uint256" },
120
+ { indexed: false, internalType: "string", name: "name", type: "string" },
121
+ { indexed: false, internalType: "string", name: "symbol", type: "string" },
122
+ {
123
+ indexed: false,
124
+ internalType: "int24",
125
+ name: "startingTickIfToken0IsNewToken",
126
+ type: "int24"
127
+ },
128
+ { indexed: false, internalType: "string", name: "metadata", type: "string" },
129
+ { indexed: false, internalType: "uint256", name: "amountTokensBought", type: "uint256" },
130
+ { indexed: false, internalType: "uint256", name: "vaultDuration", type: "uint256" },
131
+ { indexed: false, internalType: "uint8", name: "vaultPercentage", type: "uint8" },
132
+ { indexed: false, internalType: "address", name: "msgSender", type: "address" }
133
+ ],
134
+ name: "TokenCreated",
135
+ type: "event"
136
+ },
137
+ {
138
+ anonymous: false,
139
+ inputs: [
140
+ { indexed: false, internalType: "address", name: "oldVault", type: "address" },
141
+ { indexed: false, internalType: "address", name: "newVault", type: "address" }
142
+ ],
143
+ name: "VaultUpdated",
144
+ type: "event"
145
+ },
146
+ {
147
+ inputs: [],
148
+ name: "MAX_CREATOR_REWARD",
149
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
150
+ stateMutability: "view",
151
+ type: "function"
152
+ },
153
+ {
154
+ inputs: [],
155
+ name: "MAX_TICK",
156
+ outputs: [{ internalType: "int24", name: "", type: "int24" }],
157
+ stateMutability: "view",
158
+ type: "function"
159
+ },
160
+ {
161
+ inputs: [],
162
+ name: "MAX_VAULT_PERCENTAGE",
163
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
164
+ stateMutability: "view",
165
+ type: "function"
166
+ },
167
+ {
168
+ inputs: [],
169
+ name: "POOL_FEE",
170
+ outputs: [{ internalType: "uint24", name: "", type: "uint24" }],
171
+ stateMutability: "view",
172
+ type: "function"
173
+ },
174
+ {
175
+ inputs: [],
176
+ name: "TICK_SPACING",
177
+ outputs: [{ internalType: "int24", name: "", type: "int24" }],
178
+ stateMutability: "view",
179
+ type: "function"
180
+ },
181
+ {
182
+ inputs: [],
183
+ name: "TOKEN_SUPPLY",
184
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
185
+ stateMutability: "view",
186
+ type: "function"
187
+ },
188
+ {
189
+ inputs: [{ internalType: "address", name: "", type: "address" }],
190
+ name: "admins",
191
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
192
+ stateMutability: "view",
193
+ type: "function"
194
+ },
195
+ {
196
+ inputs: [{ internalType: "address", name: "token", type: "address" }],
197
+ name: "claimRewards",
198
+ outputs: [],
199
+ stateMutability: "nonpayable",
200
+ type: "function"
201
+ },
202
+ {
203
+ inputs: [
204
+ {
205
+ components: [
206
+ {
207
+ components: [
208
+ { internalType: "string", name: "name", type: "string" },
209
+ { internalType: "string", name: "symbol", type: "string" },
210
+ { internalType: "bytes32", name: "salt", type: "bytes32" },
211
+ { internalType: "string", name: "image", type: "string" },
212
+ { internalType: "string", name: "metadata", type: "string" },
213
+ { internalType: "string", name: "context", type: "string" },
214
+ { internalType: "uint256", name: "originatingChainId", type: "uint256" }
215
+ ],
216
+ internalType: "struct IClanker.TokenConfig",
217
+ name: "tokenConfig",
218
+ type: "tuple"
219
+ },
220
+ {
221
+ components: [
222
+ { internalType: "uint8", name: "vaultPercentage", type: "uint8" },
223
+ { internalType: "uint256", name: "vaultDuration", type: "uint256" }
224
+ ],
225
+ internalType: "struct IClanker.VaultConfig",
226
+ name: "vaultConfig",
227
+ type: "tuple"
228
+ },
229
+ {
230
+ components: [
231
+ { internalType: "address", name: "pairedToken", type: "address" },
232
+ { internalType: "int24", name: "tickIfToken0IsNewToken", type: "int24" }
233
+ ],
234
+ internalType: "struct IClanker.PoolConfig",
235
+ name: "poolConfig",
236
+ type: "tuple"
237
+ },
238
+ {
239
+ components: [
240
+ { internalType: "uint24", name: "pairedTokenPoolFee", type: "uint24" },
241
+ { internalType: "uint256", name: "pairedTokenSwapAmountOutMinimum", type: "uint256" }
242
+ ],
243
+ internalType: "struct IClanker.InitialBuyConfig",
244
+ name: "initialBuyConfig",
245
+ type: "tuple"
246
+ },
247
+ {
248
+ components: [
249
+ { internalType: "uint256", name: "creatorReward", type: "uint256" },
250
+ { internalType: "address", name: "creatorAdmin", type: "address" },
251
+ { internalType: "address", name: "creatorRewardRecipient", type: "address" },
252
+ { internalType: "address", name: "interfaceAdmin", type: "address" },
253
+ { internalType: "address", name: "interfaceRewardRecipient", type: "address" }
254
+ ],
255
+ internalType: "struct IClanker.RewardsConfig",
256
+ name: "rewardsConfig",
257
+ type: "tuple"
258
+ }
259
+ ],
260
+ internalType: "struct IClanker.DeploymentConfig",
261
+ name: "deploymentConfig",
262
+ type: "tuple"
263
+ }
264
+ ],
265
+ name: "deployToken",
266
+ outputs: [
267
+ { internalType: "address", name: "tokenAddress", type: "address" },
268
+ { internalType: "uint256", name: "positionId", type: "uint256" }
269
+ ],
270
+ stateMutability: "payable",
271
+ type: "function"
272
+ },
273
+ {
274
+ inputs: [
275
+ {
276
+ components: [
277
+ {
278
+ components: [
279
+ { internalType: "string", name: "name", type: "string" },
280
+ { internalType: "string", name: "symbol", type: "string" },
281
+ { internalType: "bytes32", name: "salt", type: "bytes32" },
282
+ { internalType: "string", name: "image", type: "string" },
283
+ { internalType: "string", name: "metadata", type: "string" },
284
+ { internalType: "string", name: "context", type: "string" },
285
+ { internalType: "uint256", name: "originatingChainId", type: "uint256" }
286
+ ],
287
+ internalType: "struct IClanker.TokenConfig",
288
+ name: "tokenConfig",
289
+ type: "tuple"
290
+ },
291
+ {
292
+ components: [
293
+ { internalType: "uint8", name: "vaultPercentage", type: "uint8" },
294
+ { internalType: "uint256", name: "vaultDuration", type: "uint256" }
295
+ ],
296
+ internalType: "struct IClanker.VaultConfig",
297
+ name: "vaultConfig",
298
+ type: "tuple"
299
+ },
300
+ {
301
+ components: [
302
+ { internalType: "address", name: "pairedToken", type: "address" },
303
+ { internalType: "int24", name: "tickIfToken0IsNewToken", type: "int24" }
304
+ ],
305
+ internalType: "struct IClanker.PoolConfig",
306
+ name: "poolConfig",
307
+ type: "tuple"
308
+ },
309
+ {
310
+ components: [
311
+ { internalType: "uint24", name: "pairedTokenPoolFee", type: "uint24" },
312
+ { internalType: "uint256", name: "pairedTokenSwapAmountOutMinimum", type: "uint256" }
313
+ ],
314
+ internalType: "struct IClanker.InitialBuyConfig",
315
+ name: "initialBuyConfig",
316
+ type: "tuple"
317
+ },
318
+ {
319
+ components: [
320
+ { internalType: "uint256", name: "creatorReward", type: "uint256" },
321
+ { internalType: "address", name: "creatorAdmin", type: "address" },
322
+ { internalType: "address", name: "creatorRewardRecipient", type: "address" },
323
+ { internalType: "address", name: "interfaceAdmin", type: "address" },
324
+ { internalType: "address", name: "interfaceRewardRecipient", type: "address" }
325
+ ],
326
+ internalType: "struct IClanker.RewardsConfig",
327
+ name: "rewardsConfig",
328
+ type: "tuple"
329
+ }
330
+ ],
331
+ internalType: "struct IClanker.DeploymentConfig",
332
+ name: "deploymentConfig",
333
+ type: "tuple"
334
+ },
335
+ { internalType: "address", name: "teamRewardRecipient", type: "address" }
336
+ ],
337
+ name: "deployTokenWithCustomTeamRewardRecipient",
338
+ outputs: [
339
+ { internalType: "address", name: "tokenAddress", type: "address" },
340
+ { internalType: "uint256", name: "positionId", type: "uint256" }
341
+ ],
342
+ stateMutability: "payable",
343
+ type: "function"
344
+ },
345
+ {
346
+ inputs: [
347
+ {
348
+ components: [
349
+ { internalType: "string", name: "name", type: "string" },
350
+ { internalType: "string", name: "symbol", type: "string" },
351
+ { internalType: "bytes32", name: "salt", type: "bytes32" },
352
+ { internalType: "string", name: "image", type: "string" },
353
+ { internalType: "string", name: "metadata", type: "string" },
354
+ { internalType: "string", name: "context", type: "string" },
355
+ { internalType: "uint256", name: "originatingChainId", type: "uint256" }
356
+ ],
357
+ internalType: "struct IClanker.TokenConfig",
358
+ name: "tokenConfig",
359
+ type: "tuple"
360
+ },
361
+ { internalType: "address", name: "tokenAdmin", type: "address" }
362
+ ],
363
+ name: "deployTokenZeroSupply",
364
+ outputs: [{ internalType: "address", name: "tokenAddress", type: "address" }],
365
+ stateMutability: "nonpayable",
366
+ type: "function"
367
+ },
368
+ {
369
+ inputs: [{ internalType: "address", name: "", type: "address" }],
370
+ name: "deploymentInfoForToken",
371
+ outputs: [
372
+ { internalType: "address", name: "token", type: "address" },
373
+ { internalType: "uint256", name: "positionId", type: "uint256" },
374
+ { internalType: "address", name: "locker", type: "address" }
375
+ ],
376
+ stateMutability: "view",
377
+ type: "function"
378
+ },
379
+ {
380
+ inputs: [],
381
+ name: "deprecated",
382
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
383
+ stateMutability: "view",
384
+ type: "function"
385
+ },
386
+ {
387
+ inputs: [{ internalType: "address", name: "user", type: "address" }],
388
+ name: "getTokensDeployedByUser",
389
+ outputs: [
390
+ {
391
+ components: [
392
+ { internalType: "address", name: "token", type: "address" },
393
+ { internalType: "uint256", name: "positionId", type: "uint256" },
394
+ { internalType: "address", name: "locker", type: "address" }
395
+ ],
396
+ internalType: "struct IClanker.DeploymentInfo[]",
397
+ name: "",
398
+ type: "tuple[]"
399
+ }
400
+ ],
401
+ stateMutability: "view",
402
+ type: "function"
403
+ },
404
+ {
405
+ inputs: [
406
+ { internalType: "address", name: "uniswapV3Factory_", type: "address" },
407
+ { internalType: "address", name: "positionManager_", type: "address" },
408
+ { internalType: "address", name: "swapRouter_", type: "address" },
409
+ { internalType: "address", name: "weth_", type: "address" },
410
+ { internalType: "address", name: "liquidityLocker_", type: "address" },
411
+ { internalType: "address", name: "vault_", type: "address" }
412
+ ],
413
+ name: "initialize",
414
+ outputs: [],
415
+ stateMutability: "nonpayable",
416
+ type: "function"
417
+ },
418
+ {
419
+ inputs: [],
420
+ name: "liquidityLocker",
421
+ outputs: [{ internalType: "contract ILpLockerv2", name: "", type: "address" }],
422
+ stateMutability: "view",
423
+ type: "function"
424
+ },
425
+ {
426
+ inputs: [],
427
+ name: "owner",
428
+ outputs: [{ internalType: "address", name: "", type: "address" }],
429
+ stateMutability: "view",
430
+ type: "function"
431
+ },
432
+ {
433
+ inputs: [],
434
+ name: "positionManager",
435
+ outputs: [{ internalType: "contract INonfungiblePositionManager", name: "", type: "address" }],
436
+ stateMutability: "view",
437
+ type: "function"
438
+ },
439
+ {
440
+ inputs: [],
441
+ name: "renounceOwnership",
442
+ outputs: [],
443
+ stateMutability: "nonpayable",
444
+ type: "function"
445
+ },
446
+ {
447
+ inputs: [
448
+ { internalType: "address", name: "admin", type: "address" },
449
+ { internalType: "bool", name: "isAdmin", type: "bool" }
450
+ ],
451
+ name: "setAdmin",
452
+ outputs: [],
453
+ stateMutability: "nonpayable",
454
+ type: "function"
455
+ },
456
+ {
457
+ inputs: [{ internalType: "bool", name: "deprecated_", type: "bool" }],
458
+ name: "setDeprecated",
459
+ outputs: [],
460
+ stateMutability: "nonpayable",
461
+ type: "function"
462
+ },
463
+ {
464
+ inputs: [],
465
+ name: "swapRouter",
466
+ outputs: [{ internalType: "contract ISwapRouter", name: "", type: "address" }],
467
+ stateMutability: "view",
468
+ type: "function"
469
+ },
470
+ {
471
+ inputs: [
472
+ { internalType: "address", name: "", type: "address" },
473
+ { internalType: "uint256", name: "", type: "uint256" }
474
+ ],
475
+ name: "tokensDeployedByUsers",
476
+ outputs: [
477
+ { internalType: "address", name: "token", type: "address" },
478
+ { internalType: "uint256", name: "positionId", type: "uint256" },
479
+ { internalType: "address", name: "locker", type: "address" }
480
+ ],
481
+ stateMutability: "view",
482
+ type: "function"
483
+ },
484
+ {
485
+ inputs: [{ internalType: "address", name: "newOwner", type: "address" }],
486
+ name: "transferOwnership",
487
+ outputs: [],
488
+ stateMutability: "nonpayable",
489
+ type: "function"
490
+ },
491
+ {
492
+ inputs: [],
493
+ name: "uniswapV3Factory",
494
+ outputs: [{ internalType: "contract IUniswapV3Factory", name: "", type: "address" }],
495
+ stateMutability: "view",
496
+ type: "function"
497
+ },
498
+ {
499
+ inputs: [{ internalType: "address", name: "newLocker", type: "address" }],
500
+ name: "updateLiquidityLocker",
501
+ outputs: [],
502
+ stateMutability: "nonpayable",
503
+ type: "function"
504
+ },
505
+ {
506
+ inputs: [{ internalType: "address", name: "newVault", type: "address" }],
507
+ name: "updateVault",
508
+ outputs: [],
509
+ stateMutability: "nonpayable",
510
+ type: "function"
511
+ },
512
+ {
513
+ inputs: [],
514
+ name: "vault",
515
+ outputs: [{ internalType: "contract IClankerVault", name: "", type: "address" }],
516
+ stateMutability: "view",
517
+ type: "function"
518
+ },
519
+ {
520
+ inputs: [],
521
+ name: "weth",
522
+ outputs: [{ internalType: "address", name: "", type: "address" }],
523
+ stateMutability: "view",
524
+ type: "function"
525
+ }
526
+ ];
527
+ }
528
+ });
529
+
530
+ // src/types.ts
531
+ var init_types = __esm({
532
+ "src/types.ts"() {
533
+ "use strict";
534
+ init_esm_shims();
535
+ }
536
+ });
537
+
538
+ // src/index.ts
539
+ import {
540
+ parseEther,
541
+ parseUnits,
542
+ stringify,
543
+ parseEventLogs,
544
+ encodeFunctionData
545
+ } from "viem";
546
+ import { simulateContract, writeContract, readContract } from "viem/actions";
547
+ var ERC20_DECIMALS_ABI, UNIV3_FACTORY_ABI, UNIV3_POOL_ABI, UNIV3_FACTORY, FEE_TIERS, Clanker;
548
+ var init_index = __esm({
549
+ "src/index.ts"() {
550
+ "use strict";
551
+ init_esm_shims();
552
+ init_constants();
553
+ init_Clanker_V3_1();
554
+ init_types();
555
+ ERC20_DECIMALS_ABI = [
556
+ {
557
+ inputs: [],
558
+ name: "decimals",
559
+ outputs: [{ type: "uint8", name: "" }],
560
+ stateMutability: "view",
561
+ type: "function"
562
+ }
563
+ ];
564
+ UNIV3_FACTORY_ABI = [
565
+ {
566
+ inputs: [
567
+ { internalType: "address", name: "tokenA", type: "address" },
568
+ { internalType: "address", name: "tokenB", type: "address" },
569
+ { internalType: "uint24", name: "fee", type: "uint24" }
570
+ ],
571
+ name: "getPool",
572
+ outputs: [{ internalType: "address", name: "", type: "address" }],
573
+ stateMutability: "view",
574
+ type: "function"
575
+ }
576
+ ];
577
+ UNIV3_POOL_ABI = [
578
+ {
579
+ inputs: [],
580
+ name: "liquidity",
581
+ outputs: [{ internalType: "uint128", name: "", type: "uint128" }],
582
+ stateMutability: "view",
583
+ type: "function"
584
+ },
585
+ {
586
+ inputs: [],
587
+ name: "slot0",
588
+ outputs: [
589
+ { internalType: "uint160", name: "sqrtPriceX96", type: "uint160" },
590
+ { internalType: "int24", name: "tick", type: "int24" },
591
+ { internalType: "uint16", name: "observationIndex", type: "uint16" },
592
+ { internalType: "uint16", name: "observationCardinality", type: "uint16" },
593
+ { internalType: "uint16", name: "observationCardinalityNext", type: "uint16" },
594
+ { internalType: "uint8", name: "feeProtocol", type: "uint8" },
595
+ { internalType: "bool", name: "unlocked", type: "bool" }
596
+ ],
597
+ stateMutability: "view",
598
+ type: "function"
599
+ }
600
+ ];
601
+ UNIV3_FACTORY = "0x33128a8fC17869897dcE68Ed026d694621f6FDfD";
602
+ FEE_TIERS = [100, 500, 3e3, 1e4];
603
+ Clanker = class {
604
+ wallet;
605
+ factoryAddress;
606
+ publicClient;
607
+ constructor(config2) {
608
+ this.wallet = config2.wallet;
609
+ this.publicClient = config2.publicClient;
610
+ this.factoryAddress = config2.factoryAddress ?? CLANKER_FACTORY_V3_1;
611
+ }
612
+ // Get quote token decimals
613
+ async getQuoteTokenDecimals(quoteToken) {
614
+ try {
615
+ const decimals = await readContract(this.publicClient, {
616
+ address: quoteToken,
617
+ abi: ERC20_DECIMALS_ABI,
618
+ functionName: "decimals"
619
+ });
620
+ return decimals;
621
+ } catch (error) {
622
+ console.warn(`Failed to fetch decimals for quote token ${quoteToken}, defaulting to 18:`, error);
623
+ return 18;
624
+ }
625
+ }
626
+ // Find the most liquid pool between WETH and quote token
627
+ async findMostLiquidPool(quoteToken) {
628
+ const pools = await Promise.all(
629
+ FEE_TIERS.map(async (fee) => {
630
+ try {
631
+ const poolAddress = await readContract(this.publicClient, {
632
+ address: UNIV3_FACTORY,
633
+ abi: UNIV3_FACTORY_ABI,
634
+ functionName: "getPool",
635
+ args: [WETH_ADDRESS, quoteToken, fee]
636
+ });
637
+ if (poolAddress === "0x0000000000000000000000000000000000000000") {
638
+ return { fee, liquidity: 0n, sqrtPriceX96: 0n };
639
+ }
640
+ const [liquidity, slot0] = await Promise.all([
641
+ readContract(this.publicClient, {
642
+ address: poolAddress,
643
+ abi: UNIV3_POOL_ABI,
644
+ functionName: "liquidity"
645
+ }),
646
+ readContract(this.publicClient, {
647
+ address: poolAddress,
648
+ abi: UNIV3_POOL_ABI,
649
+ functionName: "slot0"
650
+ })
651
+ ]);
652
+ return { fee, liquidity, sqrtPriceX96: slot0[0] };
653
+ } catch (error) {
654
+ console.warn(`Failed to get pool info for fee tier ${fee}:`, error);
655
+ return { fee, liquidity: 0n, sqrtPriceX96: 0n };
656
+ }
657
+ })
658
+ );
659
+ const mostLiquidPool = pools.reduce(
660
+ (max, current) => current.liquidity > max.liquidity ? current : max
661
+ );
662
+ if (mostLiquidPool.liquidity === 0n) {
663
+ console.warn("No liquid pool found, defaulting to 1% fee tier");
664
+ return { fee: 1e4, sqrtPriceX96: 0n };
665
+ }
666
+ return { fee: mostLiquidPool.fee, sqrtPriceX96: mostLiquidPool.sqrtPriceX96 };
667
+ }
668
+ // Calculate minimum output amount for WETH -> quote token swap
669
+ calculateMinimumOutput(ethAmount, sqrtPriceX96, quoteDecimals, slippagePercent) {
670
+ if (sqrtPriceX96 === 0n) {
671
+ return 0n;
672
+ }
673
+ const Q96 = BigInt("79228162514264337593543950336");
674
+ const price = (Number(sqrtPriceX96) / Number(Q96)) ** 2;
675
+ const ethDecimals = 18;
676
+ const ethAmountInEth = Number(ethAmount) / 10 ** ethDecimals;
677
+ const expectedOutput = ethAmountInEth * price;
678
+ const minimumOutput = expectedOutput * (1 - slippagePercent / 100);
679
+ return BigInt(Math.floor(minimumOutput * 10 ** quoteDecimals));
680
+ }
681
+ // Calculate tick based on quote token and token ordering
682
+ async calculateTickForQuoteToken(quoteToken, marketCap) {
683
+ const quoteDecimals = await this.getQuoteTokenDecimals(quoteToken);
684
+ console.log("Quote token decimals:", quoteDecimals);
685
+ const tokenDecimals = 18;
686
+ const totalSupply = BigInt(1e11) * BigInt(10) ** BigInt(tokenDecimals);
687
+ const priceInQuoteToken = Number(marketCap) / Number(totalSupply);
688
+ console.log("Price in quote token:", priceInQuoteToken);
689
+ console.log("Market cap in quote token units:", Number(marketCap) / 10 ** quoteDecimals);
690
+ const logBase = 1.0001;
691
+ const tickSpacing = 200;
692
+ const dummyTokenAddress = "0xffffffffffffffffffffffffffffffffffffffff";
693
+ const isToken0 = dummyTokenAddress.toLowerCase() < quoteToken.toLowerCase();
694
+ console.log("Is new token token0?", isToken0);
695
+ const priceForTick = isToken0 ? priceInQuoteToken : 1 / priceInQuoteToken;
696
+ let rawTick = Math.floor(Math.log(priceForTick) / Math.log(logBase));
697
+ if (!isToken0) {
698
+ rawTick = -rawTick;
699
+ }
700
+ console.log("Raw tick (before spacing):", rawTick);
701
+ const initialTick = Math.floor(rawTick / tickSpacing) * tickSpacing;
702
+ console.log("Final tick (rounded to spacing):", initialTick);
703
+ const actualPrice = Math.pow(logBase, isToken0 ? initialTick : -initialTick);
704
+ console.log("Actual price from tick:", actualPrice);
705
+ const finalPrice = isToken0 ? actualPrice : 1 / actualPrice;
706
+ const actualMarketCap = finalPrice * Number(totalSupply) / Math.pow(10, tokenDecimals);
707
+ console.log("Actual market cap in quote token:", actualMarketCap);
708
+ return initialTick;
709
+ }
710
+ handleError(error) {
711
+ const message = error instanceof Error ? error.message : String(error);
712
+ throw new Error(`Deployment failed: ${message}`);
713
+ }
714
+ async deploy(config2) {
715
+ if (!this.wallet?.account) {
716
+ throw new Error("Wallet account not configured");
717
+ }
718
+ try {
719
+ const rewardsConfig = config2.rewardsConfig;
720
+ const tick = await this.calculateTickForQuoteToken(
721
+ config2.poolConfig.pairedToken,
722
+ config2.poolConfig.initialMarketCapInPairedToken
723
+ );
724
+ const deploymentData = {
725
+ tokenConfig: {
726
+ name: config2.tokenConfig.name,
727
+ symbol: config2.tokenConfig.symbol,
728
+ salt: config2.tokenConfig.salt,
729
+ image: config2.tokenConfig.image,
730
+ metadata: stringify(config2.tokenConfig.metadata),
731
+ context: stringify(config2.tokenConfig.context),
732
+ originatingChainId: config2.tokenConfig.originatingChainId
733
+ },
734
+ vaultConfig: {
735
+ vaultPercentage: config2.vaultConfig?.vaultPercentage ?? 0,
736
+ vaultDuration: config2.vaultConfig?.vaultDuration ?? BigInt(0)
737
+ },
738
+ poolConfig: {
739
+ pairedToken: config2.poolConfig.pairedToken,
740
+ tickIfToken0IsNewToken: tick
741
+ },
742
+ initialBuyConfig: {
743
+ pairedTokenPoolFee: config2.initialBuyConfig?.pairedTokenPoolFee ?? 1e4,
744
+ pairedTokenSwapAmountOutMinimum: config2.initialBuyConfig?.pairedTokenSwapAmountOutMinimum ?? BigInt(0)
745
+ },
746
+ rewardsConfig: {
747
+ creatorReward: rewardsConfig.creatorReward,
748
+ creatorAdmin: rewardsConfig.creatorAdmin,
749
+ creatorRewardRecipient: rewardsConfig.creatorRewardRecipient,
750
+ interfaceAdmin: rewardsConfig.interfaceAdmin,
751
+ interfaceRewardRecipient: rewardsConfig.interfaceRewardRecipient
752
+ }
753
+ };
754
+ const { request } = await simulateContract(this.publicClient, {
755
+ address: this.factoryAddress,
756
+ abi: Clanker_v3_1_abi,
757
+ functionName: "deployToken",
758
+ args: [deploymentData],
759
+ value: config2.initialBuyConfig?.ethAmount ?? BigInt(0),
760
+ chain: this.publicClient.chain,
761
+ account: this.wallet.account
762
+ });
763
+ const hash = await writeContract(this.wallet, request);
764
+ const receipt = await this.publicClient.waitForTransactionReceipt({
765
+ hash
766
+ });
767
+ const [log] = parseEventLogs({
768
+ abi: Clanker_v3_1_abi,
769
+ eventName: "TokenCreated",
770
+ logs: receipt.logs
771
+ });
772
+ if (!log) {
773
+ throw new Error("No deployment event found");
774
+ }
775
+ return log.args.tokenAddress;
776
+ } catch (error) {
777
+ this.handleError(error);
778
+ }
779
+ }
780
+ async buildDeploymentConfig(cfg) {
781
+ const quoteToken = cfg.pool?.quoteToken ?? WETH_ADDRESS;
782
+ const quoteDecimals = await this.getQuoteTokenDecimals(quoteToken);
783
+ console.log("Quote token decimals:", quoteDecimals);
784
+ const marketCap = parseUnits(
785
+ cfg.pool?.initialMarketCap ?? "100",
786
+ quoteDecimals
787
+ );
788
+ const tick = await this.calculateTickForQuoteToken(
789
+ quoteToken,
790
+ marketCap
791
+ );
792
+ let initialBuyConfig = {
793
+ pairedTokenPoolFee: 1e4,
794
+ // Default to 1%
795
+ pairedTokenSwapAmountOutMinimum: BigInt(0),
796
+ ethAmount: void 0
797
+ };
798
+ if (cfg.devBuy) {
799
+ const ethAmount = parseEther(cfg.devBuy.ethAmount);
800
+ const { fee, sqrtPriceX96 } = await this.findMostLiquidPool(quoteToken);
801
+ const minOutput = this.calculateMinimumOutput(
802
+ ethAmount,
803
+ sqrtPriceX96,
804
+ quoteDecimals,
805
+ cfg.devBuy.maxSlippage ?? 5
806
+ );
807
+ initialBuyConfig = {
808
+ pairedTokenPoolFee: fee,
809
+ pairedTokenSwapAmountOutMinimum: minOutput,
810
+ ethAmount
811
+ };
812
+ console.log("Dev buy configuration:", {
813
+ ethAmount: cfg.devBuy.ethAmount,
814
+ fee,
815
+ minOutput: minOutput.toString()
816
+ });
817
+ }
818
+ const deployerAddress = this.wallet?.account?.address ?? "0x0000000000000000000000000000000000000000";
819
+ return {
820
+ tokenConfig: {
821
+ name: cfg.name,
822
+ symbol: cfg.symbol,
823
+ salt: cfg.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
824
+ image: cfg.image || "https://ipfs.io/ipfs/QmcjfTeK3tpK3MVCQuvEaXvSscrqbL3MwsEo8LdBTWabY4",
825
+ metadata: JSON.stringify(cfg.metadata || {
826
+ description: "Clanker Token",
827
+ socialMediaUrls: [],
828
+ auditUrls: []
829
+ }),
830
+ context: JSON.stringify(cfg.context || {
831
+ interface: "Clanker SDK",
832
+ platform: "Clanker",
833
+ messageId: "Clanker SDK",
834
+ id: "Clanker SDK"
835
+ }),
836
+ originatingChainId: BigInt(this.publicClient.chain.id)
837
+ },
838
+ poolConfig: {
839
+ pairedToken: quoteToken,
840
+ tickIfToken0IsNewToken: tick,
841
+ initialMarketCapInPairedToken: marketCap
842
+ },
843
+ vaultConfig: cfg.vault ? {
844
+ vaultPercentage: cfg.vault.percentage,
845
+ vaultDuration: BigInt(cfg.vault.durationInDays * 24 * 60 * 60)
846
+ } : {
847
+ vaultPercentage: 0,
848
+ vaultDuration: 0n
849
+ },
850
+ initialBuyConfig,
851
+ rewardsConfig: {
852
+ creatorReward: BigInt(40),
853
+ // Default to 40% creator reward
854
+ creatorAdmin: deployerAddress,
855
+ creatorRewardRecipient: deployerAddress,
856
+ interfaceAdmin: deployerAddress,
857
+ interfaceRewardRecipient: deployerAddress
858
+ }
859
+ };
860
+ }
861
+ /**
862
+ * Creates calldata (+ msg.value) **without** sending a transaction.
863
+ * This version no longer relies on viem's `simulateContract`, which
864
+ * was returning an object without `.data`. We now ABI-encode the
865
+ * call manually so `data` is always defined.
866
+ */
867
+ async prepareDeployToken(cfg) {
868
+ const deploymentConfig = await this.buildDeploymentConfig(cfg);
869
+ const data = encodeFunctionData({
870
+ abi: Clanker_v3_1_abi,
871
+ functionName: "deployToken",
872
+ args: [deploymentConfig]
873
+ });
874
+ const value = deploymentConfig.initialBuyConfig?.ethAmount ?? 0n;
875
+ return {
876
+ to: this.factoryAddress,
877
+ data,
878
+ // 0x-prefixed hex string (non-empty)
879
+ value
880
+ };
881
+ }
882
+ async deployToken(cfg) {
883
+ if (!this.wallet) throw new Error("Wallet client required for deployToken");
884
+ if (!this.wallet.account) throw new Error("Wallet account required for deployToken");
885
+ const tx = await this.prepareDeployToken(cfg);
886
+ const hash = await this.wallet.sendTransaction({
887
+ ...tx,
888
+ account: this.wallet.account,
889
+ chain: this.publicClient.chain
890
+ });
891
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
892
+ const [log] = parseEventLogs({
893
+ abi: Clanker_v3_1_abi,
894
+ eventName: "TokenCreated",
895
+ logs: receipt.logs
896
+ });
897
+ if (!log) throw new Error("No deployment event found");
898
+ return log.args.tokenAddress;
899
+ }
900
+ };
901
+ }
902
+ });
903
+
904
+ // src/cli/create-clanker.ts
905
+ var create_clanker_exports = {};
906
+ __export(create_clanker_exports, {
907
+ default: () => createClanker
908
+ });
909
+ import inquirer from "inquirer";
910
+ import { createPublicClient, createWalletClient, http } from "viem";
911
+ import { privateKeyToAccount } from "viem/accounts";
912
+ import { base } from "viem/chains";
913
+ import * as dotenv from "dotenv";
914
+ async function createClanker() {
915
+ const args = process.argv.slice(2);
916
+ if (args.length === 0 || args[0] !== "--create" && args[0] !== "create") {
917
+ console.log("\n\u{1F680} Clanker SDK CLI\n");
918
+ console.log("Available commands:");
919
+ console.log(" --create Create a new token");
920
+ console.log("\nExample:");
921
+ console.log(" npx clanker-sdk --create\n");
922
+ process.exit(0);
923
+ }
924
+ const PRIVATE_KEY = process.env.PRIVATE_KEY;
925
+ const FACTORY_ADDRESS = process.env.FACTORY_ADDRESS;
926
+ const RPC_URL = process.env.RPC_URL;
927
+ const WETH_ADDRESS2 = "0x4200000000000000000000000000000000000006";
928
+ const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
929
+ function checkEnvironment() {
930
+ const missingVars = [];
931
+ if (!PRIVATE_KEY) missingVars.push("PRIVATE_KEY");
932
+ if (!FACTORY_ADDRESS) missingVars.push("FACTORY_ADDRESS");
933
+ if (missingVars.length > 0) {
934
+ console.log("\n\u274C Missing required environment variables:");
935
+ console.log(missingVars.join(", "));
936
+ console.log("\n\u{1F4DD} Please create a .env file in your current directory with the following variables:");
937
+ console.log(`
938
+ Required:
939
+ PRIVATE_KEY=your_private_key_here
940
+ FACTORY_ADDRESS=factory_contract_address_here
941
+
942
+ Optional:
943
+ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
944
+ `);
945
+ console.log("\nMake sure to include the 0x prefix for addresses and private keys.");
946
+ console.log("Never share or commit your private key!\n");
947
+ return false;
948
+ }
949
+ if (!PRIVATE_KEY.startsWith("0x") || PRIVATE_KEY.length !== 66) {
950
+ console.log("\n\u274C Invalid PRIVATE_KEY format. It should:");
951
+ console.log("- Start with 0x");
952
+ console.log("- Be 64 characters long (plus 0x prefix)");
953
+ return false;
954
+ }
955
+ if (!FACTORY_ADDRESS.startsWith("0x") || FACTORY_ADDRESS.length !== 42) {
956
+ console.log("\n\u274C Invalid FACTORY_ADDRESS format. It should:");
957
+ console.log("- Start with 0x");
958
+ console.log("- Be 40 characters long (plus 0x prefix)");
959
+ return false;
960
+ }
961
+ return true;
962
+ }
963
+ const validateAddress = (input) => {
964
+ if (!input) return "Address cannot be empty";
965
+ if (!/^0x[a-fA-F0-9]{40}$/.test(input)) return "Invalid Ethereum address";
966
+ return true;
967
+ };
968
+ const validatePercentage = (input) => {
969
+ const num = Number(input);
970
+ if (isNaN(num)) return "Must be a number";
971
+ if (num < 0 || num > 100) return "Percentage must be between 0 and 100";
972
+ return true;
973
+ };
974
+ const validateSymbol = (input) => {
975
+ if (!input) return "Symbol cannot be empty";
976
+ if (!/^[A-Z0-9]+$/.test(input)) return "Symbol must contain only uppercase letters and numbers";
977
+ if (input.length > 10) return "Symbol must be 10 characters or less";
978
+ return true;
979
+ };
980
+ const validateIpfsUri = (input) => {
981
+ if (!input) return "Image URI cannot be empty";
982
+ if (!input.startsWith("ipfs://")) return "Image URI must start with ipfs://";
983
+ return true;
984
+ };
985
+ const validateAmount = (input) => {
986
+ if (!input) return "Amount cannot be empty";
987
+ if (!/^\d*\.?\d+$/.test(input)) return "Must be a valid number";
988
+ return true;
989
+ };
990
+ const validateHexString = (input) => {
991
+ if (!input) return true;
992
+ if (!/^0x[a-fA-F0-9]+$/.test(input)) return "Must be a valid hex string starting with 0x";
993
+ return true;
994
+ };
995
+ const validateSlippage = (input) => {
996
+ const num = Number(input);
997
+ if (isNaN(num)) return "Must be a number";
998
+ if (num < 0 || num > 100) return "Slippage must be between 0 and 100";
999
+ return true;
1000
+ };
1001
+ const validateVaultPercentage = (input) => {
1002
+ const num = Number(input);
1003
+ if (isNaN(num)) return "Must be a number";
1004
+ if (num < 0 || num > 30) return "Vault percentage must be between 0 and 30%";
1005
+ return true;
1006
+ };
1007
+ const validateVaultDuration = (input) => {
1008
+ const num = Number(input);
1009
+ if (isNaN(num)) return "Must be a number";
1010
+ if (num < 30) return "Vault duration must be at least 30 days";
1011
+ return true;
1012
+ };
1013
+ const validateCreatorReward = (input) => {
1014
+ const num = Number(input);
1015
+ if (isNaN(num)) return "Must be a number";
1016
+ if (num < 0 || num > 80) return "Creator reward must be between 0 and 80%";
1017
+ return true;
1018
+ };
1019
+ const validateUrl = (input) => {
1020
+ if (!input) return true;
1021
+ try {
1022
+ new URL(input);
1023
+ return true;
1024
+ } catch (e) {
1025
+ return "Please enter a valid URL";
1026
+ }
1027
+ };
1028
+ async function promptUser() {
1029
+ const questions = [
1030
+ {
1031
+ type: "input",
1032
+ name: "name",
1033
+ message: "Token name:",
1034
+ validate: (input) => input.length > 0 || "Name cannot be empty"
1035
+ },
1036
+ {
1037
+ type: "input",
1038
+ name: "symbol",
1039
+ message: "Token symbol:",
1040
+ validate: validateSymbol
1041
+ },
1042
+ {
1043
+ type: "list",
1044
+ name: "pairedTokenChoice",
1045
+ message: "Select quote token:",
1046
+ choices: [
1047
+ { name: "WETH", value: "WETH" },
1048
+ { name: "USDC", value: "USDC" },
1049
+ { name: "Custom Address", value: "CUSTOM" }
1050
+ ],
1051
+ default: "WETH"
1052
+ },
1053
+ {
1054
+ type: "input",
1055
+ name: "customPairedToken",
1056
+ message: "Enter custom token address:",
1057
+ validate: validateAddress,
1058
+ when: (answers2) => answers2.pairedTokenChoice === "CUSTOM"
1059
+ },
1060
+ {
1061
+ type: "input",
1062
+ name: "initialMarketCapUsd",
1063
+ message: (answers2) => `Enter initial market cap in ${answers2.pairedTokenChoice === "CUSTOM" ? "quote token" : answers2.pairedTokenChoice}:`,
1064
+ validate: validateAmount,
1065
+ default: (answers2) => answers2.pairedTokenChoice === "WETH" ? "1" : answers2.pairedTokenChoice === "USDC" ? "1000" : "1"
1066
+ },
1067
+ {
1068
+ type: "input",
1069
+ name: "customMarketCap",
1070
+ message: "Enter custom market cap in quote token:",
1071
+ validate: validateAmount,
1072
+ when: (answers2) => answers2.initialMarketCapUsd === "CUSTOM"
1073
+ },
1074
+ {
1075
+ type: "input",
1076
+ name: "image",
1077
+ message: "Enter the IPFS URI for the token image:",
1078
+ validate: validateIpfsUri
1079
+ },
1080
+ {
1081
+ type: "list",
1082
+ name: "devBuy.ethAmount",
1083
+ message: "Creator buy amount (optional):",
1084
+ choices: [
1085
+ { name: "None", value: "0" },
1086
+ { name: "0.00005 ETH", value: "0.00005" },
1087
+ { name: "0.1 ETH", value: "0.1" },
1088
+ { name: "0.5 ETH", value: "0.5" },
1089
+ { name: "1.0 ETH", value: "1.0" },
1090
+ { name: "Custom", value: "CUSTOM" }
1091
+ ],
1092
+ default: "0"
1093
+ },
1094
+ {
1095
+ type: "input",
1096
+ name: "customDevBuy",
1097
+ message: "Enter custom dev buy amount in ETH:",
1098
+ validate: validateAmount,
1099
+ when: (answers2) => answers2.devBuy.ethAmount === "CUSTOM"
1100
+ },
1101
+ {
1102
+ type: "input",
1103
+ name: "devBuy.maxSlippage",
1104
+ message: "Maximum slippage percentage (0-100):",
1105
+ validate: validateSlippage,
1106
+ default: "5",
1107
+ when: (answers2) => answers2.devBuy.ethAmount !== "0"
1108
+ },
1109
+ {
1110
+ type: "list",
1111
+ name: "vaultConfig.vaultPercentage",
1112
+ message: "Vault percentage (optional):",
1113
+ choices: [
1114
+ { name: "None", value: "0" },
1115
+ { name: "5%", value: "5" },
1116
+ { name: "15%", value: "15" },
1117
+ { name: "30%", value: "30" },
1118
+ { name: "Custom", value: "CUSTOM" }
1119
+ ],
1120
+ default: "0"
1121
+ },
1122
+ {
1123
+ type: "input",
1124
+ name: "customVaultPercentage",
1125
+ message: "Enter custom vault percentage (0-30):",
1126
+ validate: validateVaultPercentage,
1127
+ when: (answers2) => answers2.vaultConfig.vaultPercentage === "CUSTOM"
1128
+ },
1129
+ {
1130
+ type: "list",
1131
+ name: "vaultConfig.durationInDays",
1132
+ message: "Vault duration:",
1133
+ choices: [
1134
+ { name: "31 days", value: "31" },
1135
+ { name: "90 days", value: "90" },
1136
+ { name: "180 days", value: "180" },
1137
+ { name: "Custom", value: "CUSTOM" }
1138
+ ],
1139
+ default: "31",
1140
+ when: (answers2) => answers2.vaultConfig.vaultPercentage !== "0"
1141
+ },
1142
+ {
1143
+ type: "input",
1144
+ name: "customVaultDuration",
1145
+ message: "Enter custom vault duration in days (minimum 30):",
1146
+ validate: validateVaultDuration,
1147
+ when: (answers2) => answers2.vaultConfig.durationInDays === "CUSTOM"
1148
+ },
1149
+ {
1150
+ type: "input",
1151
+ name: "metadata.description",
1152
+ message: "Token description:",
1153
+ default: (answers2) => `${answers2.name} token deployed via Clanker CLI`,
1154
+ validate: (input) => input.length > 0 || "Description cannot be empty"
1155
+ },
1156
+ {
1157
+ type: "input",
1158
+ name: "metadata.telegram",
1159
+ message: "Telegram URL (optional):",
1160
+ validate: validateUrl
1161
+ },
1162
+ {
1163
+ type: "input",
1164
+ name: "metadata.website",
1165
+ message: "Website URL (optional):",
1166
+ validate: validateUrl
1167
+ },
1168
+ {
1169
+ type: "input",
1170
+ name: "metadata.twitter",
1171
+ message: "X/Twitter URL (optional):",
1172
+ validate: validateUrl
1173
+ },
1174
+ {
1175
+ type: "input",
1176
+ name: "metadata.farcaster",
1177
+ message: "Farcaster URL (optional):",
1178
+ validate: validateUrl
1179
+ }
1180
+ ];
1181
+ const answers = await inquirer.prompt(questions);
1182
+ if (answers.initialMarketCapUsd === "CUSTOM") {
1183
+ answers.initialMarketCapUsd = answers.customMarketCap || "0";
1184
+ }
1185
+ if (answers.devBuy.ethAmount === "CUSTOM") {
1186
+ answers.devBuy.ethAmount = answers.customDevBuy || "0";
1187
+ }
1188
+ const vaultPercentage = answers.vaultConfig.vaultPercentage === "CUSTOM" ? parseInt(answers.customVaultPercentage || "0", 10) : parseInt(answers.vaultConfig.vaultPercentage, 10);
1189
+ const vaultDuration = answers.vaultConfig.durationInDays === "CUSTOM" ? parseInt(answers.customVaultDuration || "31", 10) : parseInt(answers.vaultConfig.durationInDays, 10);
1190
+ const socialMediaUrls = [];
1191
+ if (answers.metadata.telegram) socialMediaUrls.push(answers.metadata.telegram);
1192
+ if (answers.metadata.website) socialMediaUrls.push(answers.metadata.website);
1193
+ if (answers.metadata.twitter) socialMediaUrls.push(answers.metadata.twitter);
1194
+ if (answers.metadata.farcaster) socialMediaUrls.push(answers.metadata.farcaster);
1195
+ const metadata = {
1196
+ description: answers.metadata.description,
1197
+ socialMediaUrls,
1198
+ auditUrls: []
1199
+ };
1200
+ return {
1201
+ ...answers,
1202
+ metadata,
1203
+ vaultConfig: {
1204
+ vaultPercentage: vaultPercentage.toString(),
1205
+ durationInDays: vaultDuration.toString()
1206
+ }
1207
+ };
1208
+ }
1209
+ async function deployToken(answers) {
1210
+ if (!PRIVATE_KEY || !FACTORY_ADDRESS) {
1211
+ throw new Error("Missing required environment variables (PRIVATE_KEY, FACTORY_ADDRESS)");
1212
+ }
1213
+ const account = privateKeyToAccount(PRIVATE_KEY);
1214
+ const transport = RPC_URL ? http(RPC_URL) : http();
1215
+ const publicClient = createPublicClient({
1216
+ chain: base,
1217
+ transport
1218
+ });
1219
+ const walletClient = createWalletClient({
1220
+ account,
1221
+ chain: base,
1222
+ transport
1223
+ });
1224
+ const clanker = new Clanker({
1225
+ wallet: walletClient,
1226
+ publicClient,
1227
+ factoryAddress: FACTORY_ADDRESS
1228
+ });
1229
+ console.log("\n\u{1F504} Preparing deployment configuration...");
1230
+ let quoteToken;
1231
+ let decimals;
1232
+ switch (answers.pairedTokenChoice) {
1233
+ case "WETH":
1234
+ quoteToken = WETH_ADDRESS2;
1235
+ decimals = 18;
1236
+ break;
1237
+ case "USDC":
1238
+ quoteToken = USDC_ADDRESS;
1239
+ decimals = 6;
1240
+ break;
1241
+ case "CUSTOM":
1242
+ quoteToken = answers.customPairedToken;
1243
+ decimals = 18;
1244
+ break;
1245
+ default:
1246
+ quoteToken = WETH_ADDRESS2;
1247
+ decimals = 18;
1248
+ }
1249
+ const tokenAddress = await clanker.deployToken({
1250
+ name: answers.name,
1251
+ symbol: answers.symbol,
1252
+ salt: answers.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
1253
+ image: answers.image,
1254
+ metadata: {
1255
+ description: `${answers.name} token deployed via Clanker CLI`,
1256
+ socialMediaUrls: [],
1257
+ auditUrls: []
1258
+ },
1259
+ context: {
1260
+ interface: "Clanker CLI",
1261
+ platform: "Clanker",
1262
+ messageId: `CLI-${Date.now()}`,
1263
+ id: `${answers.symbol}-${Date.now()}`
1264
+ },
1265
+ vault: answers.vaultConfig.vaultPercentage !== "0" ? {
1266
+ percentage: parseInt(answers.vaultConfig.vaultPercentage, 10),
1267
+ durationInDays: parseInt(answers.vaultConfig.durationInDays, 10)
1268
+ } : void 0,
1269
+ pool: {
1270
+ quoteToken,
1271
+ initialMarketCap: answers.initialMarketCapUsd
1272
+ // Pass raw value, SDK will handle decimals
1273
+ },
1274
+ devBuy: answers.devBuy.ethAmount !== "0" ? {
1275
+ ethAmount: answers.devBuy.ethAmount,
1276
+ maxSlippage: answers.devBuy.maxSlippage
1277
+ } : void 0
1278
+ });
1279
+ return tokenAddress;
1280
+ }
1281
+ async function main2() {
1282
+ console.log("\n\u{1F680} Welcome to the Clanker Token Creator! \u{1F680}\n");
1283
+ if (!checkEnvironment()) {
1284
+ process.exit(1);
1285
+ }
1286
+ try {
1287
+ const answers = await promptUser();
1288
+ console.log("\n\u{1F4DD} Review your token configuration:\n");
1289
+ console.log(JSON.stringify(answers, null, 2));
1290
+ const { confirm } = await inquirer.prompt([
1291
+ {
1292
+ type: "confirm",
1293
+ name: "confirm",
1294
+ message: "Would you like to proceed with deployment?",
1295
+ default: false
1296
+ }
1297
+ ]);
1298
+ if (confirm) {
1299
+ console.log("\n\u{1F504} Deploying your token...");
1300
+ try {
1301
+ const tokenAddress = await deployToken(answers);
1302
+ console.log("\n\u2728 Token deployed successfully!");
1303
+ console.log("\u{1F4CD} Token address:", tokenAddress);
1304
+ console.log("\n\u{1F310} View on Basescan:");
1305
+ console.log(`https://basescan.org/token/${tokenAddress}`);
1306
+ } catch (error) {
1307
+ console.error("\n\u274C Deployment failed:", error instanceof Error ? error.message : "Unknown error");
1308
+ process.exit(1);
1309
+ }
1310
+ } else {
1311
+ console.log("\n\u274C Deployment cancelled");
1312
+ }
1313
+ } catch (error) {
1314
+ console.error("\n\u274C Error:", error);
1315
+ process.exit(1);
1316
+ }
1317
+ }
1318
+ await main2();
1319
+ }
1320
+ var init_create_clanker = __esm({
1321
+ "src/cli/create-clanker.ts"() {
1322
+ "use strict";
1323
+ init_esm_shims();
1324
+ init_index();
1325
+ dotenv.config();
1326
+ createClanker();
1327
+ }
1328
+ });
1329
+
1330
+ // src/cli/cli.ts
1331
+ init_esm_shims();
1332
+ import { fileURLToPath } from "url";
1333
+ import { dirname } from "path";
1334
+ var __filename2 = fileURLToPath(import.meta.url);
1335
+ var __dirname2 = dirname(__filename2);
1336
+ async function main() {
1337
+ const args = process.argv.slice(2);
1338
+ if (args.includes("--create")) {
1339
+ const createClanker2 = await Promise.resolve().then(() => (init_create_clanker(), create_clanker_exports));
1340
+ await createClanker2.default();
1341
+ } else {
1342
+ console.log("\n\u{1F680} Clanker SDK CLI\n");
1343
+ console.log("Available commands:");
1344
+ console.log(" --create Create a new token");
1345
+ console.log("\nExample:");
1346
+ console.log(" npx clanker-sdk --create\n");
1347
+ process.exit(0);
1348
+ }
1349
+ }
1350
+ main().catch((error) => {
1351
+ console.error("Error:", error);
1352
+ process.exit(1);
1353
+ });