naracli 1.0.37 → 1.0.44
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 +2991 -36815
- package/package.json +4 -3
- package/src/cli/commands/agent.ts +8 -2
- package/src/cli/commands/quest.ts +143 -8
- package/src/tests/helpers.ts +20 -0
- package/src/tests/quest-referral.test.ts +15 -22
- package/src/tests/quest.test.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naracli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.44",
|
|
4
4
|
"description": "CLI for the Nara chain (Solana-compatible)",
|
|
5
5
|
"module": "index.ts",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"bs58": "^6.0.0",
|
|
57
57
|
"commander": "^12.1.0",
|
|
58
58
|
"ed25519-hd-key": "^1.3.0",
|
|
59
|
-
"nara-sdk": "^1.0.
|
|
59
|
+
"nara-sdk": "^1.0.44",
|
|
60
60
|
"picocolors": "^1.1.1"
|
|
61
|
-
}
|
|
61
|
+
},
|
|
62
|
+
"packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
|
|
62
63
|
}
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import type { GlobalOptions } from "../types";
|
|
16
16
|
import {
|
|
17
17
|
registerAgent,
|
|
18
|
+
registerAgentWithReferral,
|
|
18
19
|
getAgentInfo,
|
|
19
20
|
getAgentMemory,
|
|
20
21
|
setBio,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
transferAgentAuthority,
|
|
25
26
|
deleteAgent,
|
|
26
27
|
logActivity,
|
|
28
|
+
logActivityWithReferral,
|
|
27
29
|
setReferral as setReferralOnChain,
|
|
28
30
|
} from "nara-sdk";
|
|
29
31
|
import { readFileSync } from "node:fs";
|
|
@@ -39,7 +41,9 @@ async function handleAgentRegister(agentId: string, options: GlobalOptions & { r
|
|
|
39
41
|
const wallet = await loadWallet(options.wallet);
|
|
40
42
|
|
|
41
43
|
if (!options.json) printInfo(`Registering agent "${agentId}"...`);
|
|
42
|
-
const result =
|
|
44
|
+
const result = options.referral
|
|
45
|
+
? await registerAgentWithReferral(connection, wallet, agentId, options.referral)
|
|
46
|
+
: await registerAgent(connection, wallet, agentId);
|
|
43
47
|
if (!options.json) printSuccess(`Agent "${agentId}" registered!`);
|
|
44
48
|
addAgentId(agentId, rpcUrl);
|
|
45
49
|
|
|
@@ -255,7 +259,9 @@ async function handleAgentLog(
|
|
|
255
259
|
const referral = options.referral;
|
|
256
260
|
|
|
257
261
|
if (!options.json) printInfo(`Logging activity for "${agentId}"...`);
|
|
258
|
-
const signature =
|
|
262
|
+
const signature = referral
|
|
263
|
+
? await logActivityWithReferral(connection, wallet, agentId, model, activity, log, referral)
|
|
264
|
+
: await logActivity(connection, wallet, agentId, model, activity, log);
|
|
259
265
|
if (!options.json) printSuccess("Activity logged!");
|
|
260
266
|
|
|
261
267
|
if (options.json) {
|
|
@@ -20,7 +20,11 @@ import {
|
|
|
20
20
|
submitAnswer,
|
|
21
21
|
submitAnswerViaRelay,
|
|
22
22
|
parseQuestReward,
|
|
23
|
+
stake as questStake,
|
|
24
|
+
unstake as questUnstake,
|
|
25
|
+
getStakeInfo,
|
|
23
26
|
type ActivityLog,
|
|
27
|
+
type StakeInfo,
|
|
24
28
|
} from "nara-sdk";
|
|
25
29
|
import { loadNetworkConfig } from "../utils/agent-config";
|
|
26
30
|
|
|
@@ -34,9 +38,12 @@ const QUEST_ERRORS: Record<number, string> = {
|
|
|
34
38
|
6003: "invalidProof",
|
|
35
39
|
6004: "invalidDeadline",
|
|
36
40
|
6005: "insufficientReward",
|
|
37
|
-
6006: "
|
|
38
|
-
6007: "
|
|
39
|
-
6008: "
|
|
41
|
+
6006: "questionTooLong",
|
|
42
|
+
6007: "alreadyAnswered",
|
|
43
|
+
6008: "invalidMinRewardCount",
|
|
44
|
+
6009: "invalidMaxRewardCount",
|
|
45
|
+
6010: "unstakeNotReady",
|
|
46
|
+
6011: "insufficientStakeBalance",
|
|
40
47
|
};
|
|
41
48
|
|
|
42
49
|
function anchorErrorCode(err: any): string {
|
|
@@ -85,9 +92,8 @@ async function handleQuestGet(options: GlobalOptions) {
|
|
|
85
92
|
return;
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
const data = {
|
|
95
|
+
const data: Record<string, any> = {
|
|
89
96
|
round: quest.round,
|
|
90
|
-
questionId: quest.questionId,
|
|
91
97
|
question: quest.question,
|
|
92
98
|
difficulty: quest.difficulty,
|
|
93
99
|
rewardPerWinner: `${quest.rewardPerWinner} NARA`,
|
|
@@ -97,6 +103,8 @@ async function handleQuestGet(options: GlobalOptions) {
|
|
|
97
103
|
deadline: new Date(quest.deadline * 1000).toLocaleString(),
|
|
98
104
|
timeRemaining: formatTimeRemaining(quest.timeRemaining),
|
|
99
105
|
expired: quest.expired,
|
|
106
|
+
stakeRequirement: `${quest.stakeRequirement} NARA`,
|
|
107
|
+
minWinnerStake: `${quest.minWinnerStake} NARA`,
|
|
100
108
|
};
|
|
101
109
|
|
|
102
110
|
if (options.json) {
|
|
@@ -111,6 +119,10 @@ async function handleQuestGet(options: GlobalOptions) {
|
|
|
111
119
|
console.log(
|
|
112
120
|
` Reward slots: ${quest.winnerCount}/${quest.rewardCount} (${quest.remainingSlots} remaining)`
|
|
113
121
|
);
|
|
122
|
+
if (quest.stakeRequirement > 0) {
|
|
123
|
+
console.log(` Stake requirement: ${quest.stakeRequirement} NARA`);
|
|
124
|
+
console.log(` Min winner stake: ${quest.minWinnerStake} NARA`);
|
|
125
|
+
}
|
|
114
126
|
console.log(` Deadline: ${new Date(quest.deadline * 1000).toLocaleString()}`);
|
|
115
127
|
if (quest.timeRemaining > 0) {
|
|
116
128
|
console.log(` Time remaining: ${formatTimeRemaining(quest.timeRemaining)}`);
|
|
@@ -124,7 +136,7 @@ async function handleQuestGet(options: GlobalOptions) {
|
|
|
124
136
|
// ─── Command: quest answer ───────────────────────────────────────
|
|
125
137
|
async function handleQuestAnswer(
|
|
126
138
|
answer: string,
|
|
127
|
-
options: GlobalOptions & { relay?: string; agent?: string; model?: string; referral?: string }
|
|
139
|
+
options: GlobalOptions & { relay?: string; agent?: string; model?: string; referral?: string; stake?: string }
|
|
128
140
|
) {
|
|
129
141
|
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
130
142
|
const connection = new Connection(rpcUrl, "confirmed");
|
|
@@ -210,7 +222,8 @@ async function handleQuestAnswer(
|
|
|
210
222
|
if (configAgentId) {
|
|
211
223
|
activityLog = { agentId: configAgentId, activity: "PoMI", model, log: "", referralAgentId: referral };
|
|
212
224
|
}
|
|
213
|
-
const
|
|
225
|
+
const stakeOpt = options.stake === "auto" ? "auto" : options.stake ? parseFloat(options.stake) : undefined;
|
|
226
|
+
const result = await submitAnswer(connection, wallet, proof.solana, agent, model, stakeOpt !== undefined ? { stake: stakeOpt } : undefined, activityLog);
|
|
214
227
|
printSuccess("Answer submitted!");
|
|
215
228
|
console.log(` Transaction: ${result.signature}`);
|
|
216
229
|
await handleReward(connection, result.signature, options);
|
|
@@ -220,6 +233,78 @@ async function handleQuestAnswer(
|
|
|
220
233
|
}
|
|
221
234
|
}
|
|
222
235
|
|
|
236
|
+
// ─── Command: quest stake ────────────────────────────────────────
|
|
237
|
+
async function handleQuestStake(amount: string, options: GlobalOptions) {
|
|
238
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
239
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
240
|
+
const wallet = await loadWallet(options.wallet);
|
|
241
|
+
|
|
242
|
+
const n = parseFloat(amount);
|
|
243
|
+
if (isNaN(n) || n <= 0) {
|
|
244
|
+
printError("Amount must be a positive number");
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!options.json) printInfo(`Staking ${n} NARA...`);
|
|
249
|
+
const signature = await questStake(connection, wallet, n);
|
|
250
|
+
if (!options.json) printSuccess(`Staked ${n} NARA!`);
|
|
251
|
+
|
|
252
|
+
if (options.json) {
|
|
253
|
+
formatOutput({ amount: n, signature }, true);
|
|
254
|
+
} else {
|
|
255
|
+
console.log(` Transaction: ${signature}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ─── Command: quest unstake ─────────────────────────────────────
|
|
260
|
+
async function handleQuestUnstake(amount: string, options: GlobalOptions) {
|
|
261
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
262
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
263
|
+
const wallet = await loadWallet(options.wallet);
|
|
264
|
+
|
|
265
|
+
const n = parseFloat(amount);
|
|
266
|
+
if (isNaN(n) || n <= 0) {
|
|
267
|
+
printError("Amount must be a positive number");
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (!options.json) printInfo(`Unstaking ${n} NARA...`);
|
|
272
|
+
const signature = await questUnstake(connection, wallet, n);
|
|
273
|
+
if (!options.json) printSuccess(`Unstaked ${n} NARA!`);
|
|
274
|
+
|
|
275
|
+
if (options.json) {
|
|
276
|
+
formatOutput({ amount: n, signature }, true);
|
|
277
|
+
} else {
|
|
278
|
+
console.log(` Transaction: ${signature}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ─── Command: quest stake-info ──────────────────────────────────
|
|
283
|
+
async function handleQuestStakeInfo(options: GlobalOptions) {
|
|
284
|
+
const rpcUrl = getRpcUrl(options.rpcUrl);
|
|
285
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
286
|
+
const wallet = await loadWallet(options.wallet);
|
|
287
|
+
|
|
288
|
+
const stakeInfo = await getStakeInfo(connection, wallet.publicKey);
|
|
289
|
+
if (!stakeInfo) {
|
|
290
|
+
if (options.json) {
|
|
291
|
+
formatOutput({ staked: false, amount: 0 }, true);
|
|
292
|
+
} else {
|
|
293
|
+
printInfo("No stake record found");
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (options.json) {
|
|
299
|
+
formatOutput({ staked: true, amount: stakeInfo.amount, stakeRound: stakeInfo.stakeRound }, true);
|
|
300
|
+
} else {
|
|
301
|
+
console.log("");
|
|
302
|
+
console.log(` Staked: ${stakeInfo.amount} NARA`);
|
|
303
|
+
console.log(` Stake round: ${stakeInfo.stakeRound}`);
|
|
304
|
+
console.log("");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
223
308
|
// ─── Parse reward from transaction ───────────────────────────────
|
|
224
309
|
async function handleReward(
|
|
225
310
|
connection: Connection,
|
|
@@ -280,6 +365,12 @@ function handleSubmitError(err: any) {
|
|
|
280
365
|
case "poolNotActive":
|
|
281
366
|
printError("No active quest at the moment");
|
|
282
367
|
break;
|
|
368
|
+
case "unstakeNotReady":
|
|
369
|
+
printError("Cannot unstake until round advances or deadline passes");
|
|
370
|
+
break;
|
|
371
|
+
case "insufficientStakeBalance":
|
|
372
|
+
printError("Unstake amount exceeds staked balance");
|
|
373
|
+
break;
|
|
283
374
|
default:
|
|
284
375
|
printError(`Failed to submit answer: ${err.message ?? String(err)}`);
|
|
285
376
|
if (err.logs) {
|
|
@@ -318,11 +409,55 @@ export function registerQuestCommands(program: Command): void {
|
|
|
318
409
|
.option("--agent <name>", "Agent identifier (default: naracli)")
|
|
319
410
|
.option("--model <name>", "Model identifier")
|
|
320
411
|
.option("--referral <agent-id>", "Referral agent ID")
|
|
412
|
+
.option("--stake [amount]", 'Stake NARA before answering ("auto" to top-up to requirement, or a number)')
|
|
321
413
|
.action(async (answer: string, opts: any, cmd: Command) => {
|
|
322
414
|
try {
|
|
323
415
|
const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
|
|
324
416
|
const relayUrl = opts.relay === true ? DEFAULT_QUEST_RELAY_URL : opts.relay;
|
|
325
|
-
|
|
417
|
+
const stakeVal = opts.stake === true ? "auto" : opts.stake;
|
|
418
|
+
await handleQuestAnswer(answer, { ...globalOpts, relay: relayUrl, agent: opts.agent, model: opts.model, referral: opts.referral, stake: stakeVal });
|
|
419
|
+
} catch (error: any) {
|
|
420
|
+
printError(error.message);
|
|
421
|
+
process.exit(1);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// quest stake
|
|
426
|
+
quest
|
|
427
|
+
.command("stake <amount>")
|
|
428
|
+
.description("Stake NARA to participate in quests")
|
|
429
|
+
.action(async (amount: string, _opts: any, cmd: Command) => {
|
|
430
|
+
try {
|
|
431
|
+
const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
|
|
432
|
+
await handleQuestStake(amount, globalOpts);
|
|
433
|
+
} catch (error: any) {
|
|
434
|
+
printError(error.message);
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// quest unstake
|
|
440
|
+
quest
|
|
441
|
+
.command("unstake <amount>")
|
|
442
|
+
.description("Unstake NARA (available after round advances or deadline passes)")
|
|
443
|
+
.action(async (amount: string, _opts: any, cmd: Command) => {
|
|
444
|
+
try {
|
|
445
|
+
const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
|
|
446
|
+
await handleQuestUnstake(amount, globalOpts);
|
|
447
|
+
} catch (error: any) {
|
|
448
|
+
printError(error.message);
|
|
449
|
+
process.exit(1);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// quest stake-info
|
|
454
|
+
quest
|
|
455
|
+
.command("stake-info")
|
|
456
|
+
.description("Get your current quest stake info")
|
|
457
|
+
.action(async (_opts: any, cmd: Command) => {
|
|
458
|
+
try {
|
|
459
|
+
const globalOpts = cmd.optsWithGlobals() as GlobalOptions;
|
|
460
|
+
await handleQuestStakeInfo(globalOpts);
|
|
326
461
|
} catch (error: any) {
|
|
327
462
|
printError(error.message);
|
|
328
463
|
process.exit(1);
|
package/src/tests/helpers.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { join, dirname } from "node:path";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
|
+
import type { Connection } from "@solana/web3.js";
|
|
10
11
|
|
|
11
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
13
|
const CLI = join(__dirname, "../../bin/nara-cli.ts");
|
|
@@ -57,3 +58,22 @@ export const hasWallet = existsSync(join(homedir(), ".config", "nara", "id.json"
|
|
|
57
58
|
export function uniqueName(prefix: string): string {
|
|
58
59
|
return `${prefix}-${Date.now().toString(36)}`;
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Poll for transaction confirmation (avoids WebSocket-based confirmTransaction
|
|
64
|
+
* which fails with TLS errors on some networks).
|
|
65
|
+
*/
|
|
66
|
+
export async function pollConfirmation(
|
|
67
|
+
connection: Connection,
|
|
68
|
+
signature: string,
|
|
69
|
+
maxRetries = 30,
|
|
70
|
+
intervalMs = 1000
|
|
71
|
+
): Promise<void> {
|
|
72
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
73
|
+
const { value } = await connection.getSignatureStatuses([signature]);
|
|
74
|
+
const status = value[0]?.confirmationStatus;
|
|
75
|
+
if (status === "confirmed" || status === "finalized") return;
|
|
76
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
77
|
+
}
|
|
78
|
+
throw new Error(`Transaction ${signature} not confirmed after ${maxRetries}s`);
|
|
79
|
+
}
|
|
@@ -22,7 +22,7 @@ import { fileURLToPath } from "node:url";
|
|
|
22
22
|
import { Connection, Keypair, LAMPORTS_PER_SOL, SystemProgram, Transaction } from "@solana/web3.js";
|
|
23
23
|
import bs58 from "bs58";
|
|
24
24
|
import { DEFAULT_AGENT_REGISTRY_PROGRAM_ID, getQuestInfo, getAgentRecord } from "nara-sdk";
|
|
25
|
-
import { runCli, hasWallet } from "./helpers.js";
|
|
25
|
+
import { runCli, hasWallet, pollConfirmation } from "./helpers.js";
|
|
26
26
|
|
|
27
27
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
28
|
|
|
@@ -80,7 +80,7 @@ describe("quest referral (on-chain)", { skip: !hasWallet ? "no PRIVATE_KEY" : un
|
|
|
80
80
|
transferTx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
81
81
|
transferTx.sign(mainWallet);
|
|
82
82
|
const sig = await connection.sendRawTransaction(transferTx.serialize());
|
|
83
|
-
await connection
|
|
83
|
+
await pollConfirmation(connection, sig);
|
|
84
84
|
console.log(` Transfer tx: ${sig}`);
|
|
85
85
|
});
|
|
86
86
|
|
|
@@ -106,9 +106,11 @@ describe("quest referral (on-chain)", { skip: !hasWallet ? "no PRIVATE_KEY" : un
|
|
|
106
106
|
console.log(" Referral agent registered");
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
it("registers main agent", async () => {
|
|
110
|
-
console.log(` Registering main agent "${mainAgentId}"...`);
|
|
111
|
-
const { stdout, stderr, exitCode } = await runCli([
|
|
109
|
+
it("registers main agent with referral", async () => {
|
|
110
|
+
console.log(` Registering main agent "${mainAgentId}" with referral "${referralAgentId}"...`);
|
|
111
|
+
const { stdout, stderr, exitCode } = await runCli([
|
|
112
|
+
"agent", "register", mainAgentId, "--referral", referralAgentId,
|
|
113
|
+
]);
|
|
112
114
|
const output = stdout + stderr;
|
|
113
115
|
if (output.includes("already") || output.includes("in use")) {
|
|
114
116
|
console.log(" Agent already exists, continuing");
|
|
@@ -116,7 +118,7 @@ describe("quest referral (on-chain)", { skip: !hasWallet ? "no PRIVATE_KEY" : un
|
|
|
116
118
|
}
|
|
117
119
|
assert.equal(exitCode, 0, `Failed: ${stderr}`);
|
|
118
120
|
assert.ok(output.includes("registered") || output.includes("Transaction"), "should confirm registration");
|
|
119
|
-
console.log(" Main agent registered");
|
|
121
|
+
console.log(" Main agent registered with referral");
|
|
120
122
|
});
|
|
121
123
|
|
|
122
124
|
it("answers quest with --referral", async () => {
|
|
@@ -162,7 +164,7 @@ describe("quest referral (on-chain)", { skip: !hasWallet ? "no PRIVATE_KEY" : un
|
|
|
162
164
|
// Extract transaction signature
|
|
163
165
|
const txMatch = output.match(/Transaction:\s+(\S+)/);
|
|
164
166
|
assert.ok(txMatch, "should show transaction signature");
|
|
165
|
-
const txSig = txMatch![1]
|
|
167
|
+
const txSig = txMatch![1]!;
|
|
166
168
|
console.log(` Transaction: ${txSig}`);
|
|
167
169
|
|
|
168
170
|
// Verify transaction succeeded on-chain
|
|
@@ -204,25 +206,16 @@ describe("quest referral (on-chain)", { skip: !hasWallet ? "no PRIVATE_KEY" : un
|
|
|
204
206
|
console.log(" Answer submitted with referral successfully");
|
|
205
207
|
});
|
|
206
208
|
|
|
207
|
-
it("verifies on-chain agent
|
|
209
|
+
it("verifies on-chain agent records", async () => {
|
|
208
210
|
try {
|
|
209
211
|
const mainRecord = await getAgentRecord(connection, mainAgentId);
|
|
210
|
-
console.log(` Main agent
|
|
212
|
+
console.log(` Main agent: ${mainRecord.agentId}, referral: ${mainRecord.referralId ?? "(none)"}`);
|
|
211
213
|
|
|
212
214
|
const referralRecord = await getAgentRecord(connection, referralAgentId);
|
|
213
|
-
console.log(` Referral agent
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
} else {
|
|
218
|
-
console.log(" WARN: Main agent has 0 points (quest may not have been answered in this run)");
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (referralRecord.points > 0) {
|
|
222
|
-
console.log(" OK: Referral agent earned referral points");
|
|
223
|
-
} else {
|
|
224
|
-
console.log(" WARN: Referral agent has 0 points");
|
|
225
|
-
}
|
|
215
|
+
console.log(` Referral agent: ${referralRecord.agentId}`);
|
|
216
|
+
|
|
217
|
+
// Points are now minted as SPL tokens (Token-2022), not stored on AgentRecord
|
|
218
|
+
console.log(" OK: Both agent records exist on-chain");
|
|
226
219
|
} catch (err: any) {
|
|
227
220
|
console.log(` (skipped: ${err.message})`);
|
|
228
221
|
}
|
package/src/tests/quest.test.ts
CHANGED
|
@@ -94,7 +94,7 @@ describe("quest proof generation", () => {
|
|
|
94
94
|
|
|
95
95
|
// Generate proof with a random pubkey (we're just testing proof generation)
|
|
96
96
|
const testKeypair = Keypair.generate();
|
|
97
|
-
const proof = await generateProof(match.answer, quest.answerHash, testKeypair.publicKey);
|
|
97
|
+
const proof = await generateProof(match.answer, quest.answerHash, testKeypair.publicKey, quest.round);
|
|
98
98
|
|
|
99
99
|
assert.ok(proof.solana.proofA.length > 0, "proofA should not be empty");
|
|
100
100
|
assert.ok(proof.solana.proofB.length > 0, "proofB should not be empty");
|