clanker-sdk 3.9.8 → 3.9.9

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
@@ -146,7 +146,8 @@ async function prepareTokenDeployment() {
146
146
  ### Basic Token Configuration
147
147
  - `name`: Token name
148
148
  - `symbol`: Token symbol
149
- - `salt`: Randomly generated bytes32 value
149
+ - `salt`: Optional bytes32 value (must be "0x" + 64 hex characters), defaults to all zeros
150
+ - `creatorReward`: Optional percentage (0-80) controlling reward distribution between creator and interface, defaults to 80%
150
151
  - `image`: IPFS hash for token image
151
152
  - `metadata`: IPFS hash for token metadata
152
153
  - `context`: Deployment context string
@@ -162,6 +163,10 @@ const tokenAddress = await clanker.deployToken({
162
163
  name: "Test Token",
163
164
  symbol: "TEST",
164
165
 
166
+ // Optional configuration with validation
167
+ salt: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", // Must be 0x + 64 hex chars
168
+ creatorReward: 60, // Must be between 0-80, defaults to 80
169
+
165
170
  // Metadata configuration
166
171
  metadata: {
167
172
  description: "Test token deployment",
@@ -0,0 +1,20 @@
1
+ .--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--.
2
+ / .. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \
3
+ \ \/\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ \/ /
4
+ \/ /`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'\/ /
5
+ / /\ ```````````````````````````````````````````````````````````````````````````````````` / /\
6
+ / /\ \ ```````````````````````````````````````````````````````````````````````````````````` / /\ \
7
+ \ \/ / ```````::::::::``:::````````````:::`````::::````:::`:::````:::`::::::::::`:::::::::` \ \/ /
8
+ \/ / `````:+:````:+:`:+:``````````:+:`:+:```:+:+:```:+:`:+:```:+:``:+:````````:+:````:+:` \/ /
9
+ / /\ ````+:+````````+:+`````````+:+```+:+``:+:+:+``+:+`+:+``+:+```+:+````````+:+````+:+`` / /\
10
+ / /\ \ ```+#+````````+#+````````+#++:++#++:`+#+`+:+`+#+`+#++:++````+#++:++#```+#++:++#:```` / /\ \
11
+ \ \/ / ``+#+````````+#+````````+#+`````+#+`+#+``+#+#+#`+#+``+#+```+#+````````+#+````+#+```` \ \/ /
12
+ \/ / `#+#````#+#`#+#````````#+#`````#+#`#+#```#+#+#`#+#```#+#``#+#````````#+#````#+#````` \/ /
13
+ / /\ `########``##########`###`````###`###````####`###````###`##########`###````###`````` / /\
14
+ / /\ \ ```````````````````````````````````````````````````````````````````````````````````` / /\ \
15
+ \ \/ / ```````````````````````````````````````````````````````````````````````````````````` \ \/ /
16
+ \/ / ```````````````````````````````````````````````````````````````````````````````````` \/ /
17
+ / /\.--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--..--./ /\
18
+ / /\ \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \.. \/\ \
19
+ \ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `'\ `' /
20
+ `--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'`--'
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli/cli.js CHANGED
@@ -10,9 +10,15 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // node_modules/tsup/assets/esm_shims.js
13
+ import { fileURLToPath } from "url";
14
+ import path from "path";
15
+ var getFilename, getDirname, __dirname;
13
16
  var init_esm_shims = __esm({
14
17
  "node_modules/tsup/assets/esm_shims.js"() {
15
18
  "use strict";
19
+ getFilename = () => fileURLToPath(import.meta.url);
20
+ getDirname = () => path.dirname(getFilename());
21
+ __dirname = /* @__PURE__ */ getDirname();
16
22
  }
17
23
  });
18
24
 
@@ -820,7 +826,14 @@ var init_index = __esm({
820
826
  tokenConfig: {
821
827
  name: cfg.name,
822
828
  symbol: cfg.symbol,
823
- salt: cfg.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
829
+ salt: (() => {
830
+ const defaultSalt = "0x0000000000000000000000000000000000000000000000000000000000000000";
831
+ const salt = cfg.salt ?? defaultSalt;
832
+ if (!/^0x[a-fA-F0-9]{64}$/.test(salt)) {
833
+ throw new Error("Salt must be a valid bytes32 value (0x + 64 hex characters)");
834
+ }
835
+ return salt;
836
+ })(),
824
837
  image: cfg.image || "https://ipfs.io/ipfs/QmcjfTeK3tpK3MVCQuvEaXvSscrqbL3MwsEo8LdBTWabY4",
825
838
  metadata: JSON.stringify(cfg.metadata || {
826
839
  description: "Clanker Token",
@@ -849,12 +862,17 @@ var init_index = __esm({
849
862
  },
850
863
  initialBuyConfig,
851
864
  rewardsConfig: {
852
- creatorReward: BigInt(40),
853
- // Default to 40% creator reward
854
- creatorAdmin: deployerAddress,
855
- creatorRewardRecipient: deployerAddress,
856
- interfaceAdmin: deployerAddress,
857
- interfaceRewardRecipient: deployerAddress
865
+ creatorReward: (() => {
866
+ const reward = cfg.rewardsConfig?.creatorReward ?? 80;
867
+ if (reward < 0 || reward > 80) {
868
+ throw new Error("Creator reward must be between 0 and 80");
869
+ }
870
+ return BigInt(reward);
871
+ })(),
872
+ creatorAdmin: cfg.rewardsConfig?.creatorAdmin ?? deployerAddress,
873
+ creatorRewardRecipient: cfg.rewardsConfig?.creatorRewardRecipient ?? deployerAddress,
874
+ interfaceAdmin: cfg.rewardsConfig?.interfaceAdmin ?? deployerAddress,
875
+ interfaceRewardRecipient: cfg.rewardsConfig?.interfaceRewardRecipient ?? deployerAddress
858
876
  }
859
877
  };
860
878
  }
@@ -904,28 +922,25 @@ var init_index = __esm({
904
922
  // src/cli/create-clanker.ts
905
923
  var create_clanker_exports = {};
906
924
  __export(create_clanker_exports, {
907
- default: () => createClanker
925
+ default: () => create_clanker_default
908
926
  });
909
927
  import inquirer from "inquirer";
910
928
  import { createPublicClient, createWalletClient, http } from "viem";
911
929
  import { privateKeyToAccount } from "viem/accounts";
912
930
  import { base } from "viem/chains";
913
931
  import * as dotenv from "dotenv";
932
+ import * as fs from "fs";
933
+ import * as path2 from "path";
914
934
  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
935
  const PRIVATE_KEY = process.env.PRIVATE_KEY;
925
936
  const FACTORY_ADDRESS = process.env.FACTORY_ADDRESS;
926
937
  const RPC_URL = process.env.RPC_URL;
927
938
  const WETH_ADDRESS2 = "0x4200000000000000000000000000000000000006";
928
939
  const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
940
+ function toHexAddress(address) {
941
+ if (!address) return void 0;
942
+ return address.toLowerCase();
943
+ }
929
944
  function checkEnvironment() {
930
945
  const missingVars = [];
931
946
  if (!PRIVATE_KEY) missingVars.push("PRIVATE_KEY");
@@ -973,8 +988,8 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
973
988
  };
974
989
  const validateSymbol = (input) => {
975
990
  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";
991
+ if (!/^[a-zA-Z0-9]+$/.test(input)) return "Symbol must contain only letters and numbers";
992
+ if (input.length > 20) return "Symbol must be 20 characters or less";
978
993
  return true;
979
994
  };
980
995
  const validateIpfsUri = (input) => {
@@ -1031,18 +1046,21 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1031
1046
  type: "input",
1032
1047
  name: "name",
1033
1048
  message: "Token name:",
1049
+ prefix: "",
1034
1050
  validate: (input) => input.length > 0 || "Name cannot be empty"
1035
1051
  },
1036
1052
  {
1037
1053
  type: "input",
1038
1054
  name: "symbol",
1039
1055
  message: "Token symbol:",
1056
+ prefix: "",
1040
1057
  validate: validateSymbol
1041
1058
  },
1042
1059
  {
1043
1060
  type: "list",
1044
1061
  name: "pairedTokenChoice",
1045
1062
  message: "Select quote token:",
1063
+ prefix: "",
1046
1064
  choices: [
1047
1065
  { name: "WETH", value: "WETH" },
1048
1066
  { name: "USDC", value: "USDC" },
@@ -1054,6 +1072,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1054
1072
  type: "input",
1055
1073
  name: "customPairedToken",
1056
1074
  message: "Enter custom token address:",
1075
+ prefix: "",
1057
1076
  validate: validateAddress,
1058
1077
  when: (answers2) => answers2.pairedTokenChoice === "CUSTOM"
1059
1078
  },
@@ -1061,6 +1080,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1061
1080
  type: "input",
1062
1081
  name: "initialMarketCapUsd",
1063
1082
  message: (answers2) => `Enter initial market cap in ${answers2.pairedTokenChoice === "CUSTOM" ? "quote token" : answers2.pairedTokenChoice}:`,
1083
+ prefix: "",
1064
1084
  validate: validateAmount,
1065
1085
  default: (answers2) => answers2.pairedTokenChoice === "WETH" ? "1" : answers2.pairedTokenChoice === "USDC" ? "1000" : "1"
1066
1086
  },
@@ -1068,6 +1088,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1068
1088
  type: "input",
1069
1089
  name: "customMarketCap",
1070
1090
  message: "Enter custom market cap in quote token:",
1091
+ prefix: "",
1071
1092
  validate: validateAmount,
1072
1093
  when: (answers2) => answers2.initialMarketCapUsd === "CUSTOM"
1073
1094
  },
@@ -1075,12 +1096,14 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1075
1096
  type: "input",
1076
1097
  name: "image",
1077
1098
  message: "Enter the IPFS URI for the token image:",
1099
+ prefix: "",
1078
1100
  validate: validateIpfsUri
1079
1101
  },
1080
1102
  {
1081
1103
  type: "list",
1082
1104
  name: "devBuy.ethAmount",
1083
1105
  message: "Creator buy amount (optional):",
1106
+ prefix: "",
1084
1107
  choices: [
1085
1108
  { name: "None", value: "0" },
1086
1109
  { name: "0.00005 ETH", value: "0.00005" },
@@ -1095,6 +1118,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1095
1118
  type: "input",
1096
1119
  name: "customDevBuy",
1097
1120
  message: "Enter custom dev buy amount in ETH:",
1121
+ prefix: "",
1098
1122
  validate: validateAmount,
1099
1123
  when: (answers2) => answers2.devBuy.ethAmount === "CUSTOM"
1100
1124
  },
@@ -1102,6 +1126,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1102
1126
  type: "input",
1103
1127
  name: "devBuy.maxSlippage",
1104
1128
  message: "Maximum slippage percentage (0-100):",
1129
+ prefix: "",
1105
1130
  validate: validateSlippage,
1106
1131
  default: "5",
1107
1132
  when: (answers2) => answers2.devBuy.ethAmount !== "0"
@@ -1110,6 +1135,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1110
1135
  type: "list",
1111
1136
  name: "vaultConfig.vaultPercentage",
1112
1137
  message: "Vault percentage (optional):",
1138
+ prefix: "",
1113
1139
  choices: [
1114
1140
  { name: "None", value: "0" },
1115
1141
  { name: "5%", value: "5" },
@@ -1123,6 +1149,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1123
1149
  type: "input",
1124
1150
  name: "customVaultPercentage",
1125
1151
  message: "Enter custom vault percentage (0-30):",
1152
+ prefix: "",
1126
1153
  validate: validateVaultPercentage,
1127
1154
  when: (answers2) => answers2.vaultConfig.vaultPercentage === "CUSTOM"
1128
1155
  },
@@ -1130,6 +1157,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1130
1157
  type: "list",
1131
1158
  name: "vaultConfig.durationInDays",
1132
1159
  message: "Vault duration:",
1160
+ prefix: "",
1133
1161
  choices: [
1134
1162
  { name: "31 days", value: "31" },
1135
1163
  { name: "90 days", value: "90" },
@@ -1143,6 +1171,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1143
1171
  type: "input",
1144
1172
  name: "customVaultDuration",
1145
1173
  message: "Enter custom vault duration in days (minimum 30):",
1174
+ prefix: "",
1146
1175
  validate: validateVaultDuration,
1147
1176
  when: (answers2) => answers2.vaultConfig.durationInDays === "CUSTOM"
1148
1177
  },
@@ -1150,6 +1179,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1150
1179
  type: "input",
1151
1180
  name: "metadata.description",
1152
1181
  message: "Token description:",
1182
+ prefix: "",
1153
1183
  default: (answers2) => `${answers2.name} token deployed via Clanker CLI`,
1154
1184
  validate: (input) => input.length > 0 || "Description cannot be empty"
1155
1185
  },
@@ -1157,28 +1187,96 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1157
1187
  type: "input",
1158
1188
  name: "metadata.telegram",
1159
1189
  message: "Telegram URL (optional):",
1190
+ prefix: "",
1160
1191
  validate: validateUrl
1161
1192
  },
1162
1193
  {
1163
1194
  type: "input",
1164
1195
  name: "metadata.website",
1165
1196
  message: "Website URL (optional):",
1197
+ prefix: "",
1166
1198
  validate: validateUrl
1167
1199
  },
1168
1200
  {
1169
1201
  type: "input",
1170
1202
  name: "metadata.twitter",
1171
1203
  message: "X/Twitter URL (optional):",
1204
+ prefix: "",
1172
1205
  validate: validateUrl
1173
1206
  },
1174
1207
  {
1175
1208
  type: "input",
1176
1209
  name: "metadata.farcaster",
1177
1210
  message: "Farcaster URL (optional):",
1211
+ prefix: "",
1178
1212
  validate: validateUrl
1213
+ },
1214
+ {
1215
+ type: "input",
1216
+ name: "salt",
1217
+ message: "Enter custom salt (optional, press enter for default 0x0000...):",
1218
+ prefix: "",
1219
+ validate: (input) => {
1220
+ if (!input) return true;
1221
+ if (!/^0x[a-fA-F0-9]{64}$/.test(input)) {
1222
+ return "Salt must be a valid bytes32 value (0x + 64 hex characters)";
1223
+ }
1224
+ return true;
1225
+ }
1226
+ },
1227
+ {
1228
+ type: "list",
1229
+ name: "rewardsConfig.creatorReward",
1230
+ message: "Creator reward percentage, balance remaining goes to interface:",
1231
+ prefix: "",
1232
+ choices: [
1233
+ { name: "80% (maximum)", value: 80 },
1234
+ { name: "60%", value: 60 },
1235
+ { name: "40%", value: 40 },
1236
+ { name: "20%", value: 20 },
1237
+ { name: "0% (all to interface)", value: 0 },
1238
+ { name: "Custom", value: "CUSTOM" }
1239
+ ],
1240
+ default: 80
1241
+ },
1242
+ {
1243
+ type: "input",
1244
+ name: "rewardsConfig.customCreatorReward",
1245
+ message: "Enter custom creator reward percentage (0-80):",
1246
+ prefix: "",
1247
+ validate: validateCreatorReward,
1248
+ when: (answers2) => answers2.rewardsConfig.creatorReward === "CUSTOM"
1249
+ },
1250
+ {
1251
+ type: "input",
1252
+ name: "rewardsConfig.creatorAdmin",
1253
+ message: "Enter custom creator admin address (optional):",
1254
+ prefix: "",
1255
+ validate: validateAddress
1256
+ },
1257
+ {
1258
+ type: "input",
1259
+ name: "rewardsConfig.creatorRewardRecipient",
1260
+ message: "Enter custom creator reward recipient address (optional):",
1261
+ prefix: "",
1262
+ validate: validateAddress
1263
+ },
1264
+ {
1265
+ type: "input",
1266
+ name: "rewardsConfig.interfaceAdmin",
1267
+ message: "Enter custom interface admin address (optional):",
1268
+ prefix: "",
1269
+ validate: validateAddress
1270
+ },
1271
+ {
1272
+ type: "input",
1273
+ name: "rewardsConfig.interfaceRewardRecipient",
1274
+ message: "Enter custom interface reward recipient address (optional):",
1275
+ prefix: "",
1276
+ validate: validateAddress
1179
1277
  }
1180
1278
  ];
1181
- const answers = await inquirer.prompt(questions);
1279
+ const answers = await inquirer.prompt(questions, {});
1182
1280
  if (answers.initialMarketCapUsd === "CUSTOM") {
1183
1281
  answers.initialMarketCapUsd = answers.customMarketCap || "0";
1184
1282
  }
@@ -1203,6 +1301,21 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1203
1301
  vaultConfig: {
1204
1302
  vaultPercentage: vaultPercentage.toString(),
1205
1303
  durationInDays: vaultDuration.toString()
1304
+ },
1305
+ rewardsConfig: {
1306
+ creatorReward: answers.rewardsConfig.creatorReward === "CUSTOM" ? Number(answers.rewardsConfig.customCreatorReward) : Number(answers.rewardsConfig.creatorReward),
1307
+ ...answers.rewardsConfig.creatorAdmin ? {
1308
+ creatorAdmin: toHexAddress(answers.rewardsConfig.creatorAdmin)
1309
+ } : {},
1310
+ ...answers.rewardsConfig.creatorRewardRecipient ? {
1311
+ creatorRewardRecipient: toHexAddress(answers.rewardsConfig.creatorRewardRecipient)
1312
+ } : {},
1313
+ ...answers.rewardsConfig.interfaceAdmin ? {
1314
+ interfaceAdmin: toHexAddress(answers.rewardsConfig.interfaceAdmin)
1315
+ } : {},
1316
+ ...answers.rewardsConfig.interfaceRewardRecipient ? {
1317
+ interfaceRewardRecipient: toHexAddress(answers.rewardsConfig.interfaceRewardRecipient)
1318
+ } : {}
1206
1319
  }
1207
1320
  };
1208
1321
  }
@@ -1251,11 +1364,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1251
1364
  symbol: answers.symbol,
1252
1365
  salt: answers.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
1253
1366
  image: answers.image,
1254
- metadata: {
1255
- description: `${answers.name} token deployed via Clanker CLI`,
1256
- socialMediaUrls: [],
1257
- auditUrls: []
1258
- },
1367
+ metadata: answers.metadata,
1259
1368
  context: {
1260
1369
  interface: "Clanker CLI",
1261
1370
  platform: "Clanker",
@@ -1269,16 +1378,37 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1269
1378
  pool: {
1270
1379
  quoteToken,
1271
1380
  initialMarketCap: answers.initialMarketCapUsd
1272
- // Pass raw value, SDK will handle decimals
1273
1381
  },
1274
1382
  devBuy: answers.devBuy.ethAmount !== "0" ? {
1275
1383
  ethAmount: answers.devBuy.ethAmount,
1276
1384
  maxSlippage: answers.devBuy.maxSlippage
1277
- } : void 0
1385
+ } : void 0,
1386
+ rewardsConfig: {
1387
+ creatorReward: answers.rewardsConfig.creatorReward === "CUSTOM" ? Number(answers.rewardsConfig.customCreatorReward) : Number(answers.rewardsConfig.creatorReward),
1388
+ ...answers.rewardsConfig.creatorAdmin ? {
1389
+ creatorAdmin: toHexAddress(answers.rewardsConfig.creatorAdmin)
1390
+ } : {},
1391
+ ...answers.rewardsConfig.creatorRewardRecipient ? {
1392
+ creatorRewardRecipient: toHexAddress(answers.rewardsConfig.creatorRewardRecipient)
1393
+ } : {},
1394
+ ...answers.rewardsConfig.interfaceAdmin ? {
1395
+ interfaceAdmin: toHexAddress(answers.rewardsConfig.interfaceAdmin)
1396
+ } : {},
1397
+ ...answers.rewardsConfig.interfaceRewardRecipient ? {
1398
+ interfaceRewardRecipient: toHexAddress(answers.rewardsConfig.interfaceRewardRecipient)
1399
+ } : {}
1400
+ }
1278
1401
  });
1402
+ console.log("\n\u2728 Deployment successful!");
1403
+ console.log(`\u{1F4CD} Token address: ${tokenAddress}`);
1404
+ console.log("\n\u{1F310} View on:");
1405
+ console.log(`Basescan: https://basescan.org/token/${tokenAddress}`);
1406
+ console.log(`Clanker World: https://clanker.world/clanker/${tokenAddress}`);
1279
1407
  return tokenAddress;
1280
1408
  }
1281
1409
  async function main2() {
1410
+ console.clear();
1411
+ console.log(ASCII_ART);
1282
1412
  console.log("\n\u{1F680} Welcome to the Clanker Token Creator! \u{1F680}\n");
1283
1413
  if (!checkEnvironment()) {
1284
1414
  process.exit(1);
@@ -1292,23 +1422,22 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1292
1422
  type: "confirm",
1293
1423
  name: "confirm",
1294
1424
  message: "Would you like to proceed with deployment?",
1295
- default: false
1425
+ default: false,
1426
+ prefix: ""
1296
1427
  }
1297
1428
  ]);
