@aintivirus-ai/mixer-sdk 1.0.0

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.
@@ -0,0 +1,694 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AintiVirusSolana = void 0;
37
+ const anchor = __importStar(require("@coral-xyz/anchor"));
38
+ const web3_js_1 = require("@solana/web3.js");
39
+ const spl_token_1 = require("@solana/spl-token");
40
+ const types_1 = require("../types");
41
+ /**
42
+ * Solana SDK for AintiVirus Mixer
43
+ */
44
+ class AintiVirusSolana {
45
+ constructor(factoryProgramId, mixerProgramId, stakingProgramId, wallet, connection, tokenMint) {
46
+ this.connection = connection;
47
+ this.wallet = wallet;
48
+ // Initialize programs (using any type for IDL flexibility)
49
+ this.factoryProgram = new anchor.Program({}, // IDL should be loaded separately
50
+ new web3_js_1.PublicKey(factoryProgramId), new anchor.AnchorProvider(connection, wallet, {}));
51
+ this.mixerProgram = new anchor.Program({}, new web3_js_1.PublicKey(mixerProgramId), new anchor.AnchorProvider(connection, wallet, {}));
52
+ this.stakingProgram = new anchor.Program({}, new web3_js_1.PublicKey(stakingProgramId), new anchor.AnchorProvider(connection, wallet, {}));
53
+ if (tokenMint) {
54
+ this.tokenMint = new web3_js_1.PublicKey(tokenMint);
55
+ }
56
+ }
57
+ /**
58
+ * Get factory PDA
59
+ */
60
+ getFactoryPda() {
61
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("factory")], this.factoryProgram.programId);
62
+ }
63
+ /**
64
+ * Get mixer pool PDA
65
+ */
66
+ getMixerPoolPda(mode, amount) {
67
+ const amountBuffer = Buffer.allocUnsafe(8);
68
+ amountBuffer.writeBigUInt64LE(amount, 0);
69
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("mixer_pool"), Buffer.from([mode]), amountBuffer], this.factoryProgram.programId);
70
+ }
71
+ /**
72
+ * Get mixer config PDA
73
+ */
74
+ getMixerConfigPda(mode, amount) {
75
+ const amountBuffer = Buffer.allocUnsafe(8);
76
+ amountBuffer.writeBigUInt64LE(amount, 0);
77
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("mixer_config"), Buffer.from([mode]), amountBuffer], this.mixerProgram.programId);
78
+ }
79
+ /**
80
+ * Get merkle tree PDA
81
+ */
82
+ getMerkleTreePda(mixerConfigPda) {
83
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("merkle_tree"), mixerConfigPda.toBuffer()], this.mixerProgram.programId);
84
+ }
85
+ /**
86
+ * Get mixer address for a specific mode and amount
87
+ */
88
+ async getMixer(mode, amount) {
89
+ const [mixerPoolPda] = this.getMixerPoolPda(mode, amount);
90
+ // Call get_mixer instruction (view function)
91
+ try {
92
+ const mixerConfigPubkey = await this.factoryProgram.methods
93
+ .getMixer(mode, new anchor.BN(amount.toString()))
94
+ .accounts({
95
+ mixerPool: mixerPoolPda,
96
+ })
97
+ .view();
98
+ return mixerConfigPubkey;
99
+ }
100
+ catch (error) {
101
+ throw new Error(`Mixer not found for mode ${mode}, amount ${amount}`);
102
+ }
103
+ }
104
+ /**
105
+ * Check if mixer exists
106
+ */
107
+ async mixerExists(mode, amount) {
108
+ try {
109
+ await this.getMixer(mode, amount);
110
+ return true;
111
+ }
112
+ catch {
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Deposit SOL into the mixer
118
+ */
119
+ async depositSol(amount, commitment) {
120
+ const [factoryPda] = this.getFactoryPda();
121
+ const [mixerPoolPda] = this.getMixerPoolPda(types_1.AssetMode.ETH, amount);
122
+ const [mixerConfigPda] = this.getMixerConfigPda(types_1.AssetMode.ETH, amount);
123
+ const [merkleTreePda] = this.getMerkleTreePda(mixerConfigPda);
124
+ const commitmentBytes = Buffer.allocUnsafe(32);
125
+ const commitmentBigInt = commitment;
126
+ commitmentBytes.writeBigUInt64LE(commitmentBigInt & BigInt("0xFFFFFFFFFFFFFFFF"), 0);
127
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 64n) & BigInt("0xFFFFFFFFFFFFFFFF"), 8);
128
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 128n) & BigInt("0xFFFFFFFFFFFFFFFF"), 16);
129
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 192n) & BigInt("0xFFFFFFFFFFFFFFFF"), 24);
130
+ const tx = await this.factoryProgram.methods
131
+ .deposit(types_1.AssetMode.ETH, new anchor.BN(amount.toString()), Array.from(commitmentBytes))
132
+ .accounts({
133
+ factory: factoryPda,
134
+ payer: this.wallet.publicKey,
135
+ mixerProgram: this.mixerProgram.programId,
136
+ mixerPool: mixerPoolPda,
137
+ mixerConfig: mixerConfigPda,
138
+ merkleTree: merkleTreePda,
139
+ systemProgram: web3_js_1.SystemProgram.programId,
140
+ })
141
+ .rpc();
142
+ const signature = tx;
143
+ const txDetails = await this.connection.getTransaction(signature, {
144
+ commitment: "confirmed",
145
+ });
146
+ return {
147
+ txHash: signature,
148
+ blockTime: txDetails?.blockTime ?? undefined,
149
+ };
150
+ }
151
+ /**
152
+ * Deposit tokens into the mixer
153
+ */
154
+ async depositToken(amount, commitment) {
155
+ if (!this.tokenMint) {
156
+ throw new Error("Token mint not configured");
157
+ }
158
+ const [factoryPda] = this.getFactoryPda();
159
+ const [mixerPoolPda] = this.getMixerPoolPda(types_1.AssetMode.TOKEN, amount);
160
+ const [mixerConfigPda] = this.getMixerConfigPda(types_1.AssetMode.TOKEN, amount);
161
+ const [merkleTreePda] = this.getMerkleTreePda(mixerConfigPda);
162
+ const userTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, this.wallet.publicKey);
163
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true // allowOwnerOffCurve
164
+ );
165
+ const commitmentBytes = Buffer.allocUnsafe(32);
166
+ const commitmentBigInt = commitment;
167
+ commitmentBytes.writeBigUInt64LE(commitmentBigInt & BigInt("0xFFFFFFFFFFFFFFFF"), 0);
168
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 64n) & BigInt("0xFFFFFFFFFFFFFFFF"), 8);
169
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 128n) & BigInt("0xFFFFFFFFFFFFFFFF"), 16);
170
+ commitmentBytes.writeBigUInt64LE((commitmentBigInt >> 192n) & BigInt("0xFFFFFFFFFFFFFFFF"), 24);
171
+ const tx = await this.factoryProgram.methods
172
+ .deposit(types_1.AssetMode.TOKEN, new anchor.BN(amount.toString()), Array.from(commitmentBytes))
173
+ .accounts({
174
+ factory: factoryPda,
175
+ payer: this.wallet.publicKey,
176
+ mixerProgram: this.mixerProgram.programId,
177
+ mixerPool: mixerPoolPda,
178
+ mixerConfig: mixerConfigPda,
179
+ merkleTree: merkleTreePda,
180
+ tokenMint: this.tokenMint,
181
+ userTokenAccount: userTokenAccount,
182
+ factoryTokenAccount: factoryTokenAccount,
183
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
184
+ systemProgram: web3_js_1.SystemProgram.programId,
185
+ })
186
+ .rpc();
187
+ const signature = tx;
188
+ const txDetails = await this.connection.getTransaction(signature, {
189
+ commitment: "confirmed",
190
+ });
191
+ return {
192
+ txHash: signature,
193
+ blockTime: txDetails?.blockTime ?? undefined,
194
+ };
195
+ }
196
+ /**
197
+ * Withdraw from the mixer
198
+ */
199
+ async withdraw(instructionData, nullifierHash, amount, mode) {
200
+ const [factoryPda] = this.getFactoryPda();
201
+ const [mixerPoolPda] = this.getMixerPoolPda(mode, amount);
202
+ const [mixerConfigPda] = this.getMixerConfigPda(mode, amount);
203
+ const [merkleTreePda] = this.getMerkleTreePda(mixerConfigPda);
204
+ const nullifierHashBytes = Buffer.allocUnsafe(32);
205
+ const nullifierHashBigInt = nullifierHash;
206
+ nullifierHashBytes.writeBigUInt64LE(nullifierHashBigInt & BigInt("0xFFFFFFFFFFFFFFFF"), 0);
207
+ nullifierHashBytes.writeBigUInt64LE((nullifierHashBigInt >> 64n) & BigInt("0xFFFFFFFFFFFFFFFF"), 8);
208
+ nullifierHashBytes.writeBigUInt64LE((nullifierHashBigInt >> 128n) & BigInt("0xFFFFFFFFFFFFFFFF"), 16);
209
+ nullifierHashBytes.writeBigUInt64LE((nullifierHashBigInt >> 192n) & BigInt("0xFFFFFFFFFFFFFFFF"), 24);
210
+ const accounts = {
211
+ factory: factoryPda,
212
+ payer: this.wallet.publicKey,
213
+ mixerProgram: this.mixerProgram.programId,
214
+ mixerPool: mixerPoolPda,
215
+ mixerConfig: mixerConfigPda,
216
+ merkleTree: merkleTreePda,
217
+ systemProgram: web3_js_1.SystemProgram.programId,
218
+ };
219
+ if (mode === types_1.AssetMode.TOKEN && this.tokenMint) {
220
+ const userTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, this.wallet.publicKey);
221
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true);
222
+ accounts.tokenMint = this.tokenMint;
223
+ accounts.userTokenAccount = userTokenAccount;
224
+ accounts.factoryTokenAccount = factoryTokenAccount;
225
+ accounts.tokenProgram = spl_token_1.TOKEN_PROGRAM_ID;
226
+ }
227
+ const tx = await this.factoryProgram.methods
228
+ .withdraw(mode, new anchor.BN(amount.toString()), Array.from(instructionData), Array.from(nullifierHashBytes))
229
+ .accounts(accounts)
230
+ .rpc();
231
+ const signature = tx;
232
+ const txDetails = await this.connection.getTransaction(signature, {
233
+ commitment: "confirmed",
234
+ });
235
+ return {
236
+ txHash: signature,
237
+ blockTime: txDetails?.blockTime ?? undefined,
238
+ };
239
+ }
240
+ /**
241
+ * Stake SOL
242
+ */
243
+ async stakeSol(amount) {
244
+ const [factoryPda] = this.getFactoryPda();
245
+ const tx = await this.factoryProgram.methods
246
+ .stakeEther(new anchor.BN(amount.toString()))
247
+ .accounts({
248
+ factory: factoryPda,
249
+ staker: this.wallet.publicKey,
250
+ stakingProgram: this.stakingProgram.programId,
251
+ systemProgram: web3_js_1.SystemProgram.programId,
252
+ })
253
+ .rpc();
254
+ const signature = tx;
255
+ const txDetails = await this.connection.getTransaction(signature, {
256
+ commitment: "confirmed",
257
+ });
258
+ return {
259
+ txHash: signature,
260
+ blockTime: txDetails?.blockTime ?? undefined,
261
+ };
262
+ }
263
+ /**
264
+ * Stake tokens
265
+ */
266
+ async stakeToken(amount) {
267
+ if (!this.tokenMint) {
268
+ throw new Error("Token mint not configured");
269
+ }
270
+ const [factoryPda] = this.getFactoryPda();
271
+ const userTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, this.wallet.publicKey);
272
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true);
273
+ const tx = await this.factoryProgram.methods
274
+ .stakeToken(new anchor.BN(amount.toString()))
275
+ .accounts({
276
+ factory: factoryPda,
277
+ staker: this.wallet.publicKey,
278
+ stakingProgram: this.stakingProgram.programId,
279
+ tokenMint: this.tokenMint,
280
+ userTokenAccount: userTokenAccount,
281
+ factoryTokenAccount: factoryTokenAccount,
282
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
283
+ systemProgram: web3_js_1.SystemProgram.programId,
284
+ })
285
+ .rpc();
286
+ const signature = tx;
287
+ const txDetails = await this.connection.getTransaction(signature, {
288
+ commitment: "confirmed",
289
+ });
290
+ return {
291
+ txHash: signature,
292
+ blockTime: txDetails?.blockTime ?? undefined,
293
+ };
294
+ }
295
+ /**
296
+ * Claim SOL rewards
297
+ */
298
+ async claimSol(seasonId) {
299
+ const [factoryPda] = this.getFactoryPda();
300
+ const tx = await this.factoryProgram.methods
301
+ .claimEth(new anchor.BN(seasonId.toString()))
302
+ .accounts({
303
+ factory: factoryPda,
304
+ staker: this.wallet.publicKey,
305
+ stakingProgram: this.stakingProgram.programId,
306
+ systemProgram: web3_js_1.SystemProgram.programId,
307
+ })
308
+ .rpc();
309
+ const signature = tx;
310
+ const txDetails = await this.connection.getTransaction(signature, {
311
+ commitment: "confirmed",
312
+ });
313
+ return {
314
+ txHash: signature,
315
+ blockTime: txDetails?.blockTime ?? undefined,
316
+ };
317
+ }
318
+ /**
319
+ * Claim token rewards
320
+ */
321
+ async claimToken(seasonId) {
322
+ if (!this.tokenMint) {
323
+ throw new Error("Token mint not configured");
324
+ }
325
+ const [factoryPda] = this.getFactoryPda();
326
+ const userTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, this.wallet.publicKey);
327
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true);
328
+ const tx = await this.factoryProgram.methods
329
+ .claimToken(new anchor.BN(seasonId.toString()))
330
+ .accounts({
331
+ factory: factoryPda,
332
+ staker: this.wallet.publicKey,
333
+ stakingProgram: this.stakingProgram.programId,
334
+ tokenMint: this.tokenMint,
335
+ userTokenAccount: userTokenAccount,
336
+ factoryTokenAccount: factoryTokenAccount,
337
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
338
+ systemProgram: web3_js_1.SystemProgram.programId,
339
+ })
340
+ .rpc();
341
+ const signature = tx;
342
+ const txDetails = await this.connection.getTransaction(signature, {
343
+ commitment: "confirmed",
344
+ });
345
+ return {
346
+ txHash: signature,
347
+ blockTime: txDetails?.blockTime ?? undefined,
348
+ };
349
+ }
350
+ /**
351
+ * Unstake SOL
352
+ */
353
+ async unstakeSol() {
354
+ const [factoryPda] = this.getFactoryPda();
355
+ const tx = await this.factoryProgram.methods
356
+ .unstakeEth()
357
+ .accounts({
358
+ factory: factoryPda,
359
+ staker: this.wallet.publicKey,
360
+ stakingProgram: this.stakingProgram.programId,
361
+ systemProgram: web3_js_1.SystemProgram.programId,
362
+ })
363
+ .rpc();
364
+ const signature = tx;
365
+ const txDetails = await this.connection.getTransaction(signature, {
366
+ commitment: "confirmed",
367
+ });
368
+ return {
369
+ txHash: signature,
370
+ blockTime: txDetails?.blockTime ?? undefined,
371
+ };
372
+ }
373
+ /**
374
+ * Unstake tokens
375
+ */
376
+ async unstakeToken() {
377
+ if (!this.tokenMint) {
378
+ throw new Error("Token mint not configured");
379
+ }
380
+ const [factoryPda] = this.getFactoryPda();
381
+ const userTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, this.wallet.publicKey);
382
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true);
383
+ const tx = await this.factoryProgram.methods
384
+ .unstakeToken()
385
+ .accounts({
386
+ factory: factoryPda,
387
+ staker: this.wallet.publicKey,
388
+ stakingProgram: this.stakingProgram.programId,
389
+ tokenMint: this.tokenMint,
390
+ userTokenAccount: userTokenAccount,
391
+ factoryTokenAccount: factoryTokenAccount,
392
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
393
+ systemProgram: web3_js_1.SystemProgram.programId,
394
+ })
395
+ .rpc();
396
+ const signature = tx;
397
+ const txDetails = await this.connection.getTransaction(signature, {
398
+ commitment: "confirmed",
399
+ });
400
+ return {
401
+ txHash: signature,
402
+ blockTime: txDetails?.blockTime ?? undefined,
403
+ };
404
+ }
405
+ /**
406
+ * Get current stake season
407
+ */
408
+ async getCurrentStakeSeason() {
409
+ const [factoryPda] = this.getFactoryPda();
410
+ const factoryAccount = await this.factoryProgram.account.factory.fetch(factoryPda);
411
+ // Assuming factory account has currentStakeSeason field
412
+ // This may need adjustment based on actual account structure
413
+ return BigInt(factoryAccount.currentStakeSeason?.toString() || "0");
414
+ }
415
+ /**
416
+ * Get SOL balance
417
+ */
418
+ async getSolBalance(address) {
419
+ const balance = await this.connection.getBalance(address);
420
+ return BigInt(balance);
421
+ }
422
+ /**
423
+ * Get token balance
424
+ */
425
+ async getTokenBalance(address) {
426
+ if (!this.tokenMint) {
427
+ throw new Error("Token mint not configured");
428
+ }
429
+ const tokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, address);
430
+ try {
431
+ const accountInfo = await this.connection.getTokenAccountBalance(tokenAccount);
432
+ return BigInt(accountInfo.value.amount);
433
+ }
434
+ catch {
435
+ return 0n;
436
+ }
437
+ }
438
+ /**
439
+ * Deploy mixer instance
440
+ */
441
+ async deployMixer(mode, amount) {
442
+ const [factoryPda] = this.getFactoryPda();
443
+ const [mixerPoolPda] = this.getMixerPoolPda(mode, amount);
444
+ const [mixerConfigPda] = this.getMixerConfigPda(mode, amount);
445
+ const [merkleTreePda] = this.getMerkleTreePda(mixerConfigPda);
446
+ const accounts = {
447
+ factory: factoryPda,
448
+ payer: this.wallet.publicKey,
449
+ mixerProgram: this.mixerProgram.programId,
450
+ mixerPool: mixerPoolPda,
451
+ mixerConfig: mixerConfigPda,
452
+ merkleTree: merkleTreePda,
453
+ systemProgram: web3_js_1.SystemProgram.programId,
454
+ };
455
+ if (mode === types_1.AssetMode.TOKEN && this.tokenMint) {
456
+ const factoryTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(this.tokenMint, factoryPda, true);
457
+ accounts.tokenMint = this.tokenMint;
458
+ accounts.factoryTokenAccount = factoryTokenAccount;
459
+ accounts.tokenProgram = spl_token_1.TOKEN_PROGRAM_ID;
460
+ }
461
+ const tx = await this.factoryProgram.methods
462
+ .deployMixer(mode, new anchor.BN(amount.toString()))
463
+ .accounts(accounts)
464
+ .rpc();
465
+ const signature = tx;
466
+ const txDetails = await this.connection.getTransaction(signature, {
467
+ commitment: "confirmed",
468
+ });
469
+ return {
470
+ txHash: signature,
471
+ blockTime: txDetails?.blockTime ?? undefined,
472
+ };
473
+ }
474
+ /**
475
+ * Set fee rate (admin function)
476
+ */
477
+ async setFeeRate(feeRate) {
478
+ const [factoryPda] = this.getFactoryPda();
479
+ const tx = await this.factoryProgram.methods
480
+ .setFeeRate(new anchor.BN(feeRate.toString()))
481
+ .accounts({
482
+ factory: factoryPda,
483
+ authority: this.wallet.publicKey,
484
+ })
485
+ .rpc();
486
+ const signature = tx;
487
+ const txDetails = await this.connection.getTransaction(signature, {
488
+ commitment: "confirmed",
489
+ });
490
+ return {
491
+ txHash: signature,
492
+ blockTime: txDetails?.blockTime ?? undefined,
493
+ };
494
+ }
495
+ /**
496
+ * Set staking season period (admin function)
497
+ */
498
+ async setStakingSeasonPeriod(period) {
499
+ const [factoryPda] = this.getFactoryPda();
500
+ const tx = await this.factoryProgram.methods
501
+ .setStakingSeasonPeriod(new anchor.BN(period.toString()))
502
+ .accounts({
503
+ factory: factoryPda,
504
+ authority: this.wallet.publicKey,
505
+ })
506
+ .rpc();
507
+ const signature = tx;
508
+ const txDetails = await this.connection.getTransaction(signature, {
509
+ commitment: "confirmed",
510
+ });
511
+ return {
512
+ txHash: signature,
513
+ blockTime: txDetails?.blockTime ?? undefined,
514
+ };
515
+ }
516
+ /**
517
+ * Start stake season (admin function)
518
+ */
519
+ async startStakeSeason() {
520
+ const [factoryPda] = this.getFactoryPda();
521
+ const tx = await this.factoryProgram.methods
522
+ .startStakeSeason()
523
+ .accounts({
524
+ factory: factoryPda,
525
+ authority: this.wallet.publicKey,
526
+ stakingProgram: this.stakingProgram.programId,
527
+ })
528
+ .rpc();
529
+ const signature = tx;
530
+ const txDetails = await this.connection.getTransaction(signature, {
531
+ commitment: "confirmed",
532
+ });
533
+ return {
534
+ txHash: signature,
535
+ blockTime: txDetails?.blockTime ?? undefined,
536
+ };
537
+ }
538
+ /**
539
+ * Set verifier address (admin function)
540
+ */
541
+ async setVerifier(verifierAddress) {
542
+ const [factoryPda] = this.getFactoryPda();
543
+ const tx = await this.factoryProgram.methods
544
+ .setVerifier(new web3_js_1.PublicKey(verifierAddress))
545
+ .accounts({
546
+ factory: factoryPda,
547
+ authority: this.wallet.publicKey,
548
+ })
549
+ .rpc();
550
+ const signature = tx;
551
+ const txDetails = await this.connection.getTransaction(signature, {
552
+ commitment: "confirmed",
553
+ });
554
+ return {
555
+ txHash: signature,
556
+ blockTime: txDetails?.blockTime ?? undefined,
557
+ };
558
+ }
559
+ /**
560
+ * Set hasher address (admin function)
561
+ */
562
+ async setHasher(hasherAddress) {
563
+ const [factoryPda] = this.getFactoryPda();
564
+ const tx = await this.factoryProgram.methods
565
+ .setHasher(new web3_js_1.PublicKey(hasherAddress))
566
+ .accounts({
567
+ factory: factoryPda,
568
+ authority: this.wallet.publicKey,
569
+ })
570
+ .rpc();
571
+ const signature = tx;
572
+ const txDetails = await this.connection.getTransaction(signature, {
573
+ commitment: "confirmed",
574
+ });
575
+ return {
576
+ txHash: signature,
577
+ blockTime: txDetails?.blockTime ?? undefined,
578
+ };
579
+ }
580
+ /**
581
+ * Calculate deposit amount including fees
582
+ */
583
+ async calculateDepositAmount(amount) {
584
+ const [factoryPda] = this.getFactoryPda();
585
+ const factoryAccount = await this.factoryProgram.account.factory.fetch(factoryPda);
586
+ const feeRate = BigInt(factoryAccount.feeRate?.toString() || "0");
587
+ // Calculate: amount + (amount * feeRate / 10000)
588
+ return amount + (amount * feeRate) / 10000n;
589
+ }
590
+ /**
591
+ * Get fee rate
592
+ */
593
+ async getFeeRate() {
594
+ const [factoryPda] = this.getFactoryPda();
595
+ const factoryAccount = await this.factoryProgram.account.factory.fetch(factoryPda);
596
+ return BigInt(factoryAccount.feeRate?.toString() || "0");
597
+ }
598
+ /**
599
+ * Get stake season information
600
+ */
601
+ async getStakeSeason(seasonId) {
602
+ const [factoryPda] = this.getFactoryPda();
603
+ // Fetch stake season from staking program
604
+ const seasonPda = web3_js_1.PublicKey.findProgramAddressSync([
605
+ Buffer.from("stake_season"),
606
+ new anchor.BN(seasonId.toString()).toArrayLike(Buffer, "be", 8),
607
+ ], this.stakingProgram.programId)[0];
608
+ try {
609
+ const seasonAccount = await this.stakingProgram.account.stakeSeason.fetch(seasonPda);
610
+ return {
611
+ seasonId: BigInt(seasonAccount.seasonId?.toString() || "0"),
612
+ startTimestamp: BigInt(seasonAccount.startTimestamp?.toString() || "0"),
613
+ endTimestamp: BigInt(seasonAccount.endTimestamp?.toString() || "0"),
614
+ totalStakedEthAmount: BigInt(seasonAccount.totalStakedEthAmount?.toString() || "0"),
615
+ totalStakedTokenAmount: BigInt(seasonAccount.totalStakedTokenAmount?.toString() || "0"),
616
+ totalRewardEthAmount: BigInt(seasonAccount.totalRewardEthAmount?.toString() || "0"),
617
+ totalRewardTokenAmount: BigInt(seasonAccount.totalRewardTokenAmount?.toString() || "0"),
618
+ totalEthWeightValue: BigInt(seasonAccount.totalEthWeightValue?.toString() || "0"),
619
+ totalTokenWeightValue: BigInt(seasonAccount.totalTokenWeightValue?.toString() || "0"),
620
+ };
621
+ }
622
+ catch {
623
+ throw new Error(`Stake season ${seasonId} not found`);
624
+ }
625
+ }
626
+ /**
627
+ * Get staker record
628
+ */
629
+ async getStakerRecord(address) {
630
+ const stakerPubkey = new web3_js_1.PublicKey(address);
631
+ const stakerRecordPda = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("staker_record"), stakerPubkey.toBuffer()], this.stakingProgram.programId)[0];
632
+ try {
633
+ const stakerRecord = await this.stakingProgram.account.stakerRecord.fetch(stakerRecordPda);
634
+ return {
635
+ ethStakedSeasonId: BigInt(stakerRecord.ethStakedSeasonId?.toString() || "0"),
636
+ tokenStakedSeasonId: BigInt(stakerRecord.tokenStakedSeasonId?.toString() || "0"),
637
+ ethStakedTimestamp: BigInt(stakerRecord.ethStakedTimestamp?.toString() || "0"),
638
+ tokenStakedTimestamp: BigInt(stakerRecord.tokenStakedTimestamp?.toString() || "0"),
639
+ stakedEthAmount: BigInt(stakerRecord.stakedEthAmount?.toString() || "0"),
640
+ stakedTokenAmount: BigInt(stakerRecord.stakedTokenAmount?.toString() || "0"),
641
+ ethWeightValue: BigInt(stakerRecord.ethWeightValue?.toString() || "0"),
642
+ tokenWeightValue: BigInt(stakerRecord.tokenWeightValue?.toString() || "0"),
643
+ };
644
+ }
645
+ catch {
646
+ throw new Error(`Staker record for ${address} not found`);
647
+ }
648
+ }
649
+ /**
650
+ * Check if address has claimed SOL for a season
651
+ */
652
+ async hasClaimedSol(address, seasonId) {
653
+ const stakerPubkey = new web3_js_1.PublicKey(address);
654
+ const claimPda = web3_js_1.PublicKey.findProgramAddressSync([
655
+ Buffer.from("season_claimed_eth"),
656
+ stakerPubkey.toBuffer(),
657
+ new anchor.BN(seasonId.toString()).toArrayLike(Buffer, "be", 8),
658
+ ], this.stakingProgram.programId)[0];
659
+ try {
660
+ await this.stakingProgram.account.seasonClaimedEth.fetch(claimPda);
661
+ return true;
662
+ }
663
+ catch {
664
+ return false;
665
+ }
666
+ }
667
+ /**
668
+ * Check if address has claimed tokens for a season
669
+ */
670
+ async hasClaimedToken(address, seasonId) {
671
+ const stakerPubkey = new web3_js_1.PublicKey(address);
672
+ const claimPda = web3_js_1.PublicKey.findProgramAddressSync([
673
+ Buffer.from("season_claimed_token"),
674
+ stakerPubkey.toBuffer(),
675
+ new anchor.BN(seasonId.toString()).toArrayLike(Buffer, "be", 8),
676
+ ], this.stakingProgram.programId)[0];
677
+ try {
678
+ await this.stakingProgram.account.seasonClaimedToken.fetch(claimPda);
679
+ return true;
680
+ }
681
+ catch {
682
+ return false;
683
+ }
684
+ }
685
+ /**
686
+ * Get staking address (PDA)
687
+ */
688
+ async getStakingAddress() {
689
+ const [factoryPda] = this.getFactoryPda();
690
+ const factoryAccount = await this.factoryProgram.account.factory.fetch(factoryPda);
691
+ return factoryAccount.staking;
692
+ }
693
+ }
694
+ exports.AintiVirusSolana = AintiVirusSolana;