@otonix/cli 2.1.8 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import { header, row, success, failure, info, br, warn, mono } from "../lib/disp
7
7
  export function agentCommand(program) {
8
8
  program
9
9
  .command("agent:create")
10
- .description("Create a new autonomous agent with an isolated Base wallet")
10
+ .description("Create a new autonomous agent one wallet for everything")
11
11
  .requiredOption("--name <name>", "Agent name (alphanumeric, no spaces)")
12
12
  .action(async (opts) => {
13
13
  header("Create Agent");
@@ -17,19 +17,6 @@ export function agentCommand(program) {
17
17
  process.exit(1);
18
18
  }
19
19
  const cfg = loadConfig();
20
- if (!cfg.wallet) {
21
- const autoSpinner = ora("No creator wallet found — generating one automatically...").start();
22
- await new Promise(r => setTimeout(r, 400));
23
- const creator = generateWallet();
24
- autoSpinner.stop();
25
- cfg.wallet = { address: creator.address, privateKey: creator.privateKey };
26
- saveConfig(cfg);
27
- success("Creator wallet generated!");
28
- br();
29
- console.log(chalk.dim(" Creator wallet address: ") + chalk.bold.white(creator.address));
30
- console.log(chalk.dim(" Fund this address with ≥ 200 $OTX + ≥ 0.005 ETH (Base)"));
31
- br();
32
- }
33
20
  if (cfg.agents[name]) {
34
21
  const overwrite = await confirm({
35
22
  message: `Agent "${name}" already exists. Replace it?`,
@@ -40,7 +27,7 @@ export function agentCommand(program) {
40
27
  return;
41
28
  }
42
29
  }
43
- const spinner = ora("Generating isolated agent wallet on Base...").start();
30
+ const spinner = ora("Generating agent wallet on Base...").start();
44
31
  await new Promise(r => setTimeout(r, 600));
45
32
  const agent = generateWallet();
46
33
  spinner.stop();
@@ -54,28 +41,25 @@ export function agentCommand(program) {
54
41
  success(`Agent "${name}" created!`);
55
42
  br();
56
43
  row("Agent name", name);
57
- row("Agent address", agent.address);
44
+ row("Wallet address", agent.address);
58
45
  row("Created at", new Date().toLocaleString());
59
46
  row("Status", chalk.yellow("⊘ Not registered"));
60
47
  br();
61
48
  console.log(chalk.dim("─".repeat(44)));
62
- console.log(chalk.bold(" Next steps:"));
49
+ console.log(chalk.bold(" Fund this wallet (Base network):"));
63
50
  br();
64
- console.log(" " + chalk.bold.white("1.") + chalk.dim(" Make sure your creator wallet has:"));
65
- console.log(" " + chalk.yellow("≥ 200 $OTX") + chalk.dim(" (registration fee auto-sent by CLI)"));
66
- console.log(" " + chalk.yellow("≥ 0.005 ETH") + chalk.dim(" (gas for the $OTX transfer)"));
67
- console.log(" " + chalk.dim(" Check: ") + mono("otonix wallet balance"));
51
+ console.log(" " + chalk.yellow("≥ 200 $OTX") + chalk.dim(" registration fee (auto-sent by CLI)"));
52
+ console.log(" " + chalk.yellow("≥ 0.005 ETH") + chalk.dim(" gas for registration + deployment"));
68
53
  br();
69
- console.log(" " + chalk.bold.white("2.") + chalk.dim(" Fund the agent wallet with ETH for deploy gas:"));
70
- console.log(" " + chalk.yellow("≥ 0.003 ETH") + chalk.dim(" → ") + chalk.white(agent.address));
54
+ console.log(" Send to: " + chalk.bold.white(agent.address));
71
55
  br();
72
- console.log(" " + chalk.bold.white("3.") + chalk.dim(" Register this agent (sends 200 $OTX automatically):"));
73
- console.log(" " + mono(`otonix agent:register --name ${name}`));
56
+ console.log(chalk.dim(" After funded, register:"));
57
+ console.log(" " + mono(`otonix agent:register --name ${name}`));
74
58
  console.log(chalk.dim("─".repeat(44)));
75
59
  });
76
60
  program
77
61
  .command("agent:register")
78
- .description("Register an agent — auto-sends 200 $OTX to Otonix treasury and activates it")
62
+ .description("Register an agent — auto-sends 200 $OTX from agent wallet to Otonix treasury")
79
63
  .requiredOption("--name <name>", "Agent name to register")
80
64
  .action(async (opts) => {
81
65
  header("Agent Registration");
@@ -93,17 +77,11 @@ export function agentCommand(program) {
93
77
  row("Registered at", agent.registeredAt ? new Date(agent.registeredAt).toLocaleString() : "—");
94
78
  return;
95
79
  }
96
- if (!cfg.wallet) {
97
- failure("No creator wallet found. Run: otonix wallet generate");
98
- process.exit(1);
99
- }
100
- const balSpinner = ora("Checking balances...").start();
101
- let creatorOtx, creatorEth;
102
- let agentOtx, agentEth;
80
+ const balSpinner = ora("Checking agent wallet balance...").start();
81
+ let otxBal;
82
+ let ethBal;
103
83
  try {
104
- [creatorOtx, creatorEth, agentOtx, agentEth] = await Promise.all([
105
- getOtxBalance(cfg.wallet.address),
106
- getEthBalance(cfg.wallet.address),
84
+ [otxBal, ethBal] = await Promise.all([
107
85
  getOtxBalance(agent.address),
108
86
  getEthBalance(agent.address),
109
87
  ]);
@@ -114,46 +92,36 @@ export function agentCommand(program) {
114
92
  process.exit(1);
115
93
  }
116
94
  balSpinner.stop();
117
- const creatorOk = creatorOtx >= OTX_REQUIRED && parseFloat(creatorEth) >= 0.0001;
118
- const agentOk = agentOtx >= OTX_REQUIRED && parseFloat(agentEth) >= 0.0001;
119
- const payerKey = creatorOk ? cfg.wallet.privateKey : agent.privateKey;
120
- const payerAddress = creatorOk ? cfg.wallet.address : agent.address;
121
- const payerLabel = creatorOk ? "creator wallet" : "agent wallet";
122
95
  br();
123
- console.log(chalk.dim(" Creator wallet ") + chalk.white(cfg.wallet.address));
124
- row(" $OTX", formatOtx(creatorOtx) + " OTX" + (creatorOtx >= OTX_REQUIRED ? chalk.green(" ✓") : chalk.yellow(" ✗")));
125
- row(" ETH", parseFloat(creatorEth).toFixed(6) + " ETH" + (parseFloat(creatorEth) >= 0.0001 ? chalk.green(" ✓") : chalk.yellow(" ✗")));
126
- br();
127
- console.log(chalk.dim(" Agent wallet ") + chalk.white(agent.address));
128
- row(" $OTX", formatOtx(agentOtx) + " OTX" + (agentOtx >= OTX_REQUIRED ? chalk.green(" ✓") : chalk.yellow(" ✗")));
129
- row(" ETH", parseFloat(agentEth).toFixed(6) + " ETH" + (parseFloat(agentEth) >= 0.0001 ? chalk.green(" ✓") : chalk.yellow(" ✗")));
96
+ row("Agent wallet", agent.address);
97
+ row("$OTX balance", formatOtx(otxBal) + " OTX");
98
+ row("ETH balance", parseFloat(ethBal).toFixed(6) + " ETH (for gas)");
99
+ row("Registration fee", "200 $OTX → Otonix treasury");
100
+ row("Treasury", OTONIX_TREASURY);
130
101
  br();
131
- if (!creatorOk && !agentOk) {
132
- failure("Neither creator nor agent wallet has enough $OTX + ETH.");
133
- info("Need 200 $OTX + ≥ 0.0001 ETH in either wallet.");
102
+ if (otxBal < OTX_REQUIRED) {
103
+ failure(`Insufficient $OTX. Need 200.000, have ${formatOtx(otxBal)}.`);
104
+ info("Fund your agent wallet: " + agent.address);
134
105
  info("Buy $OTX: https://dexscreener.com/base/0xF7E2a6226Ffe0693DD85406AC3A8917cbea5DC40");
135
106
  process.exit(1);
136
107
  }
137
- if (!creatorOk && agentOk) {
138
- console.log(chalk.yellow(" ") + chalk.dim("Creator wallet insufficient using agent wallet instead."));
139
- br();
108
+ if (parseFloat(ethBal) < 0.0001) {
109
+ failure("Insufficient ETH for gas. Send ETH (Base) to your agent wallet.");
110
+ info("Agent wallet: " + agent.address);
111
+ process.exit(1);
140
112
  }
141
- row("Paying from", payerLabel + " (" + payerAddress.slice(0, 10) + "...)");
142
- row("Registration fee", "200 $OTX → Otonix treasury");
143
- row("Treasury", OTONIX_TREASURY);
144
- br();
145
113
  const confirmed = await confirm({
146
- message: `Send 200 $OTX from ${payerLabel} to Otonix treasury to activate "${opts.name}"?`,
114
+ message: `Send 200 $OTX from agent wallet to Otonix treasury to activate "${opts.name}"?`,
147
115
  default: true,
148
116
  });
149
117
  if (!confirmed) {
150
118
  info("Cancelled.");
151
119
  return;
152
120
  }
153
- const sendSpinner = ora(`Sending 200 $OTX from ${payerLabel}...`).start();
121
+ const sendSpinner = ora("Sending 200 $OTX to Otonix treasury...").start();
154
122
  let txHash;
155
123
  try {
156
- txHash = await sendOtx(payerKey, OTONIX_TREASURY, OTX_REQUIRED);
124
+ txHash = await sendOtx(agent.privateKey, OTONIX_TREASURY, OTX_REQUIRED);
157
125
  }
158
126
  catch (err) {
159
127
  sendSpinner.stop();
@@ -186,10 +154,7 @@ export function agentCommand(program) {
186
154
  row("Tx hash", txHash);
187
155
  row("Basescan", "https://basescan.org/tx/" + txHash);
188
156
  br();
189
- console.log(chalk.dim("You can now deploy tokens. Fund the agent with ETH first:"));
190
- console.log(" " + chalk.dim("Agent address:") + " " + chalk.white(agent.address));
191
- br();
192
- console.log(chalk.dim("Then deploy:"));
157
+ console.log(chalk.dim("You can now deploy tokens:"));
193
158
  console.log(" " + mono(`otonix launch token --agent ${opts.name} --name "MyToken" --ticker "MTK" --image "https://..." --description "..."`));
194
159
  }
195
160
  catch (err) {
@@ -221,7 +186,7 @@ export function agentCommand(program) {
221
186
  spinner.stop();
222
187
  br();
223
188
  row("Agent name", name);
224
- row("Address", agent.address);
189
+ row("Wallet address", agent.address);
225
190
  row("Created at", new Date(agent.createdAt).toLocaleString());
226
191
  row("Status", agent.registered
227
192
  ? chalk.green("✓ Registered & Active")
@@ -232,14 +197,22 @@ export function agentCommand(program) {
232
197
  row("ETH balance", parseFloat(eth).toFixed(6) + " ETH");
233
198
  row("$OTX balance", formatOtx(otx) + " OTX");
234
199
  br();
235
- const ethNum = parseFloat(eth);
236
200
  if (!agent.registered) {
237
- console.log(warn("⊘ ") + chalk.dim("Not registered run this to activate:"));
238
- console.log(" " + chalk.cyan(`otonix agent:register --name ${name}`));
239
- console.log(" " + chalk.dim("(auto-sends 200 $OTX from your creator wallet)"));
201
+ if (otx >= OTX_REQUIRED && parseFloat(eth) >= 0.0001) {
202
+ console.log(chalk.green("") + chalk.dim("Wallet funded ready to register:"));
203
+ console.log(" " + chalk.cyan(`otonix agent:register --name ${name}`));
204
+ }
205
+ else {
206
+ console.log(warn("⚠ ") + chalk.dim("Fund this wallet before registering:"));
207
+ if (otx < OTX_REQUIRED)
208
+ console.log(" " + chalk.yellow(`Need ≥ 200 $OTX (have ${formatOtx(otx)})`));
209
+ if (parseFloat(eth) < 0.0001)
210
+ console.log(" " + chalk.yellow("Need ≥ 0.005 ETH for gas"));
211
+ console.log(" " + chalk.dim("Address: ") + chalk.white(agent.address));
212
+ }
240
213
  }
241
- else if (ethNum < 0.0005) {
242
- console.log(warn("⚠ ") + chalk.dim("Low ETH — fund this address with ≥0.001 ETH for gas:"));
214
+ else if (parseFloat(eth) < 0.0005) {
215
+ console.log(warn("⚠ ") + chalk.dim("Low ETH — fund with ≥ 0.003 ETH for token deployment:"));
243
216
  console.log(" " + chalk.white(agent.address));
244
217
  }
245
218
  else {
@@ -270,11 +243,14 @@ export function agentCommand(program) {
270
243
  const results = await Promise.all(names.map(async (n) => {
271
244
  const a = cfg.agents[n];
272
245
  try {
273
- const eth = await getEthBalance(a.address);
274
- return { name: n, address: a.address, eth: parseFloat(eth).toFixed(5), registered: a.registered };
246
+ const [eth, otx] = await Promise.all([
247
+ getEthBalance(a.address),
248
+ getOtxBalance(a.address),
249
+ ]);
250
+ return { name: n, address: a.address, eth: parseFloat(eth).toFixed(5), otx: formatOtx(otx), registered: a.registered };
275
251
  }
276
252
  catch {
277
- return { name: n, address: a.address, eth: "—", registered: a.registered };
253
+ return { name: n, address: a.address, eth: "—", otx: "—", registered: a.registered };
278
254
  }
279
255
  }));
280
256
  spinner.stop();
@@ -283,8 +259,8 @@ export function agentCommand(program) {
283
259
  console.log(status + " " +
284
260
  chalk.bold.white(r.name.padEnd(16)) +
285
261
  chalk.dim(r.address.slice(0, 10) + "...") +
286
- " " +
287
- chalk.yellow(r.eth + " ETH"));
262
+ " " + chalk.yellow(r.eth + " ETH") +
263
+ " " + chalk.dim(r.otx + " OTX"));
288
264
  }
289
265
  br();
290
266
  info(`${names.length} agent(s) total`);
@@ -326,8 +302,7 @@ export function agentCommand(program) {
326
302
  br();
327
303
  console.log(chalk.bold.red("⚠ SECURITY WARNING"));
328
304
  console.log(chalk.dim(" Your private key gives full access to this agent wallet."));
329
- console.log(chalk.dim(" Never share it. Never paste it into websites or chats."));
330
- console.log(chalk.dim(" Store it offline or in a hardware wallet."));
305
+ console.log(chalk.dim(" Never share it. Store it offline or in a hardware wallet."));
331
306
  br();
332
307
  const ok = await confirm({
333
308
  message: `Show private key for agent "${name}" (${agent.address})?`,
@@ -339,12 +314,12 @@ export function agentCommand(program) {
339
314
  }
340
315
  br();
341
316
  row("Agent name", name);
342
- row("Agent address", agent.address);
317
+ row("Wallet address", agent.address);
343
318
  br();
344
319
  console.log(chalk.bold("Private key:"));
345
320
  console.log(chalk.bold.yellow(agent.privateKey));
346
321
  br();
347
322
  console.log(chalk.dim("Import into MetaMask: Settings → Import Account → paste key above."));
348
- console.log(chalk.dim("LP fee rewards (80% WETH) flow to your creator wallet, not this agent wallet."));
323
+ console.log(chalk.dim("80% LP fee rewards (WETH) are sent to this wallet address."));
349
324
  });
350
325
  }
@@ -2,7 +2,7 @@ import { confirm } from "@inquirer/prompts";
2
2
  import ora from "ora";
3
3
  import chalk from "chalk";
4
4
  import { loadConfig, OTONIX_TREASURY } from "../lib/config.js";
5
- import { getEthBalance, BASE_RPC, } from "../lib/chain.js";
5
+ import { getEthBalance, BASE_RPC, BASE_MEV_RPC, } from "../lib/chain.js";
6
6
  import { header, row, failure, info, br, warn, } from "../lib/display.js";
7
7
  const WETH_BASE = "0x4200000000000000000000000000000000000006";
8
8
  const OTONIX_TWITTER = "otonix_tech";
@@ -18,13 +18,10 @@ export function launchCommand(program) {
18
18
  .requiredOption("--description <text>", "Token description")
19
19
  .option("--twitter <handle>", "Your Twitter/X handle (e.g. yourname) — shown in metadata")
20
20
  .option("--devbuy <eth>", "Initial dev buy in ETH (default: 0)", "0")
21
+ .option("--mev-protect", "Route deploy tx through Flashbots private mempool (anti-sandwich)")
21
22
  .action(async (opts) => {
22
23
  header("Launch Token");
23
24
  const cfg = loadConfig();
24
- if (!cfg.wallet) {
25
- failure("No wallet. Run: otonix wallet generate");
26
- process.exit(1);
27
- }
28
25
  const agent = cfg.agents[opts.agent];
29
26
  if (!agent) {
30
27
  failure(`Agent "${opts.agent}" not found. Run: otonix agent:list`);
@@ -66,6 +63,8 @@ export function launchCommand(program) {
66
63
  failure("Pre-flight checks failed. Fix the issues above and try again.");
67
64
  process.exit(1);
68
65
  }
66
+ const useMevProtect = !!opts.mevProtect;
67
+ const activeRpc = useMevProtect ? BASE_MEV_RPC : BASE_RPC;
69
68
  br();
70
69
  console.log(chalk.bold.white("Token to deploy:"));
71
70
  row("Name", opts.name);
@@ -80,8 +79,11 @@ export function launchCommand(program) {
80
79
  row("Paired token", "WETH");
81
80
  if (devBuyEth > 0)
82
81
  row("Dev buy", devBuyEth + " ETH");
83
- row("Reward 80%", cfg.wallet.address + " (WETH → creator wallet)");
82
+ row("Reward 80%", agent.address + " (WETH → agent wallet)");
84
83
  row("Reward 20%", OTONIX_TREASURY + " ($OTX burn)");
84
+ row("MEV protect", useMevProtect
85
+ ? chalk.green("✓ ON") + chalk.dim(" (Flashbots private mempool)")
86
+ : chalk.dim("off (use --mev-protect to enable)"));
85
87
  row("Verified by", "✓ Otonix (@" + OTONIX_TWITTER + ")");
86
88
  br();
87
89
  const confirmed = await confirm({
@@ -92,7 +94,9 @@ export function launchCommand(program) {
92
94
  info("Cancelled.");
93
95
  return;
94
96
  }
95
- const deploySpinner = ora("Deploying token on Base (Clanker v4 / Uniswap v4)...").start();
97
+ const deploySpinner = ora(useMevProtect
98
+ ? "Deploying token via Flashbots private mempool (MEV protected)..."
99
+ : "Deploying token on Base (Clanker v4 / Uniswap v4)...").start();
96
100
  try {
97
101
  const { createWalletClient, createPublicClient, http } = await import("viem");
98
102
  const { base } = await import("viem/chains");
@@ -102,12 +106,12 @@ export function launchCommand(program) {
102
106
  const agentAccount = privateKeyToAccount(agent.privateKey);
103
107
  const publicClient = createPublicClient({
104
108
  chain: base,
105
- transport: http(BASE_RPC),
109
+ transport: http(activeRpc),
106
110
  });
107
111
  const walletClient = createWalletClient({
108
112
  account: agentAccount,
109
113
  chain: base,
110
- transport: http(BASE_RPC),
114
+ transport: http(activeRpc),
111
115
  });
112
116
  const clanker = new Clanker({
113
117
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -124,7 +128,7 @@ export function launchCommand(program) {
124
128
  const tokenConfig = {
125
129
  name: opts.name,
126
130
  symbol: opts.ticker.toUpperCase(),
127
- tokenAdmin: cfg.wallet.address,
131
+ tokenAdmin: agent.address,
128
132
  image: opts.image,
129
133
  metadata: {
130
134
  description: opts.description,
@@ -146,8 +150,8 @@ export function launchCommand(program) {
146
150
  rewards: {
147
151
  recipients: [
148
152
  {
149
- recipient: cfg.wallet.address,
150
- admin: cfg.wallet.address,
153
+ recipient: agent.address,
154
+ admin: agent.address,
151
155
  bps: 8000,
152
156
  token: "Paired",
153
157
  },
@@ -183,7 +187,7 @@ export function launchCommand(program) {
183
187
  txHash,
184
188
  agentName: opts.agent,
185
189
  agentAddress: agent.address,
186
- creatorAddress: cfg.wallet.address,
190
+ creatorAddress: agent.address,
187
191
  imgUrl: opts.image ?? null,
188
192
  description: opts.description ?? null,
189
193
  }),
@@ -1,166 +1,66 @@
1
- import { password, confirm } from "@inquirer/prompts";
2
- import ora from "ora";
3
- import { loadConfig, saveConfig } from "../lib/config.js";
4
- import { getEthBalance, getOtxBalance, formatOtx, generateWallet, addressFromKey, OTX_REQUIRED, } from "../lib/chain.js";
5
- import { header, row, success, failure, info, br, warn } from "../lib/display.js";
1
+ import { header, br } from "../lib/display.js";
6
2
  import chalk from "chalk";
7
3
  export function walletCommand(program) {
8
- const wallet = program.command("wallet").description("Manage your Otonix creator wallet");
4
+ const wallet = program.command("wallet").description("Wallet info each agent has its own wallet");
9
5
  wallet
10
6
  .command("generate")
11
- .description("Generate a new Base wallet (creator wallet for token launches)")
12
- .action(async () => {
13
- header("Generate Creator Wallet");
14
- const cfg = loadConfig();
15
- if (cfg.wallet) {
16
- const overwrite = await confirm({
17
- message: `Wallet ${chalk.dim(cfg.wallet.address)} already exists. Replace it?`,
18
- default: false,
19
- });
20
- if (!overwrite) {
21
- info("Cancelled. Existing wallet kept.");
22
- return;
23
- }
24
- }
25
- const spinner = ora("Generating new Base wallet...").start();
26
- await new Promise(r => setTimeout(r, 500));
27
- const { address, privateKey } = generateWallet();
28
- spinner.stop();
29
- cfg.wallet = { address, privateKey };
30
- saveConfig(cfg);
31
- success("Creator wallet generated!");
32
- br();
33
- row("Address", address);
34
- row("Network", "Base Mainnet");
35
- row("Stored at", "~/.otonix/config.json");
7
+ .description("Wallets are created per-agent. Use: otonix agent:create --name <name>")
8
+ .action(() => {
9
+ header("Wallet Generate");
36
10
  br();
37
- console.log(chalk.dim("Private key is stored locally. Never share it."));
38
- console.log(chalk.dim("To view your private key: ") + chalk.white("otonix wallet export"));
11
+ console.log(chalk.yellow("ℹ Each agent has its own wallet no separate creator wallet needed."));
39
12
  br();
40
- console.log(chalk.dim("Fund this address with:"));
41
- console.log(" " + chalk.yellow("≥200 $OTX") + chalk.dim(" — to activate agents"));
42
- console.log(" " + chalk.yellow("ETH") + chalk.dim(" — for gas fees on Base"));
13
+ console.log(chalk.dim("Create an agent (generates wallet automatically):"));
14
+ console.log(' otonix agent:create --name "MyAgent"');
43
15
  br();
16
+ console.log(chalk.dim("View agent wallet:"));
17
+ console.log(" otonix agent:info MyAgent");
44
18
  });
45
19
  wallet
46
20
  .command("import")
47
- .description("Import an existing wallet using a private key")
48
- .action(async () => {
49
- header("Import Wallet");
50
- info("Your private key is stored locally at ~/.otonix/config.json");
51
- info("Never share it. Otonix never transmits it.");
21
+ .description("Import a private key as an agent wallet")
22
+ .action(() => {
23
+ header("Wallet Import");
52
24
  br();
53
- const cfg = loadConfig();
54
- if (cfg.wallet) {
55
- const overwrite = await confirm({
56
- message: `Wallet ${chalk.dim(cfg.wallet.address)} already connected. Replace it?`,
57
- default: false,
58
- });
59
- if (!overwrite) {
60
- info("Cancelled.");
61
- return;
62
- }
63
- }
64
- const pk = await password({
65
- message: "Enter your private key (0x...):",
66
- mask: "•",
67
- });
68
- if (!pk.startsWith("0x") || pk.length !== 66) {
69
- failure("Invalid private key format. Must be 0x followed by 64 hex chars.");
70
- process.exit(1);
71
- }
72
- const spinner = ora("Verifying key...").start();
73
- try {
74
- const address = addressFromKey(pk);
75
- cfg.wallet = { address, privateKey: pk };
76
- saveConfig(cfg);
77
- spinner.stop();
78
- success("Wallet imported!");
79
- br();
80
- row("Address", address);
81
- row("Config", "~/.otonix/config.json");
82
- }
83
- catch {
84
- spinner.stop();
85
- failure("Invalid private key.");
86
- process.exit(1);
87
- }
25
+ console.log(chalk.yellow("ℹ To import an existing private key as an agent wallet, use:"));
26
+ br();
27
+ console.log(chalk.dim("(This feature is coming soon — for now, create a new agent wallet)"));
28
+ console.log(' otonix agent:create --name "MyAgent"');
88
29
  });
89
30
  wallet
90
31
  .command("export")
91
- .description("Show your private key (keep it safe!)")
92
- .action(async () => {
93
- const cfg = loadConfig();
94
- if (!cfg.wallet) {
95
- failure("No wallet. Run: otonix wallet generate");
96
- process.exit(1);
97
- }
98
- const confirmed = await confirm({
99
- message: chalk.red("⚠ This will display your private key. Continue?"),
100
- default: false,
101
- });
102
- if (!confirmed) {
103
- info("Cancelled.");
104
- return;
105
- }
32
+ .description("Export agent private key use: otonix agent:export <name>")
33
+ .action(() => {
106
34
  header("Wallet Export");
107
35
  br();
108
- row("Address", cfg.wallet.address);
109
- row("Private key", cfg.wallet.privateKey);
36
+ console.log(chalk.yellow("ℹ Private keys are stored per-agent. Export with:"));
110
37
  br();
111
- console.log(chalk.red("Never share this key. Anyone with it controls your wallet."));
38
+ console.log(" otonix agent:export <agent-name>");
112
39
  br();
40
+ console.log(chalk.dim("List your agents:"));
41
+ console.log(" otonix agent:list");
113
42
  });
114
43
  wallet
115
44
  .command("balance")
116
- .description("Show ETH and $OTX balance of your wallet")
117
- .action(async () => {
45
+ .description("Check balance use: otonix agent:info <name>")
46
+ .action(() => {
118
47
  header("Wallet Balance");
119
- const cfg = loadConfig();
120
- if (!cfg.wallet) {
121
- failure("No wallet. Run: otonix wallet generate");
122
- process.exit(1);
123
- }
124
- const address = cfg.wallet.address;
125
- const spinner = ora("Fetching balances from Base...").start();
126
- try {
127
- const [eth, otx] = await Promise.all([
128
- getEthBalance(address),
129
- getOtxBalance(address),
130
- ]);
131
- spinner.stop();
132
- br();
133
- row("Address", address);
134
- row("Network", "Base Mainnet");
135
- row("ETH balance", parseFloat(eth).toFixed(6) + " ETH");
136
- row("$OTX balance", formatOtx(otx) + " OTX");
137
- br();
138
- if (otx >= OTX_REQUIRED) {
139
- console.log(chalk.green("✓ ") + chalk.dim("Eligible to create agents (≥200 $OTX)"));
140
- }
141
- else {
142
- const need = formatOtx(OTX_REQUIRED - otx);
143
- console.log(warn("⚠ ") + chalk.dim(`Need ${need} more $OTX to activate agents`));
144
- }
145
- }
146
- catch {
147
- spinner.stop();
148
- failure("Failed to fetch balances. Check your internet connection.");
149
- process.exit(1);
150
- }
48
+ br();
49
+ console.log(chalk.yellow("ℹ Balances are tracked per-agent. Check with:"));
50
+ br();
51
+ console.log(" otonix agent:info <agent-name>");
52
+ br();
53
+ console.log(chalk.dim("List your agents:"));
54
+ console.log(" otonix agent:list");
151
55
  });
152
56
  wallet
153
57
  .command("address")
154
- .description("Show your connected wallet address")
58
+ .description("Show agent address use: otonix agent:info <name>")
155
59
  .action(() => {
156
- const cfg = loadConfig();
157
- if (!cfg.wallet) {
158
- failure("No wallet. Run: otonix wallet generate");
159
- process.exit(1);
160
- }
161
60
  header("Wallet Address");
162
61
  br();
163
- row("Address", cfg.wallet.address);
164
- row("Network", "Base Mainnet");
62
+ console.log(chalk.yellow("ℹ Each agent has its own wallet address. View with:"));
63
+ br();
64
+ console.log(" otonix agent:info <agent-name>");
165
65
  });
166
66
  }
@@ -1,6 +1,7 @@
1
1
  import { type Address } from "viem";
2
2
  export declare const OTX_ADDRESS: Address;
3
3
  export declare const BASE_RPC = "https://mainnet.base.org";
4
+ export declare const BASE_MEV_RPC = "https://rpc.flashbots.net?chain=8453";
4
5
  export declare const OTX_DECIMALS = 18;
5
6
  export declare const OTX_REQUIRED: bigint;
6
7
  export declare const publicClient: {
package/dist/lib/chain.js CHANGED
@@ -3,6 +3,7 @@ import { base } from "viem/chains";
3
3
  import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
4
4
  export const OTX_ADDRESS = "0xF7E2a6226Ffe0693DD85406AC3A8917cbea5DC40";
5
5
  export const BASE_RPC = "https://mainnet.base.org";
6
+ export const BASE_MEV_RPC = "https://rpc.flashbots.net?chain=8453";
6
7
  export const OTX_DECIMALS = 18;
7
8
  export const OTX_REQUIRED = 200n * 10n ** 18n;
8
9
  export const publicClient = createPublicClient({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otonix/cli",
3
- "version": "2.1.8",
3
+ "version": "2.2.0",
4
4
  "description": "Otonix CLI — deploy autonomous agent tokens on Base via Clanker v4",
5
5
  "type": "module",
6
6
  "bin": {