1298
1429
  if (confirm) {
1299
1430
  console.log("\n\u{1F504} Deploying your token...");
1300
1431
  try {
1301
1432
  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}`);
1433
+ process.exit(0);
1306
1434
  } catch (error) {
1307
1435
  console.error("\n\u274C Deployment failed:", error instanceof Error ? error.message : "Unknown error");
1308
1436
  process.exit(1);
1309
1437
  }
1310
1438
  } else {
1311
1439
  console.log("\n\u274C Deployment cancelled");
1440
+ process.exit(0);
1312
1441
  }
1313
1442
  } catch (error) {
1314
1443
  console.error("\n\u274C Error:", error);
@@ -1317,21 +1446,23 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1317
1446
  }
1318
1447
  await main2();
1319
1448
  }
1449
+ var ASCII_ART, create_clanker_default;
1320
1450
  var init_create_clanker = __esm({
1321
1451
  "src/cli/create-clanker.ts"() {
1322
1452
  "use strict";
1323
1453
  init_esm_shims();
1324
1454
  init_index();
1325
1455
  dotenv.config();
1326
- createClanker();
1456
+ ASCII_ART = fs.readFileSync(path2.join(__dirname, "ascii.txt"), "utf8");
1457
+ create_clanker_default = createClanker;
1327
1458
  }
1328
1459
  });
1329
1460
 
1330
1461
  // src/cli/cli.ts
1331
1462
  init_esm_shims();
1332
- import { fileURLToPath } from "url";
1463
+ import { fileURLToPath as fileURLToPath2 } from "url";
1333
1464
  import { dirname } from "path";
1334
- var __filename2 = fileURLToPath(import.meta.url);
1465
+ var __filename2 = fileURLToPath2(import.meta.url);
1335
1466
  var __dirname2 = dirname(__filename2);
1336
1467
  async function main() {
1337
1468
  const args = process.argv.slice(2);
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ declare function createClanker(): Promise<void>;
3
+
4
+ export { createClanker as default };
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // node_modules/tsup/assets/esm_shims.js
4
+ import { fileURLToPath } from "url";
5
+ import path from "path";
6
+ var getFilename = () => fileURLToPath(import.meta.url);
7
+ var getDirname = () => path.dirname(getFilename());
8
+ var __dirname = /* @__PURE__ */ getDirname();
9
+
3
10
  // src/cli/create-clanker.ts
4
11
  import inquirer from "inquirer";
5
12
 
@@ -779,7 +786,14 @@ var Clanker = class {
779
786
  tokenConfig: {
780
787
  name: cfg.name,
781
788
  symbol: cfg.symbol,
782
- salt: cfg.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
789
+ salt: (() => {
790
+ const defaultSalt = "0x0000000000000000000000000000000000000000000000000000000000000000";
791
+ const salt = cfg.salt ?? defaultSalt;
792
+ if (!/^0x[a-fA-F0-9]{64}$/.test(salt)) {
793
+ throw new Error("Salt must be a valid bytes32 value (0x + 64 hex characters)");
794
+ }
795
+ return salt;
796
+ })(),
783
797
  image: cfg.image || "https://ipfs.io/ipfs/QmcjfTeK3tpK3MVCQuvEaXvSscrqbL3MwsEo8LdBTWabY4",
784
798
  metadata: JSON.stringify(cfg.metadata || {
785
799
  description: "Clanker Token",
@@ -808,12 +822,17 @@ var Clanker = class {
808
822
  },
809
823
  initialBuyConfig,
810
824
  rewardsConfig: {
811
- creatorReward: BigInt(40),
812
- // Default to 40% creator reward
813
- creatorAdmin: deployerAddress,
814
- creatorRewardRecipient: deployerAddress,
815
- interfaceAdmin: deployerAddress,
816
- interfaceRewardRecipient: deployerAddress
825
+ creatorReward: (() => {
826
+ const reward = cfg.rewardsConfig?.creatorReward ?? 80;
827
+ if (reward < 0 || reward > 80) {
828
+ throw new Error("Creator reward must be between 0 and 80");
829
+ }
830
+ return BigInt(reward);
831
+ })(),
832
+ creatorAdmin: cfg.rewardsConfig?.creatorAdmin ?? deployerAddress,
833
+ creatorRewardRecipient: cfg.rewardsConfig?.creatorRewardRecipient ?? deployerAddress,
834
+ interfaceAdmin: cfg.rewardsConfig?.interfaceAdmin ?? deployerAddress,
835
+ interfaceRewardRecipient: cfg.rewardsConfig?.interfaceRewardRecipient ?? deployerAddress
817
836
  }
818
837
  };
819
838
  }
@@ -863,22 +882,20 @@ import { createPublicClient, createWalletClient, http } from "viem";
863
882
  import { privateKeyToAccount } from "viem/accounts";
864
883
  import { base } from "viem/chains";
865
884
  import * as dotenv from "dotenv";
885
+ import * as fs from "fs";
886
+ import * as path2 from "path";
866
887
  dotenv.config();
888
+ var ASCII_ART = fs.readFileSync(path2.join(__dirname, "ascii.txt"), "utf8");
867
889
  async function createClanker() {
868
- const args = process.argv.slice(2);
869
- if (args.length === 0 || args[0] !== "--create" && args[0] !== "create") {
870
- console.log("\n\u{1F680} Clanker SDK CLI\n");
871
- console.log("Available commands:");
872
- console.log(" --create Create a new token");
873
- console.log("\nExample:");
874
- console.log(" npx clanker-sdk --create\n");
875
- process.exit(0);
876
- }
877
890
  const PRIVATE_KEY = process.env.PRIVATE_KEY;
878
891
  const FACTORY_ADDRESS = process.env.FACTORY_ADDRESS;
879
892
  const RPC_URL = process.env.RPC_URL;
880
893
  const WETH_ADDRESS2 = "0x4200000000000000000000000000000000000006";
881
894
  const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
895
+ function toHexAddress(address) {
896
+ if (!address) return void 0;
897
+ return address.toLowerCase();
898
+ }
882
899
  function checkEnvironment() {
883
900
  const missingVars = [];
884
901
  if (!PRIVATE_KEY) missingVars.push("PRIVATE_KEY");
@@ -926,8 +943,8 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
926
943
  };
927
944
  const validateSymbol = (input) => {
928
945
  if (!input) return "Symbol cannot be empty";
929
- if (!/^[A-Z0-9]+$/.test(input)) return "Symbol must contain only uppercase letters and numbers";
930
- if (input.length > 10) return "Symbol must be 10 characters or less";
946
+ if (!/^[a-zA-Z0-9]+$/.test(input)) return "Symbol must contain only letters and numbers";
947
+ if (input.length > 20) return "Symbol must be 20 characters or less";
931
948
  return true;
932
949
  };
933
950
  const validateIpfsUri = (input) => {
@@ -984,18 +1001,21 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
984
1001
  type: "input",
985
1002
  name: "name",
986
1003
  message: "Token name:",
1004
+ prefix: "",
987
1005
  validate: (input) => input.length > 0 || "Name cannot be empty"
988
1006
  },
989
1007
  {
990
1008
  type: "input",
991
1009
  name: "symbol",
992
1010
  message: "Token symbol:",
1011
+ prefix: "",
993
1012
  validate: validateSymbol
994
1013
  },
995
1014
  {
996
1015
  type: "list",
997
1016
  name: "pairedTokenChoice",
998
1017
  message: "Select quote token:",
1018
+ prefix: "",
999
1019
  choices: [
1000
1020
  { name: "WETH", value: "WETH" },
1001
1021
  { name: "USDC", value: "USDC" },
@@ -1007,6 +1027,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1007
1027
  type: "input",
1008
1028
  name: "customPairedToken",
1009
1029
  message: "Enter custom token address:",
1030
+ prefix: "",
1010
1031
  validate: validateAddress,
1011
1032
  when: (answers2) => answers2.pairedTokenChoice === "CUSTOM"
1012
1033
  },
@@ -1014,6 +1035,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1014
1035
  type: "input",
1015
1036
  name: "initialMarketCapUsd",
1016
1037
  message: (answers2) => `Enter initial market cap in ${answers2.pairedTokenChoice === "CUSTOM" ? "quote token" : answers2.pairedTokenChoice}:`,
1038
+ prefix: "",
1017
1039
  validate: validateAmount,
1018
1040
  default: (answers2) => answers2.pairedTokenChoice === "WETH" ? "1" : answers2.pairedTokenChoice === "USDC" ? "1000" : "1"
1019
1041
  },
@@ -1021,6 +1043,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1021
1043
  type: "input",
1022
1044
  name: "customMarketCap",
1023
1045
  message: "Enter custom market cap in quote token:",
1046
+ prefix: "",
1024
1047
  validate: validateAmount,
1025
1048
  when: (answers2) => answers2.initialMarketCapUsd === "CUSTOM"
1026
1049
  },
@@ -1028,12 +1051,14 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1028
1051
  type: "input",
1029
1052
  name: "image",
1030
1053
  message: "Enter the IPFS URI for the token image:",
1054
+ prefix: "",
1031
1055
  validate: validateIpfsUri
1032
1056
  },
1033
1057
  {
1034
1058
  type: "list",
1035
1059
  name: "devBuy.ethAmount",
1036
1060
  message: "Creator buy amount (optional):",
1061
+ prefix: "",
1037
1062
  choices: [
1038
1063
  { name: "None", value: "0" },
1039
1064
  { name: "0.00005 ETH", value: "0.00005" },
@@ -1048,6 +1073,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1048
1073
  type: "input",
1049
1074
  name: "customDevBuy",
1050
1075
  message: "Enter custom dev buy amount in ETH:",
1076
+ prefix: "",
1051
1077
  validate: validateAmount,
1052
1078
  when: (answers2) => answers2.devBuy.ethAmount === "CUSTOM"
1053
1079
  },
@@ -1055,6 +1081,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1055
1081
  type: "input",
1056
1082
  name: "devBuy.maxSlippage",
1057
1083
  message: "Maximum slippage percentage (0-100):",
1084
+ prefix: "",
1058
1085
  validate: validateSlippage,
1059
1086
  default: "5",
1060
1087
  when: (answers2) => answers2.devBuy.ethAmount !== "0"
@@ -1063,6 +1090,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1063
1090
  type: "list",
1064
1091
  name: "vaultConfig.vaultPercentage",
1065
1092
  message: "Vault percentage (optional):",
1093
+ prefix: "",
1066
1094
  choices: [
1067
1095
  { name: "None", value: "0" },
1068
1096
  { name: "5%", value: "5" },
@@ -1076,6 +1104,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1076
1104
  type: "input",
1077
1105
  name: "customVaultPercentage",
1078
1106
  message: "Enter custom vault percentage (0-30):",
1107
+ prefix: "",
1079
1108
  validate: validateVaultPercentage,
1080
1109
  when: (answers2) => answers2.vaultConfig.vaultPercentage === "CUSTOM"
1081
1110
  },
@@ -1083,6 +1112,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1083
1112
  type: "list",
1084
1113
  name: "vaultConfig.durationInDays",
1085
1114
  message: "Vault duration:",
1115
+ prefix: "",
1086
1116
  choices: [
1087
1117
  { name: "31 days", value: "31" },
1088
1118
  { name: "90 days", value: "90" },
@@ -1096,6 +1126,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1096
1126
  type: "input",
1097
1127
  name: "customVaultDuration",
1098
1128
  message: "Enter custom vault duration in days (minimum 30):",
1129
+ prefix: "",
1099
1130
  validate: validateVaultDuration,
1100
1131
  when: (answers2) => answers2.vaultConfig.durationInDays === "CUSTOM"
1101
1132
  },
@@ -1103,6 +1134,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1103
1134
  type: "input",
1104
1135
  name: "metadata.description",
1105
1136
  message: "Token description:",
1137
+ prefix: "",
1106
1138
  default: (answers2) => `${answers2.name} token deployed via Clanker CLI`,
1107
1139
  validate: (input) => input.length > 0 || "Description cannot be empty"
1108
1140
  },
@@ -1110,28 +1142,96 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1110
1142
  type: "input",
1111
1143
  name: "metadata.telegram",
1112
1144
  message: "Telegram URL (optional):",
1145
+ prefix: "",
1113
1146
  validate: validateUrl
1114
1147
  },
1115
1148
  {
1116
1149
  type: "input",
1117
1150
  name: "metadata.website",
1118
1151
  message: "Website URL (optional):",
1152
+ prefix: "",
1119
1153
  validate: validateUrl
1120
1154
  },
1121
1155
  {
1122
1156
  type: "input",
1123
1157
  name: "metadata.twitter",
1124
1158
  message: "X/Twitter URL (optional):",
1159
+ prefix: "",
1125
1160
  validate: validateUrl
1126
1161
  },
1127
1162
  {
1128
1163
  type: "input",
1129
1164
  name: "metadata.farcaster",
1130
1165
  message: "Farcaster URL (optional):",
1166
+ prefix: "",
1131
1167
  validate: validateUrl
1168
+ },
1169
+ {
1170
+ type: "input",
1171
+ name: "salt",
1172
+ message: "Enter custom salt (optional, press enter for default 0x0000...):",
1173
+ prefix: "",
1174
+ validate: (input) => {
1175
+ if (!input) return true;
1176
+ if (!/^0x[a-fA-F0-9]{64}$/.test(input)) {
1177
+ return "Salt must be a valid bytes32 value (0x + 64 hex characters)";
1178
+ }
1179
+ return true;
1180
+ }
1181
+ },
1182
+ {
1183
+ type: "list",
1184
+ name: "rewardsConfig.creatorReward",
1185
+ message: "Creator reward percentage, balance remaining goes to interface:",
1186
+ prefix: "",
1187
+ choices: [
1188
+ { name: "80% (maximum)", value: 80 },
1189
+ { name: "60%", value: 60 },
1190
+ { name: "40%", value: 40 },
1191
+ { name: "20%", value: 20 },
1192
+ { name: "0% (all to interface)", value: 0 },
1193
+ { name: "Custom", value: "CUSTOM" }
1194
+ ],
1195
+ default: 80
1196
+ },
1197
+ {
1198
+ type: "input",
1199
+ name: "rewardsConfig.customCreatorReward",
1200
+ message: "Enter custom creator reward percentage (0-80):",
1201
+ prefix: "",
1202
+ validate: validateCreatorReward,
1203
+ when: (answers2) => answers2.rewardsConfig.creatorReward === "CUSTOM"
1204
+ },
1205
+ {
1206
+ type: "input",
1207
+ name: "rewardsConfig.creatorAdmin",
1208
+ message: "Enter custom creator admin address (optional):",
1209
+ prefix: "",
1210
+ validate: validateAddress
1211
+ },
1212
+ {
1213
+ type: "input",
1214
+ name: "rewardsConfig.creatorRewardRecipient",
1215
+ message: "Enter custom creator reward recipient address (optional):",
1216
+ prefix: "",
1217
+ validate: validateAddress
1218
+ },
1219
+ {
1220
+ type: "input",
1221
+ name: "rewardsConfig.interfaceAdmin",
1222
+ message: "Enter custom interface admin address (optional):",
1223
+ prefix: "",
1224
+ validate: validateAddress
1225
+ },
1226
+ {
1227
+ type: "input",
1228
+ name: "rewardsConfig.interfaceRewardRecipient",
1229
+ message: "Enter custom interface reward recipient address (optional):",
1230
+ prefix: "",
1231
+ validate: validateAddress
1132
1232
  }
1133
1233
  ];
1134
- const answers = await inquirer.prompt(questions);
1234
+ const answers = await inquirer.prompt(questions, {});
1135
1235
  if (answers.initialMarketCapUsd === "CUSTOM") {
1136
1236
  answers.initialMarketCapUsd = answers.customMarketCap || "0";
1137
1237
  }
@@ -1156,6 +1256,21 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1156
1256
  vaultConfig: {
1157
1257
  vaultPercentage: vaultPercentage.toString(),
1158
1258
  durationInDays: vaultDuration.toString()
1259
+ },
1260
+ rewardsConfig: {
1261
+ creatorReward: answers.rewardsConfig.creatorReward === "CUSTOM" ? Number(answers.rewardsConfig.customCreatorReward) : Number(answers.rewardsConfig.creatorReward),
1262
+ ...answers.rewardsConfig.creatorAdmin ? {
1263
+ creatorAdmin: toHexAddress(answers.rewardsConfig.creatorAdmin)
1264
+ } : {},
1265
+ ...answers.rewardsConfig.creatorRewardRecipient ? {
1266
+ creatorRewardRecipient: toHexAddress(answers.rewardsConfig.creatorRewardRecipient)
1267
+ } : {},
1268
+ ...answers.rewardsConfig.interfaceAdmin ? {
1269
+ interfaceAdmin: toHexAddress(answers.rewardsConfig.interfaceAdmin)
1270
+ } : {},
1271
+ ...answers.rewardsConfig.interfaceRewardRecipient ? {
1272
+ interfaceRewardRecipient: toHexAddress(answers.rewardsConfig.interfaceRewardRecipient)
1273
+ } : {}
1159
1274
  }
1160
1275
  };
1161
1276
  }
@@ -1204,11 +1319,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1204
1319
  symbol: answers.symbol,
1205
1320
  salt: answers.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
1206
1321
  image: answers.image,
1207
- metadata: {
1208
- description: `${answers.name} token deployed via Clanker CLI`,
1209
- socialMediaUrls: [],
1210
- auditUrls: []
1211
- },
1322
+ metadata: answers.metadata,
1212
1323
  context: {
1213
1324
  interface: "Clanker CLI",
1214
1325
  platform: "Clanker",
@@ -1222,16 +1333,37 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1222
1333
  pool: {
1223
1334
  quoteToken,
1224
1335
  initialMarketCap: answers.initialMarketCapUsd
1225
- // Pass raw value, SDK will handle decimals
1226
1336
  },
1227
1337
  devBuy: answers.devBuy.ethAmount !== "0" ? {
1228
1338
  ethAmount: answers.devBuy.ethAmount,
1229
1339
  maxSlippage: answers.devBuy.maxSlippage
1230
- } : void 0
1340
+ } : void 0,
1341
+ rewardsConfig: {
1342
+ creatorReward: answers.rewardsConfig.creatorReward === "CUSTOM" ? Number(answers.rewardsConfig.customCreatorReward) : Number(answers.rewardsConfig.creatorReward),
1343
+ ...answers.rewardsConfig.creatorAdmin ? {
1344
+ creatorAdmin: toHexAddress(answers.rewardsConfig.creatorAdmin)
1345
+ } : {},
1346
+ ...answers.rewardsConfig.creatorRewardRecipient ? {
1347
+ creatorRewardRecipient: toHexAddress(answers.rewardsConfig.creatorRewardRecipient)
1348
+ } : {},
1349
+ ...answers.rewardsConfig.interfaceAdmin ? {
1350
+ interfaceAdmin: toHexAddress(answers.rewardsConfig.interfaceAdmin)
1351
+ } : {},
1352
+ ...answers.rewardsConfig.interfaceRewardRecipient ? {
1353
+ interfaceRewardRecipient: toHexAddress(answers.rewardsConfig.interfaceRewardRecipient)
1354
+ } : {}
1355
+ }
1231
1356
  });
1357
+ console.log("\n\u2728 Deployment successful!");
1358
+ console.log(`\u{1F4CD} Token address: ${tokenAddress}`);
1359
+ console.log("\n\u{1F310} View on:");
1360
+ console.log(`Basescan: https://basescan.org/token/${tokenAddress}`);
1361
+ console.log(`Clanker World: https://clanker.world/clanker/${tokenAddress}`);
1232
1362
  return tokenAddress;
1233
1363
  }
