naracli 1.0.57 → 1.0.58

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.
@@ -126972,6 +126972,29 @@ async function getStakeInfo(connection, user, options) {
126972
126972
  return null;
126973
126973
  }
126974
126974
  }
126975
+ async function getQuestConfig(connection, options) {
126976
+ const kp = import_web390.Keypair.generate();
126977
+ const program3 = createProgram2(connection, kp, options?.programId);
126978
+ const programId = new import_web390.PublicKey(options?.programId ?? DEFAULT_QUEST_PROGRAM_ID);
126979
+ const [configPda] = import_web390.PublicKey.findProgramAddressSync(
126980
+ [new TextEncoder().encode("quest_config")],
126981
+ programId
126982
+ );
126983
+ const config = await program3.account.gameConfig.fetch(configPda);
126984
+ return {
126985
+ authority: config.authority,
126986
+ minRewardCount: config.minRewardCount,
126987
+ maxRewardCount: config.maxRewardCount,
126988
+ stakeBpsHigh: Number(config.stakeBpsHigh.toString()),
126989
+ stakeBpsLow: Number(config.stakeBpsLow.toString()),
126990
+ decayMs: Number(config.decayMs.toString()),
126991
+ treasury: config.treasury,
126992
+ questAuthority: config.questAuthority,
126993
+ minQuestInterval: Number(config.minQuestInterval.toString()),
126994
+ rewardPerShare: Number(config.rewardPerShare.toString()),
126995
+ extraReward: Number(config.extraReward.toString())
126996
+ };
126997
+ }
126975
126998
 
126976
126999
  // node_modules/.pnpm/nara-sdk@1.0.54_bufferutil@4.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@5.9.3_utf-8-validate@6.0.6/node_modules/nara-sdk/src/skills.ts
126977
127000
  var import_web391 = __toESM(require_index_cjs(), 1);
@@ -130963,6 +130986,14 @@ async function handleQuestGet(options) {
130963
130986
  }
130964
130987
  return;
130965
130988
  }
