nara-sdk 1.0.37 → 1.0.40
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 +53 -18
- 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 +86 -67
- package/src/zkid.ts +132 -77
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
|
+
- **Referral system**: register with referral via `registerAgentWithReferral`, or set referral post-registration via `setReferral`
|
|
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
|
|
41
|
+
- **Activity logging**: `logActivity` for standard logging, `logActivityWithReferral` for referral-based logging
|
|
38
42
|
- Memory modes: `new`, `update`, `append`, `auto` (auto-detects)
|
|
39
|
-
- Points
|
|
43
|
+
- Points are minted as **Token-2022 SPL tokens** — separate mints for registration points (`pointMint`), referee rewards (`refereeMint`), and activity rewards (`refereeActivityMint`)
|
|
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);
|
|
@@ -170,13 +187,17 @@ console.log(isValidRecipient(recipient.publicKey)); // true
|
|
|
170
187
|
```typescript
|
|
171
188
|
import {
|
|
172
189
|
registerAgent,
|
|
190
|
+
registerAgentWithReferral,
|
|
173
191
|
getAgentRecord,
|
|
174
192
|
getAgentInfo,
|
|
175
193
|
getAgentMemory,
|
|
194
|
+
getAgentRegistryConfig,
|
|
176
195
|
setBio,
|
|
177
196
|
setMetadata,
|
|
178
197
|
uploadMemory,
|
|
179
198
|
logActivity,
|
|
199
|
+
logActivityWithReferral,
|
|
200
|
+
setReferral,
|
|
180
201
|
deleteAgent,
|
|
181
202
|
Keypair,
|
|
182
203
|
} from "nara-sdk";
|
|
@@ -185,33 +206,47 @@ import { Connection } from "@solana/web3.js";
|
|
|
185
206
|
const connection = new Connection("https://mainnet-api.nara.build/", "confirmed");
|
|
186
207
|
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
187
208
|
|
|
188
|
-
//
|
|
209
|
+
// 1a. Register an agent (lowercase only, charges registration fee)
|
|
189
210
|
const { signature, agentPubkey } = await registerAgent(connection, wallet, "my-agent");
|
|
190
211
|
|
|
191
|
-
//
|
|
212
|
+
// 1b. Or register with referral
|
|
213
|
+
const result = await registerAgentWithReferral(
|
|
214
|
+
connection, wallet, "my-agent", "referral-agent-id"
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
// 2. Or set referral after registration
|
|
218
|
+
await setReferral(connection, wallet, "my-agent", "referral-agent-id");
|
|
219
|
+
|
|
220
|
+
// 3. Set bio and metadata
|
|
192
221
|
await setBio(connection, wallet, "my-agent", "An AI assistant for code review.");
|
|
193
222
|
await setMetadata(connection, wallet, "my-agent", JSON.stringify({ model: "gpt-4" }));
|
|
194
223
|
|
|
195
|
-
//
|
|
224
|
+
// 4. Upload memory (auto-chunked, supports new/update/append modes)
|
|
196
225
|
const memory = Buffer.from(JSON.stringify({ facts: ["sky is blue"] }));
|
|
197
226
|
await uploadMemory(connection, wallet, "my-agent", memory, {
|
|
198
227
|
onProgress(chunk, total, sig) { console.log(`[${chunk}/${total}] ${sig}`); },
|
|
199
228
|
});
|
|
200
229
|
|
|
201
|
-
//
|
|
230
|
+
// 5. Read back memory
|
|
202
231
|
const bytes = await getAgentMemory(connection, "my-agent");
|
|
203
232
|
|
|
204
|
-
//
|
|
233
|
+
// 6. Append to existing memory
|
|
205
234
|
const extra = Buffer.from(JSON.stringify({ more: "data" }));
|
|
206
235
|
await uploadMemory(connection, wallet, "my-agent", extra, {}, "append");
|
|
207
236
|
|
|
208
|
-
//
|
|
237
|
+
// 7a. Log activity
|
|
209
238
|
await logActivity(connection, wallet, "my-agent", "gpt-4", "chat", "Answered a question");
|
|
210
|
-
await logActivity(connection, wallet, "my-agent", "gpt-4", "chat", "With referral", undefined, "referral-agent-id");
|
|
211
239
|
|
|
212
|
-
//
|
|
240
|
+
// 7b. Log activity with referral
|
|
241
|
+
await logActivityWithReferral(connection, wallet, "my-agent", "gpt-4", "chat", "With referral", "referral-agent-id");
|
|
242
|
+
|
|
243
|
+
// 8. Query agent info
|
|
213
244
|
const info = await getAgentInfo(connection, "my-agent");
|
|
214
|
-
console.log(info.record.agentId, info.record.
|
|
245
|
+
console.log(info.record.agentId, info.record.referralId, info.bio);
|
|
246
|
+
|
|
247
|
+
// 9. Query program config
|
|
248
|
+
const config = await getAgentRegistryConfig(connection);
|
|
249
|
+
console.log(config.pointMint.toBase58(), config.refereeMint.toBase58(), config.pointsSelf, config.activityReward);
|
|
215
250
|
```
|
|
216
251
|
|
|
217
252
|
### 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();
|