1234
1364
  async function main() {
1365
+ console.clear();
1366
+ console.log(ASCII_ART);
1235
1367
  console.log("\n\u{1F680} Welcome to the Clanker Token Creator! \u{1F680}\n");
1236
1368
  if (!checkEnvironment()) {
1237
1369
  process.exit(1);
@@ -1245,23 +1377,22 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1245
1377
  type: "confirm",
1246
1378
  name: "confirm",
1247
1379
  message: "Would you like to proceed with deployment?",
1248
- default: false
1380
+ default: false,
1381
+ prefix: ""
1249
1382
  }
1250
1383
  ]);
1251
1384
  if (confirm) {
1252
1385
  console.log("\n\u{1F504} Deploying your token...");
1253
1386
  try {
1254
1387
  const tokenAddress = await deployToken(answers);
1255
- console.log("\n\u2728 Token deployed successfully!");
1256
- console.log("\u{1F4CD} Token address:", tokenAddress);
1257
- console.log("\n\u{1F310} View on Basescan:");
1258
- console.log(`https://basescan.org/token/${tokenAddress}`);
1388
+ process.exit(0);
1259
1389
  } catch (error) {
1260
1390
  console.error("\n\u274C Deployment failed:", error instanceof Error ? error.message : "Unknown error");
1261
1391
  process.exit(1);
1262
1392
  }
1263
1393
  } else {
1264
1394
  console.log("\n\u274C Deployment cancelled");
1395
+ process.exit(0);
1265
1396
  }