130989
+ let stakeRequired = quest.effectiveStakeRequirement > 0;
130990
+ try {
130991
+ const config = await getQuestConfig(connection);
130992
+ if (quest.rewardCount < config.maxRewardCount) {
130993
+ stakeRequired = false;
130994
+ }
130995
+ } catch {
130996
+ }
130966
130997
  const data = {
130967
130998
  round: quest.round,
130968
130999
  question: quest.question,
@@ -130974,7 +131005,8 @@ async function handleQuestGet(options) {
130974
131005
  deadline: new Date(quest.deadline * 1e3).toLocaleString(),
130975
131006
  timeRemaining: formatTimeRemaining(quest.timeRemaining),
130976
131007
  expired: quest.expired,
130977
- stakeRequirement: `${quest.effectiveStakeRequirement.toFixed(4)} NARA`,
131008
+ stakeRequired,
131009
+ stakeRequirement: stakeRequired ? `${quest.effectiveStakeRequirement.toFixed(4)} NARA` : "0 NARA",
130978
131010
  stakeHigh: `${quest.stakeHigh} NARA`,
130979
131011
  stakeLow: `${quest.stakeLow} NARA`,
130980
131012
  avgParticipantStake: `${quest.avgParticipantStake} NARA`
@@ -130991,8 +131023,10 @@ async function handleQuestGet(options) {
130991
131023
  console.log(
130992
131024
  ` Reward slots: ${quest.winnerCount}/${quest.rewardCount} (${quest.remainingSlots} remaining)`
130993
131025
  );
130994
- if (quest.effectiveStakeRequirement > 0) {
131026
+ if (stakeRequired) {
130995
131027
  console.log(` Stake requirement: ${quest.effectiveStakeRequirement.toFixed(4)} NARA (decays ${quest.stakeHigh} \u2192 ${quest.stakeLow})`);
131028
+ } else {
131029
+ console.log(` Stake requirement: none`);
130996
131030
  }
130997
131031
  console.log(` Deadline: ${new Date(quest.deadline * 1e3).toLocaleString()}`);
130998
131032
  if (quest.timeRemaining > 0) {
@@ -131003,6 +131037,49 @@ async function handleQuestGet(options) {
131003
131037
  console.log("");
131004
131038
  }
131005
131039
  }
131040
+ async function handleQuestConfig(options) {
131041
+ const rpcUrl = getRpcUrl(options.rpcUrl);
131042
+ const connection = new import_web398.Connection(rpcUrl, "confirmed");
131043
+ let config;
131044
+ try {
131045
+ config = await getQuestConfig(connection);
131046
+ } catch (err) {
131047
+ printError(`Failed to fetch quest config: ${err.message}`);
131048
+ process.exit(1);
131049
+ }
131050
+ const DECIMALS = 1e9;
131051
+ const rewardPerShare = config.rewardPerShare / DECIMALS;
131052
+ const extraReward = config.extraReward / DECIMALS;
131053
+ const stakeBpsHigh = config.stakeBpsHigh;
131054
+ const stakeBpsLow = config.stakeBpsLow;
131055
+ const data = {
131056
+ authority: config.authority.toBase58(),
131057
+ questAuthority: config.questAuthority.toBase58(),
131058
+ treasury: config.treasury.toBase58(),
131059
+ minRewardCount: config.minRewardCount,
131060
+ maxRewardCount: config.maxRewardCount,
131061
+ rewardPerShare,
131062
+ extraReward,
131063
+ stakeBpsHigh,
131064
+ stakeBpsLow,
131065
+ decayMs: config.decayMs,
131066
+ minQuestInterval: config.minQuestInterval
131067
+ };
131068
+ if (options.json) {
131069
+ formatOutput(data, true);
131070
+ } else {
131071
+ console.log("");
131072
+ console.log(` Min Reward Count: ${data.minRewardCount}`);
131073
+ console.log(` Max Reward Count: ${data.maxRewardCount}`);
131074
+ console.log(` Reward Per Share: ${rewardPerShare} NARA`);
131075
+ console.log(` Extra Reward: ${extraReward} NARA`);
131076
+ console.log(` Stake BPS High: ${stakeBpsHigh / 100}%`);
131077
+ console.log(` Stake BPS Low: ${stakeBpsLow / 100}%`);
131078
+ console.log(` Decay (ms): ${data.decayMs}`);
131079
+ console.log(` Min Quest Interval: ${data.minQuestInterval}s`);
131080
+ console.log("");
131081
+ }
131082
+ }
131006
131083
  async function handleQuestAnswer(answer, options) {
131007
131084
  const rpcUrl = getRpcUrl(options.rpcUrl);
131008
131085
  const connection = new import_web398.Connection(rpcUrl, "confirmed");
@@ -131229,6 +131306,15 @@ function registerQuestCommands(program3) {
131229
131306
  process.exit(1);
131230
131307
  }
131231
131308
  });
131309
+ quest.command("config").description("Show quest program config (reward counts, stake params, decay, intervals)").action(async (_opts, cmd) => {
131310
+ try {
131311
+ const globalOpts = cmd.optsWithGlobals();
131312
+ await handleQuestConfig(globalOpts);
131313
+ } catch (error) {
131314
+ printError(error.message);
131315
+ process.exit(1);
131316
+ }
131317
+ });
131232
131318
  quest.command("stake <amount>").description("Stake NARA to participate in quests").action(async (amount, _opts, cmd) => {
131233
131319
  try {
131234
131320
  const globalOpts = cmd.optsWithGlobals();
@@ -134174,7 +134260,7 @@ function registerCommands(program3) {
134174
134260
  }
134175
134261
 
134176
134262
  // bin/nara-cli.ts
134177
- var version2 = true ? "1.0.57" : "dev";
134263
+ var version2 = true ? "1.0.58" : "dev";
134178
134264
  var program2 = new Command();
134179
134265
  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
134266
  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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naracli",
3
- "version": "1.0.57",
3
+ "version": "1.0.58",
4
4
  "description": "CLI for the Nara chain (Solana-compatible)",
5
5
  "homepage": "https://nara.build",
6
6
  "repository": {
@@ -16,6 +16,7 @@ import {
16
16
  import type { GlobalOptions } from "../types";
17
17
  import {
18
18
  getQuestInfo,
19
+ getQuestConfig,
19
20
  hasAnswered,
20
21
  generateProof,
21
22
  submitAnswer,
@@ -106,6 +107,17 @@ async function handleQuestGet(options: GlobalOptions) {
106
107
  return;
107
108
  }
108
109
 
110
+ // Stake only applies when reward slots have reached maxRewardCount
111
+ let stakeRequired = quest.effectiveStakeRequirement > 0;
112
+ try {
113
+ const config = await getQuestConfig(connection);
114
+ if (quest.rewardCount < config.maxRewardCount) {
115
+ stakeRequired = false;
116
+ }
117
+ } catch {
118
+ // If config fetch fails, fall back to showing stake as-is
119
+ }
120
+
109
121
  const data: Record<string, any> = {
110
122
  round: quest.round,
111
123
  question: quest.question,
@@ -117,7 +129,8 @@ async function handleQuestGet(options: GlobalOptions) {
117
129
  deadline: new Date(quest.deadline * 1000).toLocaleString(),
118
130
  timeRemaining: formatTimeRemaining(quest.timeRemaining),
119
131
  expired: quest.expired,
120
- stakeRequirement: `${quest.effectiveStakeRequirement.toFixed(4)} NARA`,
132
+ stakeRequired,
133
+ stakeRequirement: stakeRequired ? `${quest.effectiveStakeRequirement.toFixed(4)} NARA` : "0 NARA",
121
134
  stakeHigh: `${quest.stakeHigh} NARA`,
122
135
  stakeLow: `${quest.stakeLow} NARA`,
123
136
  avgParticipantStake: `${quest.avgParticipantStake} NARA`,
@@ -135,8 +148,10 @@ async function handleQuestGet(options: GlobalOptions) {
135
148
  console.log(
136
149
  ` Reward slots: ${quest.winnerCount}/${quest.rewardCount} (${quest.remainingSlots} remaining)`
137
150
  );
138
- if (quest.effectiveStakeRequirement > 0) {
151
+ if (stakeRequired) {
139
152
  console.log(` Stake requirement: ${quest.effectiveStakeRequirement.toFixed(4)} NARA (decays ${quest.stakeHigh} → ${quest.stakeLow})`);
153
+ } else {
154
+ console.log(` Stake requirement: none`);
140
155
  }
141
156
  console.log(` Deadline: ${new Date(quest.deadline * 1000).toLocaleString()}`);
142
157
  if (quest.timeRemaining > 0) {
@@ -148,6 +163,55 @@ async function handleQuestGet(options: GlobalOptions) {
148
163
  }
149
164
  }
150
165
 
166
+ // ─── Command: quest config ───────────────────────────────────────
167
+ async function handleQuestConfig(options: GlobalOptions) {
168
+ const rpcUrl = getRpcUrl(options.rpcUrl);
169
+ const connection = new Connection(rpcUrl, "confirmed");
170
+
171
+ let config;
172
+ try {
173
+ config = await getQuestConfig(connection);
174
+ } catch (err: any) {
175
+ printError(`Failed to fetch quest config: ${err.message}`);
176
+ process.exit(1);
177
+ }
178
+
179
+ const DECIMALS = 1e9;
180
+ const rewardPerShare = config.rewardPerShare / DECIMALS;
181
+ const extraReward = config.extraReward / DECIMALS;
182
+ const stakeBpsHigh = config.stakeBpsHigh;
183
+ const stakeBpsLow = config.stakeBpsLow;
184
+
185
+ const data = {
186
+ authority: config.authority.toBase58(),
187
+ questAuthority: config.questAuthority.toBase58(),
188
+ treasury: config.treasury.toBase58(),
189
+ minRewardCount: config.minRewardCount,
190
+ maxRewardCount: config.maxRewardCount,
191
+ rewardPerShare,
192
+ extraReward,
193
+ stakeBpsHigh,
194
+ stakeBpsLow,
195
+ decayMs: config.decayMs,
196
+ minQuestInterval: config.minQuestInterval,
197
+ };
198
+
199
+ if (options.json) {
200
+ formatOutput(data, true);
201
+ } else {
202
+ console.log("");
203
+ console.log(` Min Reward Count: ${data.minRewardCount}`);
204
+ console.log(` Max Reward Count: ${data.maxRewardCount}`);
205
+ console.log(` Reward Per Share: ${rewardPerShare} NARA`);
206
+ console.log(` Extra Reward: ${extraReward} NARA`);
207
+ console.log(` Stake BPS High: ${stakeBpsHigh / 100}%`);
208
+ console.log(` Stake BPS Low: ${stakeBpsLow / 100}%`);
209
+ console.log(` Decay (ms): ${data.decayMs}`);
210
+ console.log(` Min Quest Interval: ${data.minQuestInterval}s`);
211
+ console.log("");
212
+ }
213
+ }
214
+
151
215
  // ─── Command: quest answer ───────────────────────────────────────
152
216
  async function handleQuestAnswer(
153
217
  answer: string,
@@ -437,6 +501,20 @@ export function registerQuestCommands(program: Command): void {
437
501
  }
438
502
  });
439
503
 
504
+ // quest config
505
+ quest
506
+ .command("config")
507
+ .description("Show quest program config (reward counts, stake params, decay, intervals)")
508
+ .action(async (_opts: any, cmd: Command) => {
509
+ try {
510
+ const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
511
+ await handleQuestConfig(globalOpts);
512
+ } catch (error: any) {
513
+ printError(error.message);
514
+ process.exit(1);
515
+ }
516
+ });
517
+
440
518
  // quest stake
441
519
  quest
442
520
  .command("stake <amount>")