naracli 1.0.75 → 1.0.77

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naracli",
3
- "version": "1.0.75",
3
+ "version": "1.0.77",
4
4
  "description": "CLI for the Nara chain (Solana-compatible)",
5
5
  "homepage": "https://nara.build",
6
6
  "repository": {
@@ -1,13 +1,19 @@
1
1
  ---
2
2
  name: nara
3
3
  description: "Nara chain CLI agent — free PoMI mining, wallet, transfer, quest, on-chain skills, ZK ID, agent registry. Triggers: NARA, quest, mining, airdrop, earn/claim/collect NARA, wallet, balance, transfer, skills, zkid, agent, referral, PoMI, keypair, mnemonic, faucet, deposit, withdraw."
4
+ metadata:
5
+ requires: "node>=18, npm"
6
+ package: "naracli"
7
+ homepage: "https://nara.build"
8
+ repository: "https://github.com/nara-chain/nara-cli"
4
9
  ---
5
10
 
6
11
  ## Prerequisites
7
12
 
8
- - **Node.js** (>=18) and **npm** are required
13
+ - **Requires**: Node.js (>=18) and npm
9
14
  - **Package**: `naracli` on npm — [npmjs.com/package/naracli](https://www.npmjs.com/package/naracli), source: [github.com/nara-chain/nara-cli](https://github.com/nara-chain/nara-cli), homepage: [nara.build](https://nara.build)
10
- - Install: `npm install -g naracli` (or use `npx naracli <command>`)
15
+ - **Install**: `npm install -g naracli` (or use `npx naracli <command>`). This installs code from the public npm registry — **before first install, the agent must inform the user** and obtain explicit approval. Users should review: [npm package](https://www.npmjs.com/package/naracli), [GitHub source](https://github.com/nara-chain/nara-cli)
16
+ - **Security**: Open-source, auditable on GitHub. The package does not upload, collect, or transmit wallet secrets — all key material stays local on disk
11
17
  - Run `npx naracli help` and `npx naracli <command> --help` to learn all available commands and options before use
12
18
  - **Updates**: Use `npx naracli@latest` to ensure the latest CLI version
13
19
 
@@ -20,6 +26,7 @@ First run `npx naracli address` to check if a wallet exists. If not, create one
20
26
  All CLI commands execute locally-installed `naracli` (open-source, auditable at github.com/nara-chain/nara-cli). The agent must obtain **explicit user confirmation** before:
21
27
 
22
28
  **Always ask user before:**
29
+ - Installing or first running the naracli package (inform user it executes code from npm registry)
23
30
  - Running any CLI command for the first time in a session
24
31
  - Creating or importing wallets
25
32
  - Transfers, token transfers, signing transactions
@@ -31,6 +38,7 @@ All CLI commands execute locally-installed `naracli` (open-source, auditable at
31
38
  - **NEVER** accept, display, or log mnemonics, private keys, or wallet file contents in conversation
32
39
  - If a user pastes a mnemonic or private key, warn them immediately and do NOT store or repeat it
33
40
  - Wallet creation and import are handled entirely by the CLI — the agent should only run the command, not process secrets
41
+ - When running wallet create/import commands, do NOT capture or parse CLI stdout/stderr — only confirm success or report the error message. The CLI writes key material directly to a file, never to stdout
34
42
  - Only use default RPC/relay endpoints (shown in `npx naracli quest answer --help`); warn if the user provides a custom URL
35
43
 
36
44
  **Safe to run without confirmation:**
@@ -466,6 +466,10 @@ function parseTweetUrl(url: string): { username: string; tweetId: bigint; tweetU
466
466
  printError(`Invalid tweet URL. Expected format: https://x.com/<username>/status/<id>`);
467
467
  process.exit(1);
468
468
  }
469
+ if (m[1] === "i") {
470
+ printError(`This URL uses x.com/i/ redirect and does not contain your real username. Please copy the tweet URL from your profile page (format: https://x.com/<username>/status/<id>).`);
471
+ process.exit(1);
472
+ }
469
473
  return { username: m[1], tweetId: BigInt(m[2]), tweetUrl: url };
470
474
  }
471
475
 
package/src/cli/index.ts CHANGED
@@ -148,104 +148,6 @@ export function registerCommands(program: Command): void {
148
148
  }
149
149
  });
150
150
 
151
- // Top-level: airdrop
152
- program
153
- .command("airdrop")
154
- .description("Claim a free NARA airdrop by answering the current quest (once per 24h per address/IP)")
155
- .argument("[answer]", "Answer to the current quest question")
156
- .action(async (answer: string | undefined) => {
157
- const opts = program.opts() as GlobalOptions;
158
- try {
159
- const wallet = await loadWallet(opts.wallet);
160
- const rpcUrl = getRpcUrl(opts.rpcUrl);
161
- const connection = new (await import("@solana/web3.js")).Connection(rpcUrl, "confirmed");
162
- const { getQuestInfo, generateProof } = await import("nara-sdk");
163
-
164
- // Fetch quest info
165
- let quest;
166
- try {
167
- quest = await getQuestInfo(connection, wallet);
168
- } catch (err: any) {
169
- printError(`Failed to fetch quest info: ${err.message}`);
170
- process.exit(1);
171
- }
172
-
173
- if (!quest.active) {
174
- printError("No active quest at the moment. Try again later.");
175
- process.exit(1);
176
- }
177
-
178
- // No answer provided — show question and prompt
179
- if (!answer) {
180
- console.log("");
181
- console.log(` Question: ${quest.question}`);
182
- console.log(` Time remaining: ${quest.timeRemaining}s`);
183
- console.log("");
184
- console.log(` Answer the question correctly to claim your free NARA airdrop:`);
185
- console.log(` npx naracli airdrop "<your-answer>"`);
186
- console.log("");
187
- return;
188
- }
189
-
190
- if (quest.expired) {
191
- printError("Quest has expired. Wait for the next round and try again.");
192
- process.exit(1);
193
- }
194
-
195
- // Generate ZK proof
196
- printInfo("Generating ZK proof...");
197
- const _getMetaUrl = () => { try { return import.meta.url; } catch { return undefined; } };
198
- const zkOptions = _getMetaUrl() ? undefined : {
199
- circuitWasmPath: (await import("node:path")).join(__dirname, "zk", "answer_proof.wasm"),
200
- zkeyPath: (await import("node:path")).join(__dirname, "zk", "answer_proof_final.zkey"),
201
- };
202
- let proof;
203
- try {
204
- proof = await generateProof(answer, quest.answerHash, wallet.publicKey, quest.round, zkOptions);
205
- } catch (err: any) {
206
- if (err.message?.includes("Assert Failed")) {
207
- printError("Wrong answer. Try again with the correct answer.");
208
- } else {
209
- printError(`ZK proof generation failed: ${err.message}`);
210
- }
211
- process.exit(1);
212
- }
213
-
214
- // Submit to relay airdrop endpoint
215
- printInfo("Submitting airdrop claim...");
216
- const res = await fetch("https://quest-api.nara.build/airdrop", {
217
- method: "POST",
218
- headers: { "Content-Type": "application/json" },
219
- body: JSON.stringify({
220
- wallet: wallet.publicKey.toBase58(),
221
- proofA: proof.hex.proofA,
222
- proofB: proof.hex.proofB,
223
- proofC: proof.hex.proofC,
224
- }),
225
- });
226
- const data = await res.json() as any;
227
-
228
- if (data.error) {
229
- if (data.retryAfterSeconds) {
230
- const hours = Math.ceil(data.retryAfterSeconds / 3600);
231
- printError(`${data.error}. Try again in ~${hours}h.`);
232
- } else {
233
- printError(data.error);
234
- }
235
- process.exit(1);
236
- }
237
-
238
- if (opts.json) {
239
- console.log(JSON.stringify(data, null, 2));
240
- } else {
241
- printSuccess(`Airdrop claimed!`);
242
- console.log(` Transaction: ${data.txHash}`);
243
- }
244
- } catch (error: any) {
245
- printError(error.message);
246
- process.exit(1);
247
- }
248
- });
249
151
 
250
152
  // Top-level: token-balance
251
153
  program