clanker-sdk 3.9.0 → 3.9.2

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