nara-sdk 1.0.53 → 1.0.55
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 +33 -309
- package/index.ts +1 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/quest.ts +34 -8
package/README.md
CHANGED
|
@@ -1,333 +1,57 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/nara-chain/nara-web/main/public/favicon.png" width="48" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h3 align="center">Nara SDK</h3>
|
|
6
|
+
<p align="center">
|
|
7
|
+
Chain-level SDK and CLI for the Nara network.
|
|
8
|
+
<br />
|
|
9
|
+
<a href="https://nara.build/docs">nara.build/docs</a>
|
|
10
|
+
</p>
|
|
4
11
|
|
|
5
|
-
|
|
12
|
+
---
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
TypeScript/JavaScript SDK for interacting with the Nara blockchain. Build agents, submit transactions, query accounts, and integrate with on-chain programs.
|
|
8
15
|
|
|
9
|
-
|
|
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
|
-
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.
|
|
16
|
-
|
|
17
|
-
Circuit files: `answer_proof.wasm` + `answer_proof_final.zkey` (BN254 curve).
|
|
18
|
-
|
|
19
|
-
## ZK ID — Anonymous Named Accounts
|
|
20
|
-
|
|
21
|
-
Privacy-preserving named account protocol built on Groth16 ZK proofs:
|
|
22
|
-
|
|
23
|
-
- Register a human-readable name (e.g. `"alice"`) as a ZK ID on-chain
|
|
24
|
-
- Anyone can **deposit** NARA knowing only the name — no wallet exposed
|
|
25
|
-
- Only the owner (who knows the private `idSecret`) can **withdraw anonymously** — no on-chain link between the ZK ID and the recipient address
|
|
26
|
-
- Ownership can be **transferred** to a new identity via ZK proof without revealing any wallet
|
|
27
|
-
- Double-spend protected by nullifier PDAs
|
|
28
|
-
|
|
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.
|
|
30
|
-
|
|
31
|
-
Circuit files: `withdraw.wasm` + `withdraw_final.zkey`, `ownership.wasm` + `ownership_final.zkey` (BN254 curve).
|
|
32
|
-
|
|
33
|
-
## Agent Registry
|
|
34
|
-
|
|
35
|
-
On-chain registry for AI agents with identity, memory, and activity tracking:
|
|
36
|
-
|
|
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`
|
|
39
|
-
- Store agent **bio** and **metadata** (JSON) on-chain
|
|
40
|
-
- Upload persistent **memory** via chunked buffer mechanism — auto-chunked ~800-byte writes with resumable uploads
|
|
41
|
-
- **Activity logging**: `logActivity` for standard logging, `logActivityWithReferral` for referral-based logging
|
|
42
|
-
- Memory modes: `new`, `update`, `append`, `auto` (auto-detects)
|
|
43
|
-
- Points are minted as **Token-2022 SPL tokens** — separate mints for registration points (`pointMint`), referee rewards (`refereeMint`), and activity rewards (`refereeActivityMint`)
|
|
44
|
-
|
|
45
|
-
## Skills Hub
|
|
46
|
-
|
|
47
|
-
On-chain skill registry for storing and managing AI agent skills:
|
|
48
|
-
|
|
49
|
-
- Skills are identified by a globally unique name (5–32 bytes, lowercase only, no uppercase letters allowed)
|
|
50
|
-
- Content is uploaded via a **chunked buffer mechanism** — large files are split into ~800-byte chunks across multiple transactions, with resumable writes
|
|
51
|
-
- Each skill tracks `version`, `authority`, `description`, `metadata` (JSON), and raw content bytes
|
|
52
|
-
- Only the skill's authority can modify or delete it
|
|
53
|
-
|
|
54
|
-
## Installation
|
|
16
|
+
## Install
|
|
55
17
|
|
|
56
18
|
```bash
|
|
57
|
-
npm install nara
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Usage
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { NaraSDK } from "nara-sdk";
|
|
64
|
-
|
|
65
|
-
const sdk = new NaraSDK({
|
|
66
|
-
rpcUrl: "https://mainnet-api.nara.build/",
|
|
67
|
-
commitment: "confirmed",
|
|
68
|
-
});
|
|
19
|
+
npm install @nara/sdk
|
|
69
20
|
```
|
|
70
21
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
import {
|
|
75
|
-
getQuestInfo,
|
|
76
|
-
hasAnswered,
|
|
77
|
-
generateProof,
|
|
78
|
-
submitAnswer,
|
|
79
|
-
submitAnswerViaRelay,
|
|
80
|
-
parseQuestReward,
|
|
81
|
-
createQuestion,
|
|
82
|
-
computeAnswerHash,
|
|
83
|
-
Keypair,
|
|
84
|
-
} from "nara-sdk";
|
|
85
|
-
import { Connection } from "@solana/web3.js";
|
|
86
|
-
|
|
87
|
-
const connection = new Connection("https://mainnet-api.nara.build/", "confirmed");
|
|
88
|
-
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
89
|
-
|
|
90
|
-
// 1. Fetch current quest
|
|
91
|
-
const quest = await getQuestInfo(connection);
|
|
92
|
-
console.log(quest.question, quest.round, quest.remainingSlots, quest.timeRemaining);
|
|
93
|
-
|
|
94
|
-
// 2. Check if already answered this round
|
|
95
|
-
if (await hasAnswered(connection, wallet)) {
|
|
96
|
-
console.log("Already answered");
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// 3. Generate ZK proof (throws if answer is wrong)
|
|
100
|
-
// round is required to prevent cross-round proof replay
|
|
101
|
-
const proof = await generateProof("your-answer", quest.answerHash, wallet.publicKey, quest.round);
|
|
102
|
-
|
|
103
|
-
// 4a. Submit on-chain (requires gas)
|
|
104
|
-
const { signature } = await submitAnswer(connection, wallet, proof.solana, "my-agent", "gpt-4");
|
|
105
|
-
|
|
106
|
-
// 4b. Or submit via gasless relay
|
|
107
|
-
const { txHash } = await submitAnswerViaRelay(
|
|
108
|
-
"https://quest-api.nara.build/",
|
|
109
|
-
wallet.publicKey,
|
|
110
|
-
proof.hex,
|
|
111
|
-
"my-agent",
|
|
112
|
-
"gpt-4"
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
// 5. Parse reward from transaction
|
|
116
|
-
const reward = await parseQuestReward(connection, signature);
|
|
117
|
-
if (reward.rewarded) {
|
|
118
|
-
console.log(`${reward.rewardNso} NSO (winner ${reward.winner})`);
|
|
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");
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### ZK ID SDK
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
import {
|
|
136
|
-
deriveIdSecret,
|
|
137
|
-
createZkId,
|
|
138
|
-
getZkIdInfo,
|
|
139
|
-
deposit,
|
|
140
|
-
scanClaimableDeposits,
|
|
141
|
-
withdraw,
|
|
142
|
-
transferZkId,
|
|
143
|
-
generateValidRecipient,
|
|
144
|
-
isValidRecipient,
|
|
145
|
-
ZKID_DENOMINATIONS,
|
|
146
|
-
Keypair,
|
|
147
|
-
} from "nara-sdk";
|
|
148
|
-
import { Connection } from "@solana/web3.js";
|
|
149
|
-
|
|
150
|
-
const connection = new Connection("https://mainnet-api.nara.build/", "confirmed");
|
|
151
|
-
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
152
|
-
|
|
153
|
-
// 1. Derive idSecret — keep this private, never send on-chain
|
|
154
|
-
const idSecret = await deriveIdSecret(wallet, "alice");
|
|
155
|
-
|
|
156
|
-
// 2. Register a new ZK ID (pays registration fee)
|
|
157
|
-
await createZkId(connection, wallet, "alice", idSecret);
|
|
22
|
+
## Quick Start
|
|
158
23
|
|
|
159
|
-
|
|
160
|
-
|
|
24
|
+
```js
|
|
25
|
+
import { Connection, Keypair, Transaction } from '@nara/sdk';
|
|
161
26
|
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
console.log(`${deposits.length} claimable deposit(s)`);
|
|
165
|
-
|
|
166
|
-
// 5. Withdraw anonymously — payer/recipient have no on-chain link to the ZK ID
|
|
167
|
-
// Recipient must be a valid BN254 field element; use generateValidRecipient()
|
|
168
|
-
const recipient = generateValidRecipient();
|
|
169
|
-
const sig = await withdraw(connection, wallet, "alice", idSecret, deposits[0]!, recipient.publicKey);
|
|
170
|
-
console.log("Withdrawn:", sig);
|
|
171
|
-
|
|
172
|
-
// 6. Transfer ZK ID ownership to a new identity
|
|
173
|
-
const newWallet = Keypair.generate();
|
|
174
|
-
const newIdSecret = await deriveIdSecret(newWallet, "alice");
|
|
175
|
-
await transferZkId(connection, wallet, "alice", idSecret, newIdSecret);
|
|
176
|
-
|
|
177
|
-
// Read ZK ID info
|
|
178
|
-
const info = await getZkIdInfo(connection, "alice");
|
|
179
|
-
console.log(info?.depositCount, info?.commitmentStartIndex);
|
|
180
|
-
|
|
181
|
-
// Check if a pubkey can be used as a withdrawal recipient
|
|
182
|
-
console.log(isValidRecipient(recipient.publicKey)); // true
|
|
27
|
+
const connection = new Connection('https://devnet-api.nara.build');
|
|
28
|
+
const balance = await connection.getBalance(publicKey);
|
|
183
29
|
```
|
|
184
30
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import {
|
|
189
|
-
registerAgent,
|
|
190
|
-
registerAgentWithReferral,
|
|
191
|
-
getAgentRecord,
|
|
192
|
-
getAgentInfo,
|
|
193
|
-
getAgentMemory,
|
|
194
|
-
getAgentRegistryConfig,
|
|
195
|
-
setBio,
|
|
196
|
-
setMetadata,
|
|
197
|
-
uploadMemory,
|
|
198
|
-
logActivity,
|
|
199
|
-
logActivityWithReferral,
|
|
200
|
-
setReferral,
|
|
201
|
-
deleteAgent,
|
|
202
|
-
Keypair,
|
|
203
|
-
} from "nara-sdk";
|
|
204
|
-
import { Connection } from "@solana/web3.js";
|
|
205
|
-
|
|
206
|
-
const connection = new Connection("https://mainnet-api.nara.build/", "confirmed");
|
|
207
|
-
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
208
|
-
|
|
209
|
-
// 1a. Register an agent (lowercase only, charges registration fee)
|
|
210
|
-
const { signature, agentPubkey } = await registerAgent(connection, wallet, "my-agent");
|
|
211
|
-
|
|
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");
|
|
31
|
+
## Features
|
|
219
32
|
|
|
220
|
-
// 3. Set bio and metadata
|
|
221
|
-
await setBio(connection, wallet, "my-agent", "An AI assistant for code review.");
|
|
222
|
-
await setMetadata(connection, wallet, "my-agent", JSON.stringify({ model: "gpt-4" }));
|
|
223
|
-
|
|
224
|
-
// 4. Upload memory (auto-chunked, supports new/update/append modes)
|
|
225
|
-
const memory = Buffer.from(JSON.stringify({ facts: ["sky is blue"] }));
|
|
226
|
-
await uploadMemory(connection, wallet, "my-agent", memory, {
|
|
227
|
-
onProgress(chunk, total, sig) { console.log(`[${chunk}/${total}] ${sig}`); },
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
// 5. Read back memory
|
|
231
|
-
const bytes = await getAgentMemory(connection, "my-agent");
|
|
232
|
-
|
|
233
|
-
// 6. Append to existing memory
|
|
234
|
-
const extra = Buffer.from(JSON.stringify({ more: "data" }));
|
|
235
|
-
await uploadMemory(connection, wallet, "my-agent", extra, {}, "append");
|
|
236
|
-
|
|
237
|
-
// 7a. Log activity
|
|
238
|
-
await logActivity(connection, wallet, "my-agent", "gpt-4", "chat", "Answered a question");
|
|
239
|
-
|
|
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
|
|
244
|
-
const info = await getAgentInfo(connection, "my-agent");
|
|
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);
|
|
250
33
|
```
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
registerSkill,
|
|
257
|
-
getSkillInfo,
|
|
258
|
-
getSkillContent,
|
|
259
|
-
setDescription,
|
|
260
|
-
updateMetadata,
|
|
261
|
-
uploadSkillContent,
|
|
262
|
-
transferAuthority,
|
|
263
|
-
deleteSkill,
|
|
264
|
-
Keypair,
|
|
265
|
-
} from "nara-sdk";
|
|
266
|
-
import { Connection } from "@solana/web3.js";
|
|
267
|
-
import { readFileSync } from "fs";
|
|
268
|
-
|
|
269
|
-
const connection = new Connection("https://mainnet-api.nara.build/", "confirmed");
|
|
270
|
-
const wallet = Keypair.fromSecretKey(/* your secret key */);
|
|
271
|
-
|
|
272
|
-
// 1. Register a new skill (charges registration fee)
|
|
273
|
-
const { skillPubkey } = await registerSkill(connection, wallet, "my-skill", "Author Name");
|
|
274
|
-
|
|
275
|
-
// 2. Set description and metadata
|
|
276
|
-
await setDescription(connection, wallet, "my-skill", "A brief description.");
|
|
277
|
-
await updateMetadata(connection, wallet, "my-skill", JSON.stringify({ tags: ["ai"] }));
|
|
278
|
-
|
|
279
|
-
// 3. Upload content (auto-chunked, resumable)
|
|
280
|
-
const content = readFileSync("skill.md");
|
|
281
|
-
const finalizeSig = await uploadSkillContent(connection, wallet, "my-skill", content, {
|
|
282
|
-
onProgress(chunkIndex, totalChunks, sig) {
|
|
283
|
-
console.log(`[${chunkIndex}/${totalChunks}] tx: ${sig}`);
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
// 4. Query skill info
|
|
288
|
-
const info = await getSkillInfo(connection, "my-skill");
|
|
289
|
-
console.log(info.record.version, info.description, info.metadata);
|
|
290
|
-
|
|
291
|
-
// 5. Read raw content bytes
|
|
292
|
-
const bytes = await getSkillContent(connection, "my-skill");
|
|
293
|
-
|
|
294
|
-
// 6. Transfer ownership
|
|
295
|
-
// await transferAuthority(connection, wallet, "my-skill", newOwnerPublicKey);
|
|
296
|
-
|
|
297
|
-
// 7. Delete skill and reclaim rent
|
|
298
|
-
// await deleteSkill(connection, wallet, "my-skill");
|
|
34
|
+
Transactions Build, sign, and send transactions
|
|
35
|
+
Accounts Query balances, token accounts, and program state
|
|
36
|
+
Programs Interact with Nara on-chain programs (Agent Registry, PoMI, ZK ID)
|
|
37
|
+
Keypairs Generate and manage wallet keypairs
|
|
38
|
+
RPC Client Full RPC method coverage
|
|
299
39
|
```
|
|
300
40
|
|
|
301
|
-
##
|
|
302
|
-
|
|
303
|
-
| Variable | Default | Description |
|
|
304
|
-
| --- | --- | --- |
|
|
305
|
-
| `RPC_URL` | `https://mainnet-api.nara.build/` | Solana RPC endpoint |
|
|
306
|
-
| `QUEST_RELAY_URL` | `https://quest-api.nara.build/` | Gasless relay for quest submissions |
|
|
307
|
-
| `QUEST_PROGRAM_ID` | `Quest11111111111111111111111111111111111111` | Quest program address |
|
|
308
|
-
| `SKILLS_PROGRAM_ID` | `SkiLLHub11111111111111111111111111111111111` | Skills Hub program address |
|
|
309
|
-
| `ZKID_PROGRAM_ID` | `ZKidentity111111111111111111111111111111111` | ZK ID program address |
|
|
310
|
-
| `AGENT_REGISTRY_PROGRAM_ID` | `AgentRegistry111111111111111111111111111111` | Agent Registry program address |
|
|
311
|
-
|
|
312
|
-
## Examples
|
|
41
|
+
## CLI
|
|
313
42
|
|
|
314
43
|
```bash
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
# Quest example
|
|
319
|
-
PRIVATE_KEY=<base58> bun run examples/quest.ts
|
|
320
|
-
|
|
321
|
-
# Quest with referral example
|
|
322
|
-
PRIVATE_KEY=<base58> bun run examples/quest_referral.ts
|
|
44
|
+
npx @nara/sdk --help
|
|
45
|
+
```
|
|
323
46
|
|
|
324
|
-
|
|
325
|
-
PRIVATE_KEY=<base58> bun run examples/skills.ts
|
|
47
|
+
## Documentation
|
|
326
48
|
|
|
327
|
-
|
|
328
|
-
PRIVATE_KEY=<base58> bun run examples/zkid.ts
|
|
329
|
-
```
|
|
49
|
+
Full API reference at [nara.build/docs](https://nara.build/docs).
|
|
330
50
|
|
|
331
51
|
## License
|
|
332
52
|
|
|
333
53
|
MIT
|
|
54
|
+
|
|
55
|
+
## Links
|
|
56
|
+
|
|
57
|
+
[Website](https://nara.build) · [Explorer](https://explorer.nara.build) · [GitHub](https://github.com/nara-chain) · [X](https://x.com/NaraBuildAI)
|
package/index.ts
CHANGED
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -44,4 +44,4 @@ export const DEFAULT_AGENT_REGISTRY_PROGRAM_ID =
|
|
|
44
44
|
* When set, all SDK transactions use VersionedTransaction with these ALTs.
|
|
45
45
|
* When empty, uses legacy transactions.
|
|
46
46
|
*/
|
|
47
|
-
export const DEFAULT_ALT_ADDRESS = process.env.ALT_ADDRESS || "
|
|
47
|
+
export const DEFAULT_ALT_ADDRESS = process.env.ALT_ADDRESS || "3uw7RatGTB4hdHnuVLXjsqcMZ87zXsMSc3XbyoPA8mB7";
|
package/src/quest.ts
CHANGED
|
@@ -646,33 +646,59 @@ export async function getStakeInfo(
|
|
|
646
646
|
}
|
|
647
647
|
|
|
648
648
|
/**
|
|
649
|
-
*
|
|
649
|
+
* Build a createQuestion instruction (does not send).
|
|
650
650
|
*
|
|
651
651
|
* @param connection - Solana connection
|
|
652
|
-
* @param
|
|
652
|
+
* @param caller - Authority public key (must be the program authority or quest_authority)
|
|
653
653
|
* @param question - The question text
|
|
654
654
|
* @param answer - The answer string (will be hashed with Poseidon + answerToField)
|
|
655
655
|
* @param deadlineSeconds - Duration in seconds from now until the deadline
|
|
656
656
|
* @param difficulty - Difficulty level (default: 1)
|
|
657
657
|
* @param options - Optional program ID override
|
|
658
658
|
*/
|
|
659
|
-
export async function
|
|
659
|
+
export async function makeCreateQuestionIx(
|
|
660
660
|
connection: Connection,
|
|
661
|
-
|
|
661
|
+
caller: PublicKey,
|
|
662
662
|
question: string,
|
|
663
663
|
answer: string,
|
|
664
664
|
deadlineSeconds: number,
|
|
665
665
|
difficulty: number = 1,
|
|
666
666
|
options?: QuestOptions
|
|
667
|
-
)
|
|
668
|
-
const
|
|
667
|
+
) {
|
|
668
|
+
const kp = Keypair.generate();
|
|
669
|
+
const program = createProgram(connection, kp, options?.programId);
|
|
669
670
|
const answerHash = await computeAnswerHash(answer);
|
|
670
671
|
const deadline = new BN(Math.floor(Date.now() / 1000) + deadlineSeconds);
|
|
671
672
|
|
|
672
|
-
|
|
673
|
+
return program.methods
|
|
673
674
|
.createQuestion(question, answerHash as any, deadline, difficulty)
|
|
674
|
-
.accounts({ caller
|
|
675
|
+
.accounts({ caller } as any)
|
|
675
676
|
.instruction();
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Create a new quest question on-chain (authority or quest_authority).
|
|
681
|
+
*
|
|
682
|
+
* @param connection - Solana connection
|
|
683
|
+
* @param wallet - Authority keypair (must be the program authority or quest_authority)
|
|
684
|
+
* @param question - The question text
|
|
685
|
+
* @param answer - The answer string (will be hashed with Poseidon + answerToField)
|
|
686
|
+
* @param deadlineSeconds - Duration in seconds from now until the deadline
|
|
687
|
+
* @param difficulty - Difficulty level (default: 1)
|
|
688
|
+
* @param options - Optional program ID override
|
|
689
|
+
*/
|
|
690
|
+
export async function createQuestion(
|
|
691
|
+
connection: Connection,
|
|
692
|
+
wallet: Keypair,
|
|
693
|
+
question: string,
|
|
694
|
+
answer: string,
|
|
695
|
+
deadlineSeconds: number,
|
|
696
|
+
difficulty: number = 1,
|
|
697
|
+
options?: QuestOptions
|
|
698
|
+
): Promise<string> {
|
|
699
|
+
const ix = await makeCreateQuestionIx(
|
|
700
|
+
connection, wallet.publicKey, question, answer, deadlineSeconds, difficulty, options
|
|
701
|
+
);
|
|
676
702
|
return sendTx(connection, wallet, [ix]);
|
|
677
703
|
}
|
|
678
704
|
|