1266
1397
  } catch (error) {
1267
1398
  console.error("\n\u274C Error:", error);
@@ -1270,7 +1401,7 @@ RPC_URL=your_custom_rpc_url (if not provided, will use default Base RPC)
1270
1401
  }
1271
1402
  await main();
1272
1403
  }
1273
- createClanker();
1404
+ var create_clanker_default = createClanker;
1274
1405
  export {
1275
- createClanker as default
1406
+ create_clanker_default as default
1276
1407
  };
@@ -0,0 +1,125 @@
1
+ import { PublicClient, WalletClient, Address } from 'viem';
2
+
3
+ interface TokenConfig {
4
+ name: string;
5
+ symbol: string;
6
+ salt: `0x${string}`;
7
+ image: string;
8
+ metadata: IClankerMetadata;
9
+ context: IClankerSocialContext;
10
+ originatingChainId: bigint;
11
+ }
12
+ interface VaultConfig {
13
+ vaultPercentage: number;
14
+ vaultDuration: bigint;
15
+ }
16
+ interface PoolConfig {
17
+ pairedToken: Address;
18
+ initialMarketCapInPairedToken: bigint;
19
+ initialMarketCap?: string;
20
+ tickIfToken0IsNewToken?: number;
21
+ }
22
+ interface InitialBuyConfig {
23
+ pairedTokenPoolFee: number;
24
+ pairedTokenSwapAmountOutMinimum: bigint;
25
+ ethAmount?: bigint;
26
+ }
27
+ interface RewardsConfig {
28
+ creatorReward: bigint;
29
+ creatorAdmin: Address;
30
+ creatorRewardRecipient: Address;
31
+ interfaceAdmin: Address;
32
+ interfaceRewardRecipient: Address;
33
+ }
34
+ interface DeploymentConfig {
35
+ tokenConfig: TokenConfig;
36
+ vaultConfig?: VaultConfig;
37
+ poolConfig: PoolConfig;
38
+ initialBuyConfig?: InitialBuyConfig;
39
+ rewardsConfig: RewardsConfig;
40
+ }
41
+ type ClankerConfig = {
42
+ publicClient: PublicClient;
43
+ wallet?: WalletClient;
44
+ factoryAddress?: Address;
45
+ };
46
+ interface SimpleTokenConfig {
47
+ name: string;
48
+ symbol: string;
49
+ salt?: `0x${string}`;
50
+ image?: string;
51
+ metadata?: {
52
+ description: string;
53
+ socialMediaUrls: string[];
54
+ auditUrls: string[];
55
+ };
56
+ context?: {
57
+ interface: string;
58
+ platform: string;
59
+ messageId: string;
60
+ id: string;
61
+ };
62
+ pool?: {
63
+ quoteToken?: `0x${string}`;
64
+ initialMarketCap?: string;
65
+ };
66
+ vault?: {
67
+ percentage: number;
68
+ durationInDays: number;
69
+ };
70
+ devBuy?: {
71
+ ethAmount: string;
72
+ maxSlippage?: number;
73
+ };
74
+ rewardsConfig?: {
75
+ creatorReward?: number;
76
+ creatorAdmin?: `0x${string}`;
77
+ creatorRewardRecipient?: `0x${string}`;
78
+ interfaceAdmin?: `0x${string}`;
79
+ interfaceRewardRecipient?: `0x${string}`;
80
+ };
81
+ }
82
+ interface IClankerMetadata {
83
+ description?: string;
84
+ socialMediaUrls?: {
85
+ platform: string;
86
+ url: string;
87
+ }[];
88
+ auditUrls?: string[];
89
+ }
90
+ interface IClankerSocialContext {
91
+ interface: string;
92
+ platform?: string;
93
+ messageId?: string;
94
+ id?: string;
95
+ }
96
+
97
+ /** Lightweight container for a pre-built deploy transaction */
98
+ type PreparedDeployTx = {
99
+ to: Address;
100
+ data: `0x${string}`;
101
+ value: bigint;
102
+ };
103
+ declare class Clanker {
104
+ private readonly wallet?;
105
+ private readonly factoryAddress;
106
+ private readonly publicClient;
107
+ constructor(config: ClankerConfig);
108
+ private getQuoteTokenDecimals;
109
+ private findMostLiquidPool;
110
+ private calculateMinimumOutput;
111
+ private calculateTickForQuoteToken;
112
+ private handleError;
113
+ deploy(config: DeploymentConfig): Promise<Address>;
114
+ private buildDeploymentConfig;
115
+ /**
116
+ * Creates calldata (+ msg.value) **without** sending a transaction.
117
+ * This version no longer relies on viem's `simulateContract`, which
118
+ * was returning an object without `.data`. We now ABI-encode the
119
+ * call manually so `data` is always defined.
120
+ */
121
+ prepareDeployToken(cfg: SimpleTokenConfig): Promise<PreparedDeployTx>;
122
+ deployToken(cfg: SimpleTokenConfig): Promise<Address>;
123
+ }
124
+
125
+ export { Clanker, type ClankerConfig, type DeploymentConfig, type IClankerMetadata, type IClankerSocialContext, type InitialBuyConfig, type PoolConfig, type PreparedDeployTx, type RewardsConfig, type SimpleTokenConfig, type TokenConfig, type VaultConfig };
package/dist/index.js CHANGED
@@ -774,7 +774,14 @@ var Clanker = class {
774
774
  tokenConfig: {
775
775
  name: cfg.name,
776
776
  symbol: cfg.symbol,
777
- salt: cfg.salt || "0x0000000000000000000000000000000000000000000000000000000000000000",
777
+ salt: (() => {
778
+ const defaultSalt = "0x0000000000000000000000000000000000000000000000000000000000000000";
779
+ const salt = cfg.salt ?? defaultSalt;
780
+ if (!/^0x[a-fA-F0-9]{64}$/.test(salt)) {
781
+ throw new Error("Salt must be a valid bytes32 value (0x + 64 hex characters)");
782
+ }
783
+ return salt;
784
+ })(),
778
785
  image: cfg.image || "https://ipfs.io/ipfs/QmcjfTeK3tpK3MVCQuvEaXvSscrqbL3MwsEo8LdBTWabY4",
779
786
  metadata: JSON.stringify(cfg.metadata || {
780
787
  description: "Clanker Token",
@@ -803,12 +810,17 @@ var Clanker = class {
803
810
  },
804
811
  initialBuyConfig,
805
812
  rewardsConfig: {
806
- creatorReward: BigInt(40),
807
- // Default to 40% creator reward
808
- creatorAdmin: deployerAddress,
809
- creatorRewardRecipient: deployerAddress,
810
- interfaceAdmin: deployerAddress,
811
- interfaceRewardRecipient: deployerAddress
813
+ creatorReward: (() => {
814
+ const reward = cfg.rewardsConfig?.creatorReward ?? 80;
815
+ if (reward < 0 || reward > 80) {
816
+ throw new Error("Creator reward must be between 0 and 80");
817
+ }
818
+ return BigInt(reward);
819
+ })(),
820
+ creatorAdmin: cfg.rewardsConfig?.creatorAdmin ?? deployerAddress,
821
+ creatorRewardRecipient: cfg.rewardsConfig?.creatorRewardRecipient ?? deployerAddress,
822
+ interfaceAdmin: cfg.rewardsConfig?.interfaceAdmin ?? deployerAddress,
823
+ interfaceRewardRecipient: cfg.rewardsConfig?.interfaceRewardRecipient ?? deployerAddress
812
824
  }
813
825
  };
814
826
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clanker-sdk",
3
- "version": "3.9.8",
3
+ "version": "3.9.9",
4
4
  "description": "SDK for deploying tokens using Clanker",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",