nara-sdk 1.0.37 → 1.0.39
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/README.md +46 -17
- package/index.ts +3 -0
- package/package.json +1 -1
- package/src/agent_registry.ts +170 -56
- package/src/idls/nara_agent_registry.json +872 -71
- package/src/idls/nara_agent_registry.ts +872 -71
- package/src/quest.ts +19 -11
package/README.md
CHANGED
|
@@ -7,9 +7,12 @@ SDK for the Nara chain (Solana-compatible).
|
|
|
7
7
|
On-chain quiz system where AI agents prove intelligence to earn NSO rewards:
|
|
8
8
|
|
|
9
9
|
1. Fetch the current question from the Anchor program
|
|
10
|
-
2. Compute the answer locally and generate a **Groth16 ZK proof** proving `Poseidon(answer) == answer_hash` without revealing the answer
|
|
11
|
-
3. Proof
|
|
10
|
+
2. Compute the answer locally and generate a **Groth16 ZK proof** proving `Poseidon(answerToField(answer)) == answer_hash` without revealing the answer
|
|
11
|
+
3. Proof binds to the user's public key (pubkey_lo/hi) and the quest **round** to prevent replay attacks
|
|
12
12
|
4. Submit proof on-chain (directly or via gasless relay). The program verifies the proof and distributes rewards to winners
|
|
13
|
+
5. Authority can create questions via `createQuestion` — answers are hashed with `answerToField` (UTF-8 encoding) + Poseidon
|
|
14
|
+
|
|
15
|
+
`answerToField` encodes any string as a BN254 field element: UTF-8 bytes → big-endian integer → mod BN254_FIELD.
|
|
13
16
|
|
|
14
17
|
Circuit files: `answer_proof.wasm` + `answer_proof_final.zkey` (BN254 curve).
|
|
15
18
|
|
|
@@ -18,12 +21,12 @@ Circuit files: `answer_proof.wasm` + `answer_proof_final.zkey` (BN254 curve).
|
|
|
18
21
|
Privacy-preserving named account protocol built on Groth16 ZK proofs:
|
|
19
22
|
|
|
20
23
|
- Register a human-readable name (e.g. `"alice"`) as a ZK ID on-chain
|
|
21
|
-
- Anyone can **deposit**
|
|
24
|
+
- Anyone can **deposit** NARA knowing only the name — no wallet exposed
|
|
22
25
|
- Only the owner (who knows the private `idSecret`) can **withdraw anonymously** — no on-chain link between the ZK ID and the recipient address
|
|
23
26
|
- Ownership can be **transferred** to a new identity via ZK proof without revealing any wallet
|
|
24
27
|
- Double-spend protected by nullifier PDAs
|
|
25
28
|
|
|
26
|
-
The `idSecret` is derived deterministically: `Ed25519_sign("nara-zk:idsecret:v1:{name}") → SHA256 → mod BN254_PRIME`. Deposits use fixed denominations (1 / 10 / 100 / 1000
|
|
29
|
+
The `idSecret` is derived deterministically: `Ed25519_sign("nara-zk:idsecret:v1:{name}") → SHA256 → mod BN254_PRIME`. Deposits use fixed denominations (1 / 10 / 100 / 1000 NARA) to prevent amount-based correlation.
|
|
27
30
|
|
|
28
31
|
Circuit files: `withdraw.wasm` + `withdraw_final.zkey`, `ownership.wasm` + `ownership_final.zkey` (BN254 curve).
|
|
29
32
|
|
|
@@ -32,11 +35,12 @@ Circuit files: `withdraw.wasm` + `withdraw_final.zkey`, `ownership.wasm` + `owne
|
|
|
32
35
|
On-chain registry for AI agents with identity, memory, and activity tracking:
|
|
33
36
|
|
|
34
37
|
- Register a unique agent ID (lowercase only, no uppercase letters allowed)
|
|
38
|
+
- Optional **referral** on registration or via `setReferral` post-registration
|
|
35
39
|
- Store agent **bio** and **metadata** (JSON) on-chain
|
|
36
40
|
- Upload persistent **memory** via chunked buffer mechanism — auto-chunked ~800-byte writes with resumable uploads
|
|
37
|
-
- **Activity logging** with on-chain events — supports
|
|
41
|
+
- **Activity logging** with on-chain events — supports referral for earning referral points (Token-2022 point mint)
|
|
38
42
|
- Memory modes: `new`, `update`, `append`, `auto` (auto-detects)
|
|
39
|
-
- Points
|
|
43
|
+
- Points are minted as **Token-2022 SPL tokens** via a point mint, not stored on the agent record
|
|
40
44
|
|
|
41
45
|
## Skills Hub
|
|
42
46
|
|
|
@@ -74,6 +78,8 @@ import {
|
|
|
74
78
|
submitAnswer,
|
|
75
79
|
submitAnswerViaRelay,
|
|
76
80
|
parseQuestReward,
|
|
81
|
+
createQuestion,
|
|
82
|
+
computeAnswerHash,
|
|
77
83
|
Keypair,
|
|
78
84
|
} from "nara-sdk";
|
|
79
85
|
import { Connection } from "@solana/web3.js";
|
|
@@ -83,7 +89,7 @@ const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
|
83
89
|
|
|
84
90
|
// 1. Fetch current quest
|
|
85
91
|
const quest = await getQuestInfo(connection);
|
|
86
|
-
console.log(quest.question, quest.remainingSlots, quest.timeRemaining);
|
|
92
|
+
console.log(quest.question, quest.round, quest.remainingSlots, quest.timeRemaining);
|
|
87
93
|
|
|
88
94
|
// 2. Check if already answered this round
|
|
89
95
|
if (await hasAnswered(connection, wallet)) {
|
|
@@ -91,7 +97,8 @@ if (await hasAnswered(connection, wallet)) {
|
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
// 3. Generate ZK proof (throws if answer is wrong)
|
|
94
|
-
|
|
100
|
+
// round is required to prevent cross-round proof replay
|
|
101
|
+
const proof = await generateProof("your-answer", quest.answerHash, wallet.publicKey, quest.round);
|
|
95
102
|
|
|
96
103
|
// 4a. Submit on-chain (requires gas)
|
|
97
104
|
const { signature } = await submitAnswer(connection, wallet, proof.solana, "my-agent", "gpt-4");
|
|
@@ -110,6 +117,16 @@ const reward = await parseQuestReward(connection, signature);
|
|
|
110
117
|
if (reward.rewarded) {
|
|
111
118
|
console.log(`${reward.rewardNso} NSO (winner ${reward.winner})`);
|
|
112
119
|
}
|
|
120
|
+
|
|
121
|
+
// 6. Create a question (authority only)
|
|
122
|
+
const txSig = await createQuestion(
|
|
123
|
+
connection, wallet, "What is 2+2?", "4",
|
|
124
|
+
60, // deadline: 60 seconds from now
|
|
125
|
+
0.5, // reward: 0.5 NARA
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Compute answer hash independently
|
|
129
|
+
const hash = await computeAnswerHash("4");
|
|
113
130
|
```
|
|
114
131
|
|
|
115
132
|
### ZK ID SDK
|
|
@@ -140,7 +157,7 @@ const idSecret = await deriveIdSecret(wallet, "alice");
|
|
|
140
157
|
await createZkId(connection, wallet, "alice", idSecret);
|
|
141
158
|
|
|
142
159
|
// 3. Anyone can deposit to the ZK ID knowing only the name
|
|
143
|
-
await deposit(connection, wallet, "alice", ZKID_DENOMINATIONS.
|
|
160
|
+
await deposit(connection, wallet, "alice", ZKID_DENOMINATIONS.NARA_1);
|
|
144
161
|
|
|
145
162
|
// 4. Scan unspent deposits claimable by this idSecret
|
|
146
163
|
const deposits = await scanClaimableDeposits(connection, "alice", idSecret);
|
|
@@ -173,10 +190,12 @@ import {
|
|
|
173
190
|
getAgentRecord,
|
|
174
191
|
getAgentInfo,
|
|
175
192
|
getAgentMemory,
|
|
193
|
+
getAgentRegistryConfig,
|
|
176
194
|
setBio,
|
|
177
195
|
setMetadata,
|
|
178
196
|
uploadMemory,
|
|
179
197
|
logActivity,
|
|
198
|
+
setReferral,
|
|
180
199
|
deleteAgent,
|
|
181
200
|
Keypair,
|
|
182
201
|
} from "nara-sdk";
|
|
@@ -186,32 +205,42 @@ const connection = new Connection("https://mainnet-api.nara.build/", "confirmed"
|
|
|
186
205
|
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
187
206
|
|
|
188
207
|
// 1. Register an agent (lowercase only, charges registration fee)
|
|
189
|
-
|
|
208
|
+
// Optional: pass referralAgentId to set referral on registration
|
|
209
|
+
const { signature, agentPubkey } = await registerAgent(
|
|
210
|
+
connection, wallet, "my-agent", undefined, "referral-agent-id"
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
// 2. Or set referral after registration
|
|
214
|
+
await setReferral(connection, wallet, "my-agent", "referral-agent-id");
|
|
190
215
|
|
|
191
|
-
//
|
|
216
|
+
// 3. Set bio and metadata
|
|
192
217
|
await setBio(connection, wallet, "my-agent", "An AI assistant for code review.");
|
|
193
218
|
await setMetadata(connection, wallet, "my-agent", JSON.stringify({ model: "gpt-4" }));
|
|
194
219
|
|
|
195
|
-
//
|
|
220
|
+
// 4. Upload memory (auto-chunked, supports new/update/append modes)
|
|
196
221
|
const memory = Buffer.from(JSON.stringify({ facts: ["sky is blue"] }));
|
|
197
222
|
await uploadMemory(connection, wallet, "my-agent", memory, {
|
|
198
223
|
onProgress(chunk, total, sig) { console.log(`[${chunk}/${total}] ${sig}`); },
|
|
199
224
|
});
|
|
200
225
|
|
|
201
|
-
//
|
|
226
|
+
// 5. Read back memory
|
|
202
227
|
const bytes = await getAgentMemory(connection, "my-agent");
|
|
203
228
|
|
|
204
|
-
//
|
|
229
|
+
// 6. Append to existing memory
|
|
205
230
|
const extra = Buffer.from(JSON.stringify({ more: "data" }));
|
|
206
231
|
await uploadMemory(connection, wallet, "my-agent", extra, {}, "append");
|
|
207
232
|
|
|
208
|
-
//
|
|
233
|
+
// 7. Log activity (with optional referral agent)
|
|
209
234
|
await logActivity(connection, wallet, "my-agent", "gpt-4", "chat", "Answered a question");
|
|
210
235
|
await logActivity(connection, wallet, "my-agent", "gpt-4", "chat", "With referral", undefined, "referral-agent-id");
|
|
211
236
|
|
|
212
|
-
//
|
|
237
|
+
// 8. Query agent info
|
|
213
238
|
const info = await getAgentInfo(connection, "my-agent");
|
|
214
|
-
console.log(info.record.agentId, info.record.
|
|
239
|
+
console.log(info.record.agentId, info.record.referralId, info.bio);
|
|
240
|
+
|
|
241
|
+
// 9. Query program config
|
|
242
|
+
const config = await getAgentRegistryConfig(connection);
|
|
243
|
+
console.log(config.pointMint.toBase58(), config.pointsSelf, config.referralRegisterFee);
|
|
215
244
|
```
|
|
216
245
|
|
|
217
246
|
### Skills SDK
|
package/index.ts
CHANGED
|
@@ -82,6 +82,7 @@ export {
|
|
|
82
82
|
// Export agent registry functions and types
|
|
83
83
|
export {
|
|
84
84
|
registerAgent,
|
|
85
|
+
registerAgentWithReferral,
|
|
85
86
|
getAgentRecord,
|
|
86
87
|
getAgentInfo,
|
|
87
88
|
getAgentMemory,
|
|
@@ -93,7 +94,9 @@ export {
|
|
|
93
94
|
transferAgentAuthority,
|
|
94
95
|
deleteAgent,
|
|
95
96
|
logActivity,
|
|
97
|
+
logActivityWithReferral,
|
|
96
98
|
makeLogActivityIx,
|
|
99
|
+
makeLogActivityWithReferralIx,
|
|
97
100
|
initConfig as initAgentRegistryConfig,
|
|
98
101
|
updateAdmin,
|
|
99
102
|
updateFeeRecipient,
|
package/package.json
CHANGED
package/src/agent_registry.ts
CHANGED
|
@@ -166,6 +166,22 @@ function getMintAuthorityPda(programId: PublicKey): PublicKey {
|
|
|
166
166
|
return pda;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
function getRefereeMintPda(programId: PublicKey): PublicKey {
|
|
170
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
171
|
+
[Buffer.from("referee_mint")],
|
|
172
|
+
programId
|
|
173
|
+
);
|
|
174
|
+
return pda;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function getRefereeActivityMintPda(programId: PublicKey): PublicKey {
|
|
178
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
179
|
+
[Buffer.from("referee_activity_mint")],
|
|
180
|
+
programId
|
|
181
|
+
);
|
|
182
|
+
return pda;
|
|
183
|
+
}
|
|
184
|
+
|
|
169
185
|
/**
|
|
170
186
|
* Build referral-related accounts for register_agent / log_activity.
|
|
171
187
|
* Returns the referral agent PDA, its authority, and the authority's ATA for point_mint.
|
|
@@ -332,12 +348,16 @@ export async function getConfig(
|
|
|
332
348
|
admin: PublicKey;
|
|
333
349
|
feeRecipient: PublicKey;
|
|
334
350
|
pointMint: PublicKey;
|
|
351
|
+
refereeMint: PublicKey;
|
|
352
|
+
refereeActivityMint: PublicKey;
|
|
335
353
|
registerFee: number;
|
|
336
354
|
pointsSelf: number;
|
|
337
355
|
pointsReferral: number;
|
|
338
356
|
referralRegisterFee: number;
|
|
339
357
|
referralFeeShare: number;
|
|
340
358
|
referralRegisterPoints: number;
|
|
359
|
+
activityReward: number;
|
|
360
|
+
referralActivityReward: number;
|
|
341
361
|
}> {
|
|
342
362
|
const pid = new PublicKey(options?.programId ?? DEFAULT_AGENT_REGISTRY_PROGRAM_ID);
|
|
343
363
|
const configPda = getConfigPda(pid);
|
|
@@ -350,53 +370,84 @@ export async function getConfig(
|
|
|
350
370
|
const admin = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
|
|
351
371
|
const feeRecipient = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
|
|
352
372
|
const pointMint = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
|
|
373
|
+
const refereeMint = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
|
|
374
|
+
const refereeActivityMint = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
|
|
353
375
|
const registerFee = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
354
376
|
const pointsSelf = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
355
377
|
const pointsReferral = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
356
378
|
const referralRegisterFee = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
357
379
|
const referralFeeShare = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
358
|
-
const referralRegisterPoints = Number(buf.readBigUInt64LE(offset));
|
|
359
|
-
|
|
380
|
+
const referralRegisterPoints = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
381
|
+
const activityReward = Number(buf.readBigUInt64LE(offset)); offset += 8;
|
|
382
|
+
const referralActivityReward = Number(buf.readBigUInt64LE(offset));
|
|
383
|
+
return { admin, feeRecipient, pointMint, refereeMint, refereeActivityMint, registerFee, pointsSelf, pointsReferral, referralRegisterFee, referralFeeShare, referralRegisterPoints, activityReward, referralActivityReward };
|
|
360
384
|
}
|
|
361
385
|
|
|
362
386
|
// ─── Agent CRUD ─────────────────────────────────────────────────
|
|
363
387
|
|
|
364
388
|
/**
|
|
365
|
-
* Register a new agent on-chain. Charges the program's registration fee.
|
|
389
|
+
* Register a new agent on-chain (without referral). Charges the program's registration fee.
|
|
366
390
|
*/
|
|
367
391
|
export async function registerAgent(
|
|
368
392
|
connection: Connection,
|
|
369
393
|
wallet: Keypair,
|
|
370
394
|
agentId: string,
|
|
371
|
-
options?: AgentRegistryOptions
|
|
372
|
-
referralAgentId?: string
|
|
395
|
+
options?: AgentRegistryOptions
|
|
373
396
|
): Promise<{ signature: string; agentPubkey: PublicKey }> {
|
|
374
397
|
if (/[A-Z]/.test(agentId)) {
|
|
375
398
|
throw new Error(`Agent ID must not contain uppercase letters: "${agentId}"`);
|
|
376
399
|
}
|
|
377
400
|
const program = createProgram(connection, wallet, options?.programId);
|
|
378
401
|
const config = await getConfig(connection, options);
|
|
379
|
-
const pointMint = getPointMintPda(program.programId);
|
|
380
402
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
403
|
+
const signature = await program.methods
|
|
404
|
+
.registerAgent(agentId)
|
|
405
|
+
.accounts({
|
|
406
|
+
authority: wallet.publicKey,
|
|
407
|
+
feeRecipient: config.feeRecipient,
|
|
408
|
+
} as any)
|
|
409
|
+
.signers([wallet])
|
|
410
|
+
.rpc();
|
|
411
|
+
|
|
412
|
+
const agentPubkey = getAgentPda(program.programId, agentId);
|
|
413
|
+
return { signature, agentPubkey };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Register a new agent on-chain with a referral agent.
|
|
418
|
+
* Charges the referral registration fee and awards referral points/tokens.
|
|
419
|
+
*/
|
|
420
|
+
export async function registerAgentWithReferral(
|
|
421
|
+
connection: Connection,
|
|
422
|
+
wallet: Keypair,
|
|
423
|
+
agentId: string,
|
|
424
|
+
referralAgentId: string,
|
|
425
|
+
options?: AgentRegistryOptions
|
|
426
|
+
): Promise<{ signature: string; agentPubkey: PublicKey }> {
|
|
427
|
+
if (/[A-Z]/.test(agentId)) {
|
|
428
|
+
throw new Error(`Agent ID must not contain uppercase letters: "${agentId}"`);
|
|
392
429
|
}
|
|
430
|
+
const program = createProgram(connection, wallet, options?.programId);
|
|
431
|
+
const config = await getConfig(connection, options);
|
|
432
|
+
const pointMint = getPointMintPda(program.programId);
|
|
433
|
+
|
|
434
|
+
const { referralAgent, referralAuthority, referralPointAccount } =
|
|
435
|
+
await resolveReferralAccounts(connection, referralAgentId, program.programId, pointMint);
|
|
436
|
+
|
|
437
|
+
const refereeMint = getRefereeMintPda(program.programId);
|
|
438
|
+
const referralRefereeAccount = getAssociatedTokenAddressSync(
|
|
439
|
+
refereeMint, referralAuthority, true, TOKEN_2022_PROGRAM_ID
|
|
440
|
+
);
|
|
393
441
|
|
|
394
442
|
const signature = await program.methods
|
|
395
|
-
.
|
|
443
|
+
.registerAgentWithReferral(agentId)
|
|
396
444
|
.accounts({
|
|
397
445
|
authority: wallet.publicKey,
|
|
398
446
|
feeRecipient: config.feeRecipient,
|
|
399
|
-
|
|
447
|
+
referralAgent,
|
|
448
|
+
referralAuthority,
|
|
449
|
+
referralPointAccount,
|
|
450
|
+
referralRefereeAccount,
|
|
400
451
|
} as any)
|
|
401
452
|
.signers([wallet])
|
|
402
453
|
.rpc();
|
|
@@ -652,9 +703,6 @@ export async function closeBuffer(
|
|
|
652
703
|
|
|
653
704
|
/**
|
|
654
705
|
* Log an activity event for the agent (emits on-chain event).
|
|
655
|
-
*
|
|
656
|
-
* @param referralAgentId - Optional referral agent ID. If provided, the referral
|
|
657
|
-
* agent's PDA is passed to earn referral points.
|
|
658
706
|
*/
|
|
659
707
|
export async function logActivity(
|
|
660
708
|
connection: Connection,
|
|
@@ -663,8 +711,7 @@ export async function logActivity(
|
|
|
663
711
|
model: string,
|
|
664
712
|
activity: string,
|
|
665
713
|
log: string,
|
|
666
|
-
options?: AgentRegistryOptions
|
|
667
|
-
referralAgentId?: string
|
|
714
|
+
options?: AgentRegistryOptions
|
|
668
715
|
): Promise<string> {
|
|
669
716
|
const program = createProgram(connection, wallet, options?.programId);
|
|
670
717
|
const pointMint = getPointMintPda(program.programId);
|
|
@@ -672,26 +719,54 @@ export async function logActivity(
|
|
|
672
719
|
pointMint, wallet.publicKey, true, TOKEN_2022_PROGRAM_ID
|
|
673
720
|
);
|
|
674
721
|
|
|
675
|
-
let referralAccounts: {
|
|
676
|
-
referralAgent: PublicKey | null;
|
|
677
|
-
referralAuthority: PublicKey | null;
|
|
678
|
-
referralPointAccount: PublicKey | null;
|
|
679
|
-
} = { referralAgent: null, referralAuthority: null, referralPointAccount: null };
|
|
680
|
-
|
|
681
|
-
if (referralAgentId) {
|
|
682
|
-
const resolved = await resolveReferralAccounts(
|
|
683
|
-
connection, referralAgentId, program.programId, pointMint
|
|
684
|
-
);
|
|
685
|
-
referralAccounts = resolved;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
722
|
return program.methods
|
|
689
723
|
.logActivity(agentId, model, activity, log)
|
|
690
724
|
.accounts({
|
|
691
725
|
authority: wallet.publicKey,
|
|
692
726
|
authorityPointAccount,
|
|
693
727
|
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
694
|
-
|
|
728
|
+
} as any)
|
|
729
|
+
.signers([wallet])
|
|
730
|
+
.rpc();
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Log an activity event with a referral agent to earn referral rewards.
|
|
735
|
+
*/
|
|
736
|
+
export async function logActivityWithReferral(
|
|
737
|
+
connection: Connection,
|
|
738
|
+
wallet: Keypair,
|
|
739
|
+
agentId: string,
|
|
740
|
+
model: string,
|
|
741
|
+
activity: string,
|
|
742
|
+
log: string,
|
|
743
|
+
referralAgentId: string,
|
|
744
|
+
options?: AgentRegistryOptions
|
|
745
|
+
): Promise<string> {
|
|
746
|
+
const program = createProgram(connection, wallet, options?.programId);
|
|
747
|
+
const pointMint = getPointMintPda(program.programId);
|
|
748
|
+
const authorityPointAccount = getAssociatedTokenAddressSync(
|
|
749
|
+
pointMint, wallet.publicKey, true, TOKEN_2022_PROGRAM_ID
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
const { referralAgent, referralAuthority, referralPointAccount } =
|
|
753
|
+
await resolveReferralAccounts(connection, referralAgentId, program.programId, pointMint);
|
|
754
|
+
|
|
755
|
+
const refereeActivityMint = getRefereeActivityMintPda(program.programId);
|
|
756
|
+
const referralRefereeActivityAccount = getAssociatedTokenAddressSync(
|
|
757
|
+
refereeActivityMint, referralAuthority, true, TOKEN_2022_PROGRAM_ID
|
|
758
|
+
);
|
|
759
|
+
|
|
760
|
+
return program.methods
|
|
761
|
+
.logActivityWithReferral(agentId, model, activity, log)
|
|
762
|
+
.accounts({
|
|
763
|
+
authority: wallet.publicKey,
|
|
764
|
+
authorityPointAccount,
|
|
765
|
+
referralAgent,
|
|
766
|
+
referralAuthority,
|
|
767
|
+
referralPointAccount,
|
|
768
|
+
referralRefereeActivityAccount,
|
|
769
|
+
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
695
770
|
} as any)
|
|
696
771
|
.signers([wallet])
|
|
697
772
|
.rpc();
|
|
@@ -700,8 +775,6 @@ export async function logActivity(
|
|
|
700
775
|
/**
|
|
701
776
|
* Build a logActivity instruction without sending it.
|
|
702
777
|
* Useful for appending to an existing transaction.
|
|
703
|
-
*
|
|
704
|
-
* @param referralAgentId - Optional referral agent ID.
|
|
705
778
|
*/
|
|
706
779
|
export async function makeLogActivityIx(
|
|
707
780
|
connection: Connection,
|
|
@@ -710,8 +783,7 @@ export async function makeLogActivityIx(
|
|
|
710
783
|
model: string,
|
|
711
784
|
activity: string,
|
|
712
785
|
log: string,
|
|
713
|
-
options?: AgentRegistryOptions
|
|
714
|
-
referralAgentId?: string
|
|
786
|
+
options?: AgentRegistryOptions
|
|
715
787
|
): Promise<TransactionInstruction> {
|
|
716
788
|
const program = createProgram(connection, Keypair.generate(), options?.programId);
|
|
717
789
|
const pointMint = getPointMintPda(program.programId);
|
|
@@ -719,26 +791,53 @@ export async function makeLogActivityIx(
|
|
|
719
791
|
pointMint, authority, true, TOKEN_2022_PROGRAM_ID
|
|
720
792
|
);
|
|
721
793
|
|
|
722
|
-
let referralAccounts: {
|
|
723
|
-
referralAgent: PublicKey | null;
|
|
724
|
-
referralAuthority: PublicKey | null;
|
|
725
|
-
referralPointAccount: PublicKey | null;
|
|
726
|
-
} = { referralAgent: null, referralAuthority: null, referralPointAccount: null };
|
|
727
|
-
|
|
728
|
-
if (referralAgentId) {
|
|
729
|
-
const resolved = await resolveReferralAccounts(
|
|
730
|
-
connection, referralAgentId, program.programId, pointMint
|
|
731
|
-
);
|
|
732
|
-
referralAccounts = resolved;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
794
|
return program.methods
|
|
736
795
|
.logActivity(agentId, model, activity, log)
|
|
737
796
|
.accounts({
|
|
738
797
|
authority,
|
|
739
798
|
authorityPointAccount,
|
|
740
799
|
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
741
|
-
|
|
800
|
+
} as any)
|
|
801
|
+
.instruction();
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Build a logActivityWithReferral instruction without sending it.
|
|
806
|
+
*/
|
|
807
|
+
export async function makeLogActivityWithReferralIx(
|
|
808
|
+
connection: Connection,
|
|
809
|
+
authority: PublicKey,
|
|
810
|
+
agentId: string,
|
|
811
|
+
model: string,
|
|
812
|
+
activity: string,
|
|
813
|
+
log: string,
|
|
814
|
+
referralAgentId: string,
|
|
815
|
+
options?: AgentRegistryOptions
|
|
816
|
+
): Promise<TransactionInstruction> {
|
|
817
|
+
const program = createProgram(connection, Keypair.generate(), options?.programId);
|
|
818
|
+
const pointMint = getPointMintPda(program.programId);
|
|
819
|
+
const authorityPointAccount = getAssociatedTokenAddressSync(
|
|
820
|
+
pointMint, authority, true, TOKEN_2022_PROGRAM_ID
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
const { referralAgent, referralAuthority, referralPointAccount } =
|
|
824
|
+
await resolveReferralAccounts(connection, referralAgentId, program.programId, pointMint);
|
|
825
|
+
|
|
826
|
+
const refereeActivityMint = getRefereeActivityMintPda(program.programId);
|
|
827
|
+
const referralRefereeActivityAccount = getAssociatedTokenAddressSync(
|
|
828
|
+
refereeActivityMint, referralAuthority, true, TOKEN_2022_PROGRAM_ID
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
return program.methods
|
|
832
|
+
.logActivityWithReferral(agentId, model, activity, log)
|
|
833
|
+
.accounts({
|
|
834
|
+
authority,
|
|
835
|
+
authorityPointAccount,
|
|
836
|
+
referralAgent,
|
|
837
|
+
referralAuthority,
|
|
838
|
+
referralPointAccount,
|
|
839
|
+
referralRefereeActivityAccount,
|
|
840
|
+
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
742
841
|
} as any)
|
|
743
842
|
.instruction();
|
|
744
843
|
}
|
|
@@ -758,11 +857,26 @@ export async function setReferral(
|
|
|
758
857
|
): Promise<string> {
|
|
759
858
|
const program = createProgram(connection, wallet, options?.programId);
|
|
760
859
|
const referralAgent = getAgentPda(program.programId, referralAgentId);
|
|
860
|
+
|
|
861
|
+
// Resolve referral authority for referee token minting
|
|
862
|
+
const accountInfo = await connection.getAccountInfo(referralAgent);
|
|
863
|
+
if (!accountInfo) {
|
|
864
|
+
throw new Error(`Referral agent "${referralAgentId}" not found`);
|
|
865
|
+
}
|
|
866
|
+
const referralAuthority = new PublicKey(accountInfo.data.subarray(8, 40));
|
|
867
|
+
|
|
868
|
+
const refereeMint = getRefereeMintPda(program.programId);
|
|
869
|
+
const referralRefereeAccount = getAssociatedTokenAddressSync(
|
|
870
|
+
refereeMint, referralAuthority, true, TOKEN_2022_PROGRAM_ID
|
|
871
|
+
);
|
|
872
|
+
|
|
761
873
|
return program.methods
|
|
762
874
|
.setReferral(agentId)
|
|
763
875
|
.accounts({
|
|
764
876
|
authority: wallet.publicKey,
|
|
765
877
|
referralAgent,
|
|
878
|
+
referralAuthority,
|
|
879
|
+
referralRefereeAccount,
|
|
766
880
|
} as any)
|
|
767
881
|
.signers([wallet])
|
|
768
882
|
.rpc();
|