naracli 1.0.70 → 1.0.72
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/dist/nara-cli-bundle.cjs +3571 -2817
- package/package.json +2 -2
- package/src/cli/index.ts +65 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naracli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.72",
|
|
4
4
|
"description": "CLI for the Nara chain (Solana-compatible)",
|
|
5
5
|
"homepage": "https://nara.build",
|
|
6
6
|
"repository": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"bs58": "^6.0.0",
|
|
64
64
|
"commander": "^12.1.0",
|
|
65
65
|
"ed25519-hd-key": "^1.3.0",
|
|
66
|
-
"nara-sdk": "^1.0.
|
|
66
|
+
"nara-sdk": "^1.0.67",
|
|
67
67
|
"picocolors": "^1.1.1"
|
|
68
68
|
},
|
|
69
69
|
"packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
|
package/src/cli/index.ts
CHANGED
|
@@ -114,18 +114,77 @@ export function registerCommands(program: Command): void {
|
|
|
114
114
|
// Top-level: airdrop
|
|
115
115
|
program
|
|
116
116
|
.command("airdrop")
|
|
117
|
-
.description("Claim a free NARA airdrop
|
|
118
|
-
.
|
|
117
|
+
.description("Claim a free NARA airdrop by answering the current quest (once per 24h per address/IP)")
|
|
118
|
+
.argument("[answer]", "Answer to the current quest question")
|
|
119
|
+
.action(async (answer: string | undefined) => {
|
|
119
120
|
const opts = program.opts() as GlobalOptions;
|
|
120
121
|
try {
|
|
121
122
|
const wallet = await loadWallet(opts.wallet);
|
|
122
|
-
const
|
|
123
|
-
|
|
123
|
+
const rpcUrl = getRpcUrl(opts.rpcUrl);
|
|
124
|
+
const connection = new (await import("@solana/web3.js")).Connection(rpcUrl, "confirmed");
|
|
125
|
+
const { getQuestInfo, generateProof } = await import("nara-sdk");
|
|
126
|
+
|
|
127
|
+
// Fetch quest info
|
|
128
|
+
let quest;
|
|
129
|
+
try {
|
|
130
|
+
quest = await getQuestInfo(connection, wallet);
|
|
131
|
+
} catch (err: any) {
|
|
132
|
+
printError(`Failed to fetch quest info: ${err.message}`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!quest.active) {
|
|
137
|
+
printError("No active quest at the moment. Try again later.");
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// No answer provided — show question and prompt
|
|
142
|
+
if (!answer) {
|
|
143
|
+
console.log("");
|
|
144
|
+
console.log(` Question: ${quest.question}`);
|
|
145
|
+
console.log(` Time remaining: ${quest.timeRemaining}s`);
|
|
146
|
+
console.log("");
|
|
147
|
+
console.log(` Answer the question correctly to claim your free NARA airdrop:`);
|
|
148
|
+
console.log(` npx naracli airdrop "<your-answer>"`);
|
|
149
|
+
console.log("");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (quest.expired) {
|
|
154
|
+
printError("Quest has expired. Wait for the next round and try again.");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Generate ZK proof
|
|
159
|
+
printInfo("Generating ZK proof...");
|
|
160
|
+
const _getMetaUrl = () => { try { return import.meta.url; } catch { return undefined; } };
|
|
161
|
+
const zkOptions = _getMetaUrl() ? undefined : {
|
|
162
|
+
circuitWasmPath: (await import("node:path")).join(__dirname, "zk", "answer_proof.wasm"),
|
|
163
|
+
zkeyPath: (await import("node:path")).join(__dirname, "zk", "answer_proof_final.zkey"),
|
|
164
|
+
};
|
|
165
|
+
let proof;
|
|
166
|
+
try {
|
|
167
|
+
proof = await generateProof(answer, quest.answerHash, wallet.publicKey, quest.round, zkOptions);
|
|
168
|
+
} catch (err: any) {
|
|
169
|
+
if (err.message?.includes("Assert Failed")) {
|
|
170
|
+
printError("Wrong answer. Try again with the correct answer.");
|
|
171
|
+
} else {
|
|
172
|
+
printError(`ZK proof generation failed: ${err.message}`);
|
|
173
|
+
}
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
124
176
|
|
|
177
|
+
// Submit to relay airdrop endpoint
|
|
178
|
+
printInfo("Submitting airdrop claim...");
|
|
125
179
|
const res = await fetch("https://quest-api.nara.build/airdrop", {
|
|
126
180
|
method: "POST",
|
|
127
181
|
headers: { "Content-Type": "application/json" },
|
|
128
|
-
body: JSON.stringify({
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
wallet: wallet.publicKey.toBase58(),
|
|
184
|
+
proofA: proof.hex.proofA,
|
|
185
|
+
proofB: proof.hex.proofB,
|
|
186
|
+
proofC: proof.hex.proofC,
|
|
187
|
+
}),
|
|
129
188
|
});
|
|
130
189
|
const data = await res.json() as any;
|
|
131
190
|
|
|
@@ -142,7 +201,7 @@ export function registerCommands(program: Command): void {
|
|
|
142
201
|
if (opts.json) {
|
|
143
202
|
console.log(JSON.stringify(data, null, 2));
|
|
144
203
|
} else {
|
|
145
|
-
printSuccess(`Airdrop
|
|
204
|
+
printSuccess(`Airdrop claimed!`);
|
|
146
205
|
console.log(` Transaction: ${data.txHash}`);
|
|
147
206
|
}
|
|
148
207
|
} catch (error: any) {
|