@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.
- package/README.md +711 -0
- package/dist/evm/index.d.ts +117 -0
- package/dist/evm/index.js +377 -0
- package/dist/hooks/index.d.ts +29 -0
- package/dist/hooks/index.js +36 -0
- package/dist/hooks/useAdmin.d.ts +35 -0
- package/dist/hooks/useAdmin.js +195 -0
- package/dist/hooks/useAintiVirus.d.ts +48 -0
- package/dist/hooks/useAintiVirus.js +238 -0
- package/dist/hooks/useClaim.d.ts +31 -0
- package/dist/hooks/useClaim.js +110 -0
- package/dist/hooks/useDeploy.d.ts +32 -0
- package/dist/hooks/useDeploy.js +96 -0
- package/dist/hooks/useDeposit.d.ts +30 -0
- package/dist/hooks/useDeposit.js +96 -0
- package/dist/hooks/useStake.d.ts +31 -0
- package/dist/hooks/useStake.js +112 -0
- package/dist/hooks/useView.d.ts +40 -0
- package/dist/hooks/useView.js +255 -0
- package/dist/hooks/useWithdraw.d.ts +30 -0
- package/dist/hooks/useWithdraw.js +98 -0
- package/dist/hooks/utils.d.ts +11 -0
- package/dist/hooks/utils.js +65 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +97 -0
- package/dist/solana/index.d.ts +139 -0
- package/dist/solana/index.js +694 -0
- package/dist/types/index.d.ts +103 -0
- package/dist/types/index.js +19 -0
- package/dist/utils/crypto.d.ts +23 -0
- package/dist/utils/crypto.js +43 -0
- package/dist/utils/proof.d.ts +34 -0
- package/dist/utils/proof.js +120 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
# AintiVirus Mixer SDK
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for easy integration with AintiVirus Mixer - a privacy-preserving transaction mixer for both EVM (Ethereum) and Solana blockchains.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 **Privacy-Preserving Transactions**: Deposit and withdraw funds anonymously using zero-knowledge proofs
|
|
8
|
+
- 💰 **Multi-Asset Support**: Support for native tokens (ETH/SOL) and ERC20/SPL tokens
|
|
9
|
+
- 🎯 **Staking & Rewards**: Stake assets and earn rewards from mixer fees
|
|
10
|
+
- 🌐 **Cross-Chain**: Unified API for both EVM and Solana
|
|
11
|
+
- 📦 **TypeScript**: Full TypeScript support with type definitions
|
|
12
|
+
- 🚀 **Easy Integration**: Simple API designed for frontend applications
|
|
13
|
+
- ⚛️ **React Hooks**: Optimized React hooks for Next.js with code splitting support
|
|
14
|
+
- 📊 **View Functions**: Comprehensive read-only functions for contract data
|
|
15
|
+
- 🔧 **Admin Functions**: Admin operations for contract management
|
|
16
|
+
- 🏗️ **Deploy Mixers**: Deploy new mixer instances programmatically
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @aintivirus-ai/mixer-sdk
|
|
22
|
+
# or
|
|
23
|
+
yarn add @aintivirus-ai/mixer-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### React Hooks (Recommended for Next.js)
|
|
29
|
+
|
|
30
|
+
The SDK provides optimized React hooks for Next.js applications with automatic code splitting:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { useDeposit, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
34
|
+
import {
|
|
35
|
+
generateSecretAndNullifier,
|
|
36
|
+
computeCommitment,
|
|
37
|
+
} from "@aintivirus-ai/mixer-sdk";
|
|
38
|
+
import { parseEther } from "ethers";
|
|
39
|
+
|
|
40
|
+
function DepositPage() {
|
|
41
|
+
const { deposit, isEVMReady } = useDeposit({
|
|
42
|
+
evm: {
|
|
43
|
+
factoryAddress: "0x...",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const handleDeposit = async () => {
|
|
48
|
+
const { secret, nullifier } = generateSecretAndNullifier();
|
|
49
|
+
const commitment = computeCommitment(secret, nullifier);
|
|
50
|
+
const amount = parseEther("1");
|
|
51
|
+
|
|
52
|
+
await deposit(ChainType.EVM, amount, commitment);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return <button onClick={handleDeposit}>Deposit</button>;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Available Hooks:**
|
|
60
|
+
|
|
61
|
+
- `useDeposit` - For deposits only
|
|
62
|
+
- `useStake` - For staking/unstaking only
|
|
63
|
+
- `useClaim` - For claiming rewards only
|
|
64
|
+
- `useWithdraw` - For withdrawals only
|
|
65
|
+
- `useView` - For reading contract data only
|
|
66
|
+
- `useDeploy` - For deploying mixers only
|
|
67
|
+
- `useAdmin` - For admin operations only
|
|
68
|
+
- `useAintiVirus` - All-in-one hook (when you need multiple functions)
|
|
69
|
+
|
|
70
|
+
See [Examples](#examples) section for complete hook examples.
|
|
71
|
+
|
|
72
|
+
### EVM (Ethereum) Example
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import {
|
|
76
|
+
AintiVirusEVM,
|
|
77
|
+
AssetMode,
|
|
78
|
+
generateSecretAndNullifier,
|
|
79
|
+
computeCommitment,
|
|
80
|
+
} from "@aintivirus-ai/mixer-sdk";
|
|
81
|
+
import { ethers } from "ethers";
|
|
82
|
+
|
|
83
|
+
// Connect to Ethereum
|
|
84
|
+
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
85
|
+
const signer = await provider.getSigner();
|
|
86
|
+
|
|
87
|
+
// Initialize SDK
|
|
88
|
+
const sdk = new AintiVirusEVM(
|
|
89
|
+
"0x...", // Factory contract address
|
|
90
|
+
"0x...", // Token contract address
|
|
91
|
+
signer
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Deposit ETH
|
|
95
|
+
const { secret, nullifier } = generateSecretAndNullifier();
|
|
96
|
+
const commitment = computeCommitment(secret, nullifier);
|
|
97
|
+
const amount = ethers.parseEther("1"); // 1 ETH
|
|
98
|
+
|
|
99
|
+
const result = await sdk.depositEth(amount, commitment);
|
|
100
|
+
console.log("Deposit transaction:", result.txHash);
|
|
101
|
+
|
|
102
|
+
// Withdraw (requires ZK proof - see proof generation section)
|
|
103
|
+
// const proof = await generateWithdrawalProof(...);
|
|
104
|
+
// await sdk.withdraw(proof, amount, AssetMode.ETH);
|
|
105
|
+
|
|
106
|
+
// Stake ETH
|
|
107
|
+
await sdk.stakeEther(ethers.parseEther("10"));
|
|
108
|
+
|
|
109
|
+
// Claim rewards
|
|
110
|
+
const currentSeason = await sdk.getCurrentStakeSeason();
|
|
111
|
+
await sdk.claimEth(currentSeason);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Solana Example
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import {
|
|
118
|
+
AintiVirusSolana,
|
|
119
|
+
AssetMode,
|
|
120
|
+
generateSecretAndNullifier,
|
|
121
|
+
computeCommitment,
|
|
122
|
+
} from "@aintivirus-ai/mixer-sdk";
|
|
123
|
+
import { Connection, Keypair } from "@solana/web3.js";
|
|
124
|
+
import { Wallet } from "@coral-xyz/anchor";
|
|
125
|
+
|
|
126
|
+
// Connect to Solana
|
|
127
|
+
const connection = new Connection("https://api.mainnet-beta.solana.com");
|
|
128
|
+
const wallet = new Wallet(keypair); // Your wallet/keypair
|
|
129
|
+
|
|
130
|
+
// Initialize SDK
|
|
131
|
+
const sdk = new AintiVirusSolana(
|
|
132
|
+
"AinTiV1ru5FacTor1111111111111111111111111111", // Factory program ID
|
|
133
|
+
"AinTiV1ru5Mixer1111111111111111111111111111", // Mixer program ID
|
|
134
|
+
"AinTiV1ru5Staking1111111111111111111111111111", // Staking program ID
|
|
135
|
+
wallet,
|
|
136
|
+
connection,
|
|
137
|
+
"TokenMintAddress..." // Optional: Token mint address
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// Deposit SOL
|
|
141
|
+
const { secret, nullifier } = generateSecretAndNullifier();
|
|
142
|
+
const commitment = computeCommitment(secret, nullifier);
|
|
143
|
+
const amount = 1_000_000_000n; // 1 SOL (in lamports)
|
|
144
|
+
|
|
145
|
+
const result = await sdk.depositSol(amount, commitment);
|
|
146
|
+
console.log("Deposit transaction:", result.txHash);
|
|
147
|
+
|
|
148
|
+
// Stake SOL
|
|
149
|
+
await sdk.stakeSol(10_000_000_000n); // 10 SOL
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## React Hooks API
|
|
153
|
+
|
|
154
|
+
### Individual Hooks (Recommended for Code Splitting)
|
|
155
|
+
|
|
156
|
+
Each hook only loads what it needs, improving bundle size and page load performance.
|
|
157
|
+
|
|
158
|
+
#### `useDeposit`
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { useDeposit, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
162
|
+
|
|
163
|
+
const { deposit, isEVMReady, isSolanaReady } = useDeposit({
|
|
164
|
+
evm: {
|
|
165
|
+
factoryAddress: "0x...",
|
|
166
|
+
tokenAddress: "0x...", // Optional
|
|
167
|
+
},
|
|
168
|
+
solana: {
|
|
169
|
+
factoryProgramId: "...",
|
|
170
|
+
mixerProgramId: "...",
|
|
171
|
+
stakingProgramId: "...",
|
|
172
|
+
tokenMint: "...", // Optional
|
|
173
|
+
},
|
|
174
|
+
solanaWallet: wallet, // Optional
|
|
175
|
+
solanaConnection: connection, // Optional
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Deposit
|
|
179
|
+
await deposit(ChainType.EVM, amount, commitment);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### `useStake`
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { useStake, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
186
|
+
|
|
187
|
+
const { stake, unstake, isEVMReady } = useStake({
|
|
188
|
+
evm: {
|
|
189
|
+
factoryAddress: "0x...",
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Stake
|
|
194
|
+
await stake(ChainType.EVM, amount);
|
|
195
|
+
|
|
196
|
+
// Unstake
|
|
197
|
+
await unstake(ChainType.EVM);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### `useClaim`
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { useClaim, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
204
|
+
|
|
205
|
+
const { claim, getCurrentSeason, isEVMReady } = useClaim({
|
|
206
|
+
evm: {
|
|
207
|
+
factoryAddress: "0x...",
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Get current season and claim
|
|
212
|
+
const season = await getCurrentSeason(ChainType.EVM);
|
|
213
|
+
if (season) {
|
|
214
|
+
await claim(ChainType.EVM, season);
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### `useWithdraw`
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import {
|
|
222
|
+
useWithdraw,
|
|
223
|
+
ChainType,
|
|
224
|
+
AssetMode,
|
|
225
|
+
} from "@aintivirus-ai/mixer-sdk/hooks";
|
|
226
|
+
|
|
227
|
+
const { withdraw, isEVMReady } = useWithdraw({
|
|
228
|
+
evm: {
|
|
229
|
+
factoryAddress: "0x...",
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Withdraw
|
|
234
|
+
await withdraw(ChainType.EVM, proof, amount, AssetMode.ETH);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### `useView`
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { useView, ChainType, AssetMode } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
241
|
+
|
|
242
|
+
const {
|
|
243
|
+
getMixer,
|
|
244
|
+
mixerExists,
|
|
245
|
+
calculateDepositAmount,
|
|
246
|
+
getFeeRate,
|
|
247
|
+
getCurrentSeason,
|
|
248
|
+
getStakeSeason,
|
|
249
|
+
getStakerRecord,
|
|
250
|
+
hasClaimedEth,
|
|
251
|
+
getTokenBalance,
|
|
252
|
+
getEthBalance,
|
|
253
|
+
isEVMReady,
|
|
254
|
+
} = useView({
|
|
255
|
+
evm: {
|
|
256
|
+
factoryAddress: "0x...",
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Read contract data
|
|
261
|
+
const mixer = await getMixer(ChainType.EVM, AssetMode.ETH, amount);
|
|
262
|
+
const exists = await mixerExists(ChainType.EVM, AssetMode.ETH, amount);
|
|
263
|
+
const feeRate = await getFeeRate(ChainType.EVM);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### `useDeploy`
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import {
|
|
270
|
+
useDeploy,
|
|
271
|
+
ChainType,
|
|
272
|
+
AssetMode,
|
|
273
|
+
} from "@aintivirus-ai/mixer-sdk/hooks";
|
|
274
|
+
|
|
275
|
+
const { deployMixer, isEVMReady } = useDeploy({
|
|
276
|
+
evm: {
|
|
277
|
+
factoryAddress: "0x...",
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Deploy new mixer
|
|
282
|
+
const result = await deployMixer(ChainType.EVM, AssetMode.ETH, amount);
|
|
283
|
+
console.log("Mixer address:", result.mixerAddress);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### `useAdmin`
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { useAdmin, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
290
|
+
|
|
291
|
+
const {
|
|
292
|
+
setFeeRate,
|
|
293
|
+
setStakingSeasonPeriod,
|
|
294
|
+
startStakeSeason,
|
|
295
|
+
setVerifier,
|
|
296
|
+
setHasher,
|
|
297
|
+
isEVMReady,
|
|
298
|
+
} = useAdmin({
|
|
299
|
+
evm: {
|
|
300
|
+
factoryAddress: "0x...",
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Admin operations (requires OPERATOR_ROLE)
|
|
305
|
+
await setFeeRate(ChainType.EVM, BigInt(250)); // 0.25%
|
|
306
|
+
await setStakingSeasonPeriod(ChainType.EVM, BigInt(86400)); // 1 day
|
|
307
|
+
await startStakeSeason(ChainType.EVM);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### `useAintiVirus` (Unified Hook)
|
|
311
|
+
|
|
312
|
+
Use this hook when you need multiple functions on the same page:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { useAintiVirus, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
316
|
+
|
|
317
|
+
const {
|
|
318
|
+
deposit,
|
|
319
|
+
withdraw,
|
|
320
|
+
stake,
|
|
321
|
+
unstake,
|
|
322
|
+
claim,
|
|
323
|
+
getCurrentSeason,
|
|
324
|
+
getMixer,
|
|
325
|
+
mixerExists,
|
|
326
|
+
calculateDepositAmount,
|
|
327
|
+
isEVMReady,
|
|
328
|
+
isSolanaReady,
|
|
329
|
+
} = useAintiVirus({
|
|
330
|
+
evm: {
|
|
331
|
+
factoryAddress: "0x...",
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Code Splitting Benefits
|
|
337
|
+
|
|
338
|
+
Using individual hooks provides better code splitting:
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
// ✅ Good - Only loads deposit code
|
|
342
|
+
import { useDeposit } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
343
|
+
|
|
344
|
+
// ❌ Bad - Loads everything (deposit, withdraw, stake, claim, etc.)
|
|
345
|
+
import { useAintiVirus } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Benefits:**
|
|
349
|
+
|
|
350
|
+
- Smaller bundle size per page
|
|
351
|
+
- Faster page loads
|
|
352
|
+
- Better tree-shaking
|
|
353
|
+
- Cleaner code organization
|
|
354
|
+
|
|
355
|
+
## SDK Classes API Reference
|
|
356
|
+
|
|
357
|
+
### EVM SDK (`AintiVirusEVM`)
|
|
358
|
+
|
|
359
|
+
#### Constructor
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
new AintiVirusEVM(
|
|
363
|
+
factoryAddress: string,
|
|
364
|
+
tokenAddress: string,
|
|
365
|
+
signerOrProvider: Signer | Provider
|
|
366
|
+
)
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Methods
|
|
370
|
+
|
|
371
|
+
##### Deposits
|
|
372
|
+
|
|
373
|
+
- `depositEth(amount: bigint, commitment: bigint): Promise<TransactionResult>`
|
|
374
|
+
- `depositToken(amount: bigint, commitment: bigint): Promise<TransactionResult>`
|
|
375
|
+
|
|
376
|
+
##### Withdrawals
|
|
377
|
+
|
|
378
|
+
- `withdraw(proof: WithdrawalProof, amount: bigint, mode: AssetMode): Promise<TransactionResult>`
|
|
379
|
+
|
|
380
|
+
##### Staking
|
|
381
|
+
|
|
382
|
+
- `stakeEther(amount: bigint): Promise<TransactionResult>`
|
|
383
|
+
- `stakeToken(amount: bigint): Promise<TransactionResult>`
|
|
384
|
+
- `unstakeEth(): Promise<TransactionResult>`
|
|
385
|
+
- `unstakeToken(): Promise<TransactionResult>`
|
|
386
|
+
|
|
387
|
+
##### Rewards
|
|
388
|
+
|
|
389
|
+
- `claimEth(seasonId: bigint): Promise<TransactionResult>`
|
|
390
|
+
- `claimToken(seasonId: bigint): Promise<TransactionResult>`
|
|
391
|
+
|
|
392
|
+
##### View Functions
|
|
393
|
+
|
|
394
|
+
- `getMixer(mode: AssetMode, amount: bigint): Promise<string>`
|
|
395
|
+
- `mixerExists(mode: AssetMode, amount: bigint): Promise<boolean>`
|
|
396
|
+
- `calculateDepositAmount(amount: bigint): Promise<bigint>`
|
|
397
|
+
- `getFeeRate(): Promise<bigint>`
|
|
398
|
+
- `getCurrentStakeSeason(): Promise<bigint>`
|
|
399
|
+
- `getStakeSeason(seasonId: bigint): Promise<StakeSeason>`
|
|
400
|
+
- `getStakerRecord(address: string): Promise<StakerRecord>`
|
|
401
|
+
- `hasClaimedEth(address: string, seasonId: bigint): Promise<boolean>`
|
|
402
|
+
- `hasClaimedToken(address: string, seasonId: bigint): Promise<boolean>`
|
|
403
|
+
- `getTokenBalance(address: string): Promise<bigint>`
|
|
404
|
+
- `getEthBalance(address: string): Promise<bigint>`
|
|
405
|
+
- `getStakingAddress(): Promise<string>`
|
|
406
|
+
|
|
407
|
+
##### Deployment
|
|
408
|
+
|
|
409
|
+
- `deployMixer(mode: AssetMode, amount: bigint): Promise<TransactionResult & { mixerAddress: string }>`
|
|
410
|
+
|
|
411
|
+
### Solana SDK (`AintiVirusSolana`)
|
|
412
|
+
|
|
413
|
+
#### Constructor
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
new AintiVirusSolana(
|
|
417
|
+
factoryProgramId: string,
|
|
418
|
+
mixerProgramId: string,
|
|
419
|
+
stakingProgramId: string,
|
|
420
|
+
wallet: Wallet,
|
|
421
|
+
connection: Connection,
|
|
422
|
+
tokenMint?: string
|
|
423
|
+
)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
#### Methods
|
|
427
|
+
|
|
428
|
+
##### Deposits
|
|
429
|
+
|
|
430
|
+
- `depositSol(amount: bigint, commitment: bigint): Promise<TransactionResult>`
|
|
431
|
+
- `depositToken(amount: bigint, commitment: bigint): Promise<TransactionResult>`
|
|
432
|
+
|
|
433
|
+
##### Withdrawals
|
|
434
|
+
|
|
435
|
+
- `withdraw(instructionData: Buffer, nullifierHash: bigint, amount: bigint, mode: AssetMode): Promise<TransactionResult>`
|
|
436
|
+
|
|
437
|
+
##### Staking
|
|
438
|
+
|
|
439
|
+
- `stakeSol(amount: bigint): Promise<TransactionResult>`
|
|
440
|
+
- `stakeToken(amount: bigint): Promise<TransactionResult>`
|
|
441
|
+
- `unstakeSol(): Promise<TransactionResult>`
|
|
442
|
+
- `unstakeToken(): Promise<TransactionResult>`
|
|
443
|
+
|
|
444
|
+
##### Rewards
|
|
445
|
+
|
|
446
|
+
- `claimSol(seasonId: bigint): Promise<TransactionResult>`
|
|
447
|
+
- `claimToken(seasonId: bigint): Promise<TransactionResult>`
|
|
448
|
+
|
|
449
|
+
##### View Functions
|
|
450
|
+
|
|
451
|
+
- `getMixer(mode: AssetMode, amount: bigint): Promise<PublicKey>`
|
|
452
|
+
- `mixerExists(mode: AssetMode, amount: bigint): Promise<boolean>`
|
|
453
|
+
- `calculateDepositAmount(amount: bigint): Promise<bigint>`
|
|
454
|
+
- `getFeeRate(): Promise<bigint>`
|
|
455
|
+
- `getCurrentStakeSeason(): Promise<bigint>`
|
|
456
|
+
- `getStakeSeason(seasonId: bigint): Promise<StakeSeason>`
|
|
457
|
+
- `getStakerRecord(address: PublicKey): Promise<StakerRecord>`
|
|
458
|
+
- `hasClaimedSol(address: PublicKey, seasonId: bigint): Promise<boolean>`
|
|
459
|
+
- `hasClaimedToken(address: PublicKey, seasonId: bigint): Promise<boolean>`
|
|
460
|
+
- `getSolBalance(address: PublicKey): Promise<bigint>`
|
|
461
|
+
- `getTokenBalance(address: PublicKey): Promise<bigint>`
|
|
462
|
+
- `getStakingAddress(): Promise<PublicKey>`
|
|
463
|
+
|
|
464
|
+
##### Deployment
|
|
465
|
+
|
|
466
|
+
- `deployMixer(mode: AssetMode, amount: bigint): Promise<TransactionResult>`
|
|
467
|
+
|
|
468
|
+
##### Admin Functions
|
|
469
|
+
|
|
470
|
+
- `setFeeRate(feeRate: bigint): Promise<TransactionResult>`
|
|
471
|
+
- `setStakingSeasonPeriod(period: bigint): Promise<TransactionResult>`
|
|
472
|
+
- `startStakeSeason(): Promise<TransactionResult>`
|
|
473
|
+
- `setVerifier(verifierAddress: string): Promise<TransactionResult>`
|
|
474
|
+
- `setHasher(hasherAddress: string): Promise<TransactionResult>`
|
|
475
|
+
|
|
476
|
+
## Proof Generation
|
|
477
|
+
|
|
478
|
+
### Generating Deposit Data
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
import {
|
|
482
|
+
generateSecretAndNullifier,
|
|
483
|
+
computeCommitment,
|
|
484
|
+
} from "@aintivirus-ai/mixer-sdk";
|
|
485
|
+
|
|
486
|
+
// Generate secret and nullifier
|
|
487
|
+
const { secret, nullifier } = generateSecretAndNullifier();
|
|
488
|
+
|
|
489
|
+
// Compute commitment
|
|
490
|
+
const commitment = computeCommitment(secret, nullifier);
|
|
491
|
+
|
|
492
|
+
// Store these securely - you'll need them for withdrawal
|
|
493
|
+
// secret and nullifier should be kept private
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Generating Withdrawal Proof
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
import {
|
|
500
|
+
generateWithdrawalProofFromData,
|
|
501
|
+
buildMerkleTree,
|
|
502
|
+
getMerklePath,
|
|
503
|
+
} from "@aintivirus-ai/mixer-sdk";
|
|
504
|
+
import { readFileSync } from "fs";
|
|
505
|
+
|
|
506
|
+
// Load circuit files (from your build directory)
|
|
507
|
+
const circuitWasm = readFileSync("path/to/mixer.wasm");
|
|
508
|
+
const circuitZkey = readFileSync("path/to/mixer.zkey");
|
|
509
|
+
|
|
510
|
+
// Get all commitments from deposit events
|
|
511
|
+
const commitments = [
|
|
512
|
+
/* ... commitments from events ... */
|
|
513
|
+
];
|
|
514
|
+
|
|
515
|
+
// Build merkle tree
|
|
516
|
+
const tree = buildMerkleTree(commitments);
|
|
517
|
+
const root = BigInt(tree.root);
|
|
518
|
+
|
|
519
|
+
// Get merkle path for your commitment
|
|
520
|
+
const path = getMerklePath(tree, commitment);
|
|
521
|
+
|
|
522
|
+
// Generate proof
|
|
523
|
+
const proof = await generateWithdrawalProofFromData({
|
|
524
|
+
secret,
|
|
525
|
+
nullifier,
|
|
526
|
+
recipient: "0x...", // Recipient address
|
|
527
|
+
commitments,
|
|
528
|
+
circuitWasm,
|
|
529
|
+
circuitZkey,
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// Withdraw
|
|
533
|
+
await sdk.withdraw(proof, amount, AssetMode.ETH);
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## Staking & Rewards
|
|
537
|
+
|
|
538
|
+
### Staking Flow
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
// 1. Stake assets
|
|
542
|
+
await sdk.stakeEther(ethers.parseEther("10"));
|
|
543
|
+
|
|
544
|
+
// 2. Wait for season to end (or check current season)
|
|
545
|
+
const currentSeason = await sdk.getCurrentStakeSeason();
|
|
546
|
+
|
|
547
|
+
// 3. Check if you can claim
|
|
548
|
+
const hasClaimed = await sdk.hasClaimedEth(userAddress, currentSeason);
|
|
549
|
+
if (!hasClaimed) {
|
|
550
|
+
// 4. Claim rewards
|
|
551
|
+
await sdk.claimEth(currentSeason);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// 5. Unstake (optional)
|
|
555
|
+
await sdk.unstakeEth();
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Viewing Staking Information
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
// Get current season
|
|
562
|
+
const season = await sdk.getCurrentStakeSeason();
|
|
563
|
+
|
|
564
|
+
// Get season details
|
|
565
|
+
const seasonInfo = await sdk.getStakeSeason(season);
|
|
566
|
+
console.log("Total rewards:", seasonInfo.totalRewardEthAmount);
|
|
567
|
+
|
|
568
|
+
// Get your staking record
|
|
569
|
+
const record = await sdk.getStakerRecord(userAddress);
|
|
570
|
+
console.log("Staked amount:", record.stakedEthAmount);
|
|
571
|
+
console.log("Weight value:", record.ethWeightValue);
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
## Types
|
|
575
|
+
|
|
576
|
+
### AssetMode
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
enum AssetMode {
|
|
580
|
+
ETH = 0, // For EVM: ETH, For Solana: SOL
|
|
581
|
+
TOKEN = 1,
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### WithdrawalProof
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
interface WithdrawalProof {
|
|
589
|
+
pA: [bigint, bigint];
|
|
590
|
+
pB: [[bigint, bigint], [bigint, bigint]];
|
|
591
|
+
pC: [bigint, bigint];
|
|
592
|
+
pubSignals: [bigint, bigint, bigint];
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### TransactionResult
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
interface TransactionResult {
|
|
600
|
+
txHash: string;
|
|
601
|
+
blockNumber?: number;
|
|
602
|
+
blockTime?: number;
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
## Error Handling
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
try {
|
|
610
|
+
await sdk.depositEth(amount, commitment);
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (error.message.includes("Insufficient")) {
|
|
613
|
+
// Handle insufficient balance
|
|
614
|
+
} else if (error.message.includes("Mixer not deployed")) {
|
|
615
|
+
// Handle mixer not found
|
|
616
|
+
} else {
|
|
617
|
+
// Handle other errors
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
## Best Practices
|
|
623
|
+
|
|
624
|
+
1. **Store Secrets Securely**: Always store `secret` and `nullifier` securely. You'll need them for withdrawals.
|
|
625
|
+
|
|
626
|
+
2. **Check Mixer Existence**: Before depositing, check if the mixer exists:
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
const exists = await sdk.mixerExists(AssetMode.ETH, amount);
|
|
630
|
+
if (!exists) {
|
|
631
|
+
throw new Error("Mixer not deployed for this amount");
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
3. **Calculate Fees**: Always calculate the total amount including fees:
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
const totalAmount = await sdk.calculateDepositAmount(amount);
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
4. **Handle Approvals**: For token deposits/staking, ensure you approve the factory contract:
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
const allowance = await token.allowance(userAddress, factoryAddress);
|
|
645
|
+
if (allowance < amount) {
|
|
646
|
+
await token.approve(factoryAddress, amount);
|
|
647
|
+
}
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
5. **Monitor Transactions**: Always wait for transaction confirmations:
|
|
651
|
+
```typescript
|
|
652
|
+
const result = await sdk.depositEth(amount, commitment);
|
|
653
|
+
await provider.waitForTransaction(result.txHash);
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## Examples
|
|
657
|
+
|
|
658
|
+
Complete example implementations are available in the `examples/` directory:
|
|
659
|
+
|
|
660
|
+
- **`deposit-page.tsx`** - Deposit page using `useDeposit` hook
|
|
661
|
+
- **`stake-page.tsx`** - Staking page using `useStake` hook
|
|
662
|
+
- **`view-functions-page.tsx`** - View functions page using `useView` hook
|
|
663
|
+
- **`admin-page.tsx`** - Admin panel using `useAdmin` hook
|
|
664
|
+
- **`deploy-mixer-page.tsx`** - Deploy mixer page using `useDeploy` hook
|
|
665
|
+
|
|
666
|
+
Each example demonstrates:
|
|
667
|
+
|
|
668
|
+
- Proper hook usage
|
|
669
|
+
- Error handling
|
|
670
|
+
- Loading states
|
|
671
|
+
- Transaction status display
|
|
672
|
+
|
|
673
|
+
## Next.js Integration
|
|
674
|
+
|
|
675
|
+
The hooks are optimized for Next.js with `wagmi` for EVM interactions. See the examples directory for complete Next.js integration patterns.
|
|
676
|
+
|
|
677
|
+
### Setup
|
|
678
|
+
|
|
679
|
+
1. Install dependencies:
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
npm install @aintivirus-ai/mixer-sdk wagmi viem @tanstack/react-query
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
2. Configure wagmi in your Next.js app (see examples for full setup)
|
|
686
|
+
|
|
687
|
+
3. Use hooks in your components:
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
import { useDeposit, ChainType } from "@aintivirus-ai/mixer-sdk/hooks";
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
## Development
|
|
694
|
+
|
|
695
|
+
### Building
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
npm run build
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### TypeScript
|
|
702
|
+
|
|
703
|
+
The SDK is written in TypeScript and includes full type definitions. Make sure your project has TypeScript configured.
|
|
704
|
+
|
|
705
|
+
## License
|
|
706
|
+
|
|
707
|
+
MIT
|
|
708
|
+
|
|
709
|
+
## Support
|
|
710
|
+
|
|
711
|
+
For issues, questions, or contributions, please refer to the project repository.
|