naracli 1.0.55 → 1.0.57

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/bin/nara-cli.ts CHANGED
@@ -15,13 +15,13 @@ const program = new Command();
15
15
  // Set program metadata
16
16
  program
17
17
  .name("naracli")
18
- .description("CLI for the Nara chain (Solana-compatible)")
18
+ .description("CLI for the Nara chain. Native coin is NARA (not SOL). Mine NARA for free via PoMI quests, manage wallets, register agents, and more. Run 'naracli <command> --help' for details on any command.")
19
19
  .version(version);
20
20
 
21
21
  // Add global options
22
22
  program
23
- .option("-r, --rpc-url <url>", "RPC endpoint URL")
24
- .option("-w, --wallet <path>", "Path to wallet keypair JSON file")
23
+ .option("-r, --rpc-url <url>", "RPC endpoint (default: https://mainnet-api.nara.build/)")
24
+ .option("-w, --wallet <path>", "Path to wallet keypair JSON file (default: ~/.config/nara/id.json)")
25
25
  .option("-j, --json", "Output in JSON format");
26
26
 
27
27
  // Register all command modules
@@ -130513,8 +130513,8 @@ ${result.base64}`);
130513
130513
  var _DEFAULT_WALLET_PATH = process.env.WALLET_PATH || "~/.config/nara/id.json";
130514
130514
  var DEFAULT_WALLET_PATH2 = _DEFAULT_WALLET_PATH.startsWith("~") ? (0, import_node_path3.join)((0, import_node_os3.homedir)(), _DEFAULT_WALLET_PATH.slice(1)) : _DEFAULT_WALLET_PATH;
130515
130515
  function registerWalletCommands(program3) {
130516
- const wallet = program3.command("wallet").description("Wallet management commands");
130517
- wallet.command("create").description("Create a new wallet").option("-o, --output <path>", "Output path for wallet file (default: ~/.config/nara/id.json)").action(async (options) => {
130516
+ const wallet = program3.command("wallet").description("Wallet management \u2014 create or import a keypair for signing transactions");
130517
+ wallet.command("create").description("Create a new wallet keypair (saved to ~/.config/nara/id.json by default)").option("-o, --output <path>", "Output path for wallet file (default: ~/.config/nara/id.json)").action(async (options) => {
130518
130518
  try {
130519
130519
  await handleWalletCreate(options);
130520
130520
  } catch (error) {
@@ -130580,7 +130580,12 @@ async function handleTokenBalance(tokenAddress, options) {
130580
130580
  }
130581
130581
  printInfo(`Owner: ${owner.toBase58()}`);
130582
130582
  printInfo(`Token: ${tokenAddress}`);
130583
- const tokenAccount = await getAssociatedTokenAddress(tokenMint, owner);
130583
+ const mintAccountInfo = await connection.getAccountInfo(tokenMint);
130584
+ if (!mintAccountInfo) {
130585
+ throw new Error(`Token mint ${tokenAddress} not found on chain`);
130586
+ }
130587
+ const tokenProgramId = mintAccountInfo.owner.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
130588
+ const tokenAccount = await getAssociatedTokenAddress(tokenMint, owner, true, tokenProgramId);
130584
130589
  try {
130585
130590
  const accountInfo = await connection.getTokenAccountBalance(tokenAccount);
130586
130591
  const balance = accountInfo.value;
@@ -131203,8 +131208,8 @@ function handleSubmitError(err) {
131203
131208
  process.exit(1);
131204
131209
  }
131205
131210
  function registerQuestCommands(program3) {
131206
- const quest = program3.command("quest").description("Quest commands");
131207
- quest.command("get").description("Get current quest info").action(async (_opts, cmd) => {
131211
+ const quest = program3.command("quest").description("PoMI quest commands \u2014 mine NARA by answering on-chain quests with ZK proofs");
131212
+ quest.command("get").description("Get current quest info (question, deadline, difficulty, stake requirement)").action(async (_opts, cmd) => {
131208
131213
  try {
131209
131214
  const globalOpts = cmd.optsWithGlobals();
131210
131215
  await handleQuestGet(globalOpts);
@@ -131213,7 +131218,7 @@ function registerQuestCommands(program3) {
131213
131218
  process.exit(1);
131214
131219
  }
131215
131220
  });
131216
- quest.command("answer <answer>").description("Submit an answer").option("--relay [url]", `Submit via relay service, gasless (default: ${DEFAULT_QUEST_RELAY_URL2})`).option("--agent <name>", "Agent identifier (default: naracli)").option("--model <name>", "Model identifier").option("--referral <agent-id>", "Referral agent ID").option("--stake [amount]", 'Stake NARA before answering ("auto" to top-up to requirement, or a number)').action(async (answer, opts, cmd) => {
131221
+ quest.command("answer <answer>").description("Submit a quest answer with ZK proof. Generates a proof locally and submits on-chain. Use --relay when balance is 0 (gasless). Always pass --agent and --model for reward tracking.").option("--relay [url]", `Submit via gasless relay (default: ${DEFAULT_QUEST_RELAY_URL2}, backup: https://quest2-api.nara.build/)`).option("--agent <name>", "Agent/platform type: claude-code, cursor, chatgpt, openclaw, etc. (default: naracli)").option("--model <name>", "AI model used: claude-opus-4-6, claude-sonnet-4-6, gpt-4o, etc.").option("--referral <agent-id>", "Referral agent ID for earning referral points").option("--stake [amount]", 'Stake NARA in the same tx ("auto" to top-up to requirement, or an exact amount)').action(async (answer, opts, cmd) => {
131217
131222
  try {
131218
131223
  const globalOpts = cmd.optsWithGlobals();
131219
131224
  const relayUrl = opts.relay === true ? DEFAULT_QUEST_RELAY_URL2 : opts.relay;
@@ -133142,7 +133147,7 @@ async function handleSkillsDelete(name, options) {
133142
133147
  }
133143
133148
  }
133144
133149
  function registerSkillsCommands(program3) {
133145
- const skills = program3.command("skills").description("Skills hub commands");
133150
+ const skills = program3.command("skills").description("On-chain skill registry \u2014 register, publish, install, and manage AI agent skills");
133146
133151
  skills.command("register <name> <author>").description("Register a new skill on-chain").action(async (name, author, _opts, cmd) => {
133147
133152
  try {
133148
133153
  const globalOpts = cmd.optsWithGlobals();
@@ -133808,8 +133813,8 @@ async function handleAgentClear(options) {
133808
133813
  }
133809
133814
  }
133810
133815
  function registerAgentCommands(program3) {
133811
- const agent = program3.command("agent").description("Agent Registry commands (on-chain AI agents)");
133812
- agent.command("register <agent-id>").description("Register a new agent on-chain").option("--referral <agent-id>", "Referral agent ID").action(async (agentId, opts, cmd) => {
133816
+ const agent = program3.command("agent").description("Agent Registry \u2014 register an on-chain AI agent identity to earn extra rewards and points from PoMI mining");
133817
+ agent.command("register <agent-id>").description("Register a new agent on-chain (costs 1 NARA, 50% off with referral). Agent ID must be lowercase alphanumeric with hyphens.").option("--referral <agent-id>", "Referral agent ID \u2014 saves 50% on registration fee").action(async (agentId, opts, cmd) => {
133813
133818
  try {
133814
133819
  const globalOpts = cmd.optsWithGlobals();
133815
133820
  await handleAgentRegister(agentId, { ...globalOpts, ...opts });
@@ -134043,7 +134048,7 @@ function registerCommands(program3) {
134043
134048
  registerZkIdCommands(program3);
134044
134049
  registerAgentCommands(program3);
134045
134050
  registerConfigCommands(program3);
134046
- program3.command("address").description("Show wallet address").action(async () => {
134051
+ program3.command("address").description("Show wallet public address (run this first to check if a wallet exists)").action(async () => {
134047
134052
  const opts = program3.opts();
134048
134053
  try {
134049
134054
  await handleWalletAddress(opts);
@@ -134052,7 +134057,7 @@ function registerCommands(program3) {
134052
134057
  process.exit(1);
134053
134058
  }
134054
134059
  });
134055
- program3.command("balance").description("Check NARA balance").argument("[address]", "Wallet address (optional, defaults to current wallet)").action(async (address) => {
134060
+ program3.command("balance").description("Check NARA balance (native coin, not SOL)").argument("[address]", "Wallet address (optional, defaults to current wallet)").action(async (address) => {
134056
134061
  const opts = program3.opts();
134057
134062
  try {
134058
134063
  await handleWalletBalance(address, opts);
@@ -134061,7 +134066,7 @@ function registerCommands(program3) {
134061
134066
  process.exit(1);
134062
134067
  }
134063
134068
  });
134064
- program3.command("token-balance <token-address>").description("Check token balance").option("--owner <address>", "Owner address (optional, defaults to current wallet)").action(async (tokenAddress, options) => {
134069
+ program3.command("token-balance <token-address>").description("Check token balance (supports SPL Token and Token-2022)").option("--owner <address>", "Owner address (optional, defaults to current wallet)").action(async (tokenAddress, options) => {
134065
134070
  const opts = program3.opts();
134066
134071
  try {
134067
134072
  await handleTokenBalance(tokenAddress, { ...opts, ...options });
@@ -134118,7 +134123,7 @@ function registerCommands(program3) {
134118
134123
  process.exit(1);
134119
134124
  }
134120
134125
  });
134121
- program3.command("sign <base64-tx>").description("Sign a base64-encoded transaction").option("--send", "Send the signed transaction", false).action(async (base64Tx, options) => {
134126
+ program3.command("sign <base64-tx>").description("Sign a base64-encoded transaction (supports legacy and versioned transactions)").option("--send", "Sign and broadcast the transaction on-chain", false).action(async (base64Tx, options) => {
134122
134127
  const opts = program3.opts();
134123
134128
  try {
134124
134129
  const wallet = await loadWallet(opts.wallet);
@@ -134169,10 +134174,10 @@ function registerCommands(program3) {
134169
134174
  }
134170
134175
 
134171
134176
  // bin/nara-cli.ts
134172
- var version2 = true ? "1.0.55" : "dev";
134177
+ var version2 = true ? "1.0.57" : "dev";
134173
134178
  var program2 = new Command();
134174
- program2.name("naracli").description("CLI for the Nara chain (Solana-compatible)").version(version2);
134175
- program2.option("-r, --rpc-url <url>", "RPC endpoint URL").option("-w, --wallet <path>", "Path to wallet keypair JSON file").option("-j, --json", "Output in JSON format");
134179
+ program2.name("naracli").description("CLI for the Nara chain. Native coin is NARA (not SOL). Mine NARA for free via PoMI quests, manage wallets, register agents, and more. Run 'naracli <command> --help' for details on any command.").version(version2);
134180
+ program2.option("-r, --rpc-url <url>", "RPC endpoint (default: https://mainnet-api.nara.build/)").option("-w, --wallet <path>", "Path to wallet keypair JSON file (default: ~/.config/nara/id.json)").option("-j, --json", "Output in JSON format");
134176
134181
  registerCommands(program2);
134177
134182
  if (!process.argv.slice(2).length) {
134178
134183
  program2.outputHelp();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naracli",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
4
4
  "description": "CLI for the Nara chain (Solana-compatible)",
5
5
  "homepage": "https://nara.build",
6
6
  "repository": {
@@ -304,13 +304,13 @@ async function handleAgentClear(options: GlobalOptions) {
304
304
  export function registerAgentCommands(program: Command): void {
305
305
  const agent = program
306
306
  .command("agent")
307
- .description("Agent Registry commands (on-chain AI agents)");
307
+ .description("Agent Registry register an on-chain AI agent identity to earn extra rewards and points from PoMI mining");
308
308
 
309
309
  // agent register
310
310
  agent
311
311
  .command("register <agent-id>")
312
- .description("Register a new agent on-chain")
313
- .option("--referral <agent-id>", "Referral agent ID")
312
+ .description("Register a new agent on-chain (costs 1 NARA, 50% off with referral). Agent ID must be lowercase alphanumeric with hyphens.")
313
+ .option("--referral <agent-id>", "Referral agent ID — saves 50% on registration fee")
314
314
  .action(async (agentId: string, opts: { referral?: string }, cmd: Command) => {
315
315
  try {
316
316
  const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
@@ -400,12 +400,12 @@ function handleSubmitError(err: any) {
400
400
  export function registerQuestCommands(program: Command): void {
401
401
  const quest = program
402
402
  .command("quest")
403
- .description("Quest commands");
403
+ .description("PoMI quest commands — mine NARA by answering on-chain quests with ZK proofs");
404
404
 
405
405
  // quest get
406
406
  quest
407
407
  .command("get")
408
- .description("Get current quest info")
408
+ .description("Get current quest info (question, deadline, difficulty, stake requirement)")
409
409
  .action(async (_opts: any, cmd: Command) => {
410
410
  try {
411
411
  const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
@@ -419,12 +419,12 @@ export function registerQuestCommands(program: Command): void {
419
419
  // quest answer
420
420
  quest
421
421
  .command("answer <answer>")
422
- .description("Submit an answer")
423
- .option("--relay [url]", `Submit via relay service, gasless (default: ${DEFAULT_QUEST_RELAY_URL})`)
424
- .option("--agent <name>", "Agent identifier (default: naracli)")
425
- .option("--model <name>", "Model identifier")
426
- .option("--referral <agent-id>", "Referral agent ID")
427
- .option("--stake [amount]", 'Stake NARA before answering ("auto" to top-up to requirement, or a number)')
422
+ .description("Submit a quest answer with ZK proof. Generates a proof locally and submits on-chain. Use --relay when balance is 0 (gasless). Always pass --agent and --model for reward tracking.")
423
+ .option("--relay [url]", `Submit via gasless relay (default: ${DEFAULT_QUEST_RELAY_URL}, backup: https://quest2-api.nara.build/)`)
424
+ .option("--agent <name>", "Agent/platform type: claude-code, cursor, chatgpt, openclaw, etc. (default: naracli)")
425
+ .option("--model <name>", "AI model used: claude-opus-4-6, claude-sonnet-4-6, gpt-4o, etc.")
426
+ .option("--referral <agent-id>", "Referral agent ID for earning referral points")
427
+ .option("--stake [amount]", 'Stake NARA in the same tx ("auto" to top-up to requirement, or an exact amount)')
428
428
  .action(async (answer: string, opts: any, cmd: Command) => {
429
429
  try {
430
430
  const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
@@ -281,7 +281,7 @@ async function handleSkillsDelete(name: string, options: GlobalOptions & { yes?:
281
281
  export function registerSkillsCommands(program: Command): void {
282
282
  const skills = program
283
283
  .command("skills")
284
- .description("Skills hub commands");
284
+ .description("On-chain skill registry — register, publish, install, and manage AI agent skills");
285
285
 
286
286
  // skills register
287
287
  skills
@@ -14,6 +14,7 @@ import {
14
14
  getAssociatedTokenAddress,
15
15
  createTransferInstruction,
16
16
  TOKEN_PROGRAM_ID,
17
+ TOKEN_2022_PROGRAM_ID,
17
18
  } from "@solana/spl-token";
18
19
  import * as bip39 from "bip39";
19
20
  import { derivePath } from "ed25519-hd-key";
@@ -54,12 +55,12 @@ const DEFAULT_WALLET_PATH = _DEFAULT_WALLET_PATH.startsWith("~")
54
55
  export function registerWalletCommands(program: Command): void {
55
56
  const wallet = program
56
57
  .command("wallet")
57
- .description("Wallet management commands");
58
+ .description("Wallet management — create or import a keypair for signing transactions");
58
59
 
59
60
  // wallet create
60
61
  wallet
61
62
  .command("create")
62
- .description("Create a new wallet")
63
+ .description("Create a new wallet keypair (saved to ~/.config/nara/id.json by default)")
63
64
  .option("-o, --output <path>", "Output path for wallet file (default: ~/.config/nara/id.json)")
64
65
  .action(async (options: { output?: string }) => {
65
66
  try {
@@ -176,8 +177,17 @@ export async function handleTokenBalance(
176
177
  printInfo(`Owner: ${owner.toBase58()}`);
177
178
  printInfo(`Token: ${tokenAddress}`);
178
179
 
180
+ // Detect token program (SPL Token vs Token-2022) by checking mint account owner
181
+ const mintAccountInfo = await connection.getAccountInfo(tokenMint);
182
+ if (!mintAccountInfo) {
183
+ throw new Error(`Token mint ${tokenAddress} not found on chain`);
184
+ }
185
+ const tokenProgramId = mintAccountInfo.owner.equals(TOKEN_2022_PROGRAM_ID)
186
+ ? TOKEN_2022_PROGRAM_ID
187
+ : TOKEN_PROGRAM_ID;
188
+
179
189
  // Get associated token account
180
- const tokenAccount = await getAssociatedTokenAddress(tokenMint, owner);
190
+ const tokenAccount = await getAssociatedTokenAddress(tokenMint, owner, true, tokenProgramId);
181
191
 
182
192
  // Get token account balance
183
193
  try {
package/src/cli/index.ts CHANGED
@@ -85,7 +85,7 @@ export function registerCommands(program: Command): void {
85
85
  // Top-level: address
86
86
  program
87
87
  .command("address")
88
- .description("Show wallet address")
88
+ .description("Show wallet public address (run this first to check if a wallet exists)")
89
89
  .action(async () => {
90
90
  const opts = program.opts() as GlobalOptions;
91
91
  try {
@@ -99,7 +99,7 @@ export function registerCommands(program: Command): void {
99
99
  // Top-level: balance
100
100
  program
101
101
  .command("balance")
102
- .description("Check NARA balance")
102
+ .description("Check NARA balance (native coin, not SOL)")
103
103
  .argument("[address]", "Wallet address (optional, defaults to current wallet)")
104
104
  .action(async (address: string | undefined) => {
105
105
  const opts = program.opts() as WalletBalanceOptions;
@@ -114,7 +114,7 @@ export function registerCommands(program: Command): void {
114
114
  // Top-level: token-balance
115
115
  program
116
116
  .command("token-balance <token-address>")
117
- .description("Check token balance")
117
+ .description("Check token balance (supports SPL Token and Token-2022)")
118
118
  .option("--owner <address>", "Owner address (optional, defaults to current wallet)")
119
119
  .action(async (tokenAddress: string, options: { owner?: string }) => {
120
120
  const opts = program.opts() as TokenBalanceOptions;
@@ -199,8 +199,8 @@ export function registerCommands(program: Command): void {
199
199
  // Top-level: sign
200
200
  program
201
201
  .command("sign <base64-tx>")
202
- .description("Sign a base64-encoded transaction")
203
- .option("--send", "Send the signed transaction", false)
202
+ .description("Sign a base64-encoded transaction (supports legacy and versioned transactions)")
203
+ .option("--send", "Sign and broadcast the transaction on-chain", false)
204
204
  .action(async (base64Tx: string, options: { send?: boolean }) => {
205
205
  const opts = program.opts() as GlobalOptions;
206
206
  try {