@hula-privacy/mixer 0.1.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 +290 -0
- package/package.json +52 -0
- package/src/api.ts +276 -0
- package/src/constants.ts +108 -0
- package/src/crypto.ts +293 -0
- package/src/index.ts +185 -0
- package/src/merkle.ts +220 -0
- package/src/proof.ts +251 -0
- package/src/transaction.ts +464 -0
- package/src/types.ts +331 -0
- package/src/utxo.ts +358 -0
- package/src/wallet.ts +475 -0
package/src/constants.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for Hula Privacy Protocol
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { PublicKey } from "@solana/web3.js";
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Program Constants
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/** Hula Privacy Program ID */
|
|
12
|
+
export const PROGRAM_ID = new PublicKey("tnJ9AAxNau3BRBTe7NzXpv8DeYyiogvGd8YPnCiuarA");
|
|
13
|
+
|
|
14
|
+
/** Token 2022 Program ID */
|
|
15
|
+
export const TOKEN_2022_PROGRAM_ID = new PublicKey(
|
|
16
|
+
"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// PDA Seeds
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
export const POOL_SEED = Buffer.from("hula_pool");
|
|
24
|
+
export const VAULT_SEED = Buffer.from("vault");
|
|
25
|
+
export const MERKLE_TREE_SEED = Buffer.from("merkle_tree");
|
|
26
|
+
export const NULLIFIER_SEED = Buffer.from("nullifier");
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Circuit Parameters
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
/** Number of input UTXOs in circuit */
|
|
33
|
+
export const NUM_INPUT_UTXOS = 2;
|
|
34
|
+
|
|
35
|
+
/** Number of output UTXOs in circuit */
|
|
36
|
+
export const NUM_OUTPUT_UTXOS = 2;
|
|
37
|
+
|
|
38
|
+
/** Depth of merkle tree */
|
|
39
|
+
export const MERKLE_TREE_DEPTH = 10;
|
|
40
|
+
|
|
41
|
+
/** Maximum leaves per tree (2^DEPTH) */
|
|
42
|
+
export const MAX_LEAVES = 1 << MERKLE_TREE_DEPTH;
|
|
43
|
+
|
|
44
|
+
/** Size of proof in bytes */
|
|
45
|
+
export const PROOF_SIZE = 256;
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Domain Separators (matching circuits/keys.circom)
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export const DOMAIN_OWNER = 0n;
|
|
52
|
+
export const DOMAIN_VIEWING = 1n;
|
|
53
|
+
export const DOMAIN_NULLIFIER = 2n;
|
|
54
|
+
export const DOMAIN_ENCRYPTION = 3n;
|
|
55
|
+
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Crypto Constants
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
60
|
+
/** BN254 field prime */
|
|
61
|
+
export const FIELD_PRIME = BigInt(
|
|
62
|
+
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// PDA Derivation Functions
|
|
67
|
+
// ============================================================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Derive Pool PDA
|
|
71
|
+
*/
|
|
72
|
+
export function getPoolPDA(): [PublicKey, number] {
|
|
73
|
+
return PublicKey.findProgramAddressSync([POOL_SEED], PROGRAM_ID);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Derive Merkle Tree PDA for a specific tree index
|
|
78
|
+
*/
|
|
79
|
+
export function getMerkleTreePDA(treeIndex: number = 0): [PublicKey, number] {
|
|
80
|
+
const treeIndexBuffer = Buffer.alloc(4);
|
|
81
|
+
treeIndexBuffer.writeUInt32LE(treeIndex, 0);
|
|
82
|
+
return PublicKey.findProgramAddressSync(
|
|
83
|
+
[MERKLE_TREE_SEED, treeIndexBuffer],
|
|
84
|
+
PROGRAM_ID
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Derive Vault PDA for a specific mint
|
|
90
|
+
*/
|
|
91
|
+
export function getVaultPDA(mint: PublicKey): [PublicKey, number] {
|
|
92
|
+
return PublicKey.findProgramAddressSync(
|
|
93
|
+
[VAULT_SEED, mint.toBytes()],
|
|
94
|
+
PROGRAM_ID
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Derive Nullifier PDA for a nullifier hash
|
|
100
|
+
*/
|
|
101
|
+
export function getNullifierPDA(nullifier: Uint8Array): [PublicKey, number] {
|
|
102
|
+
return PublicKey.findProgramAddressSync(
|
|
103
|
+
[NULLIFIER_SEED, nullifier],
|
|
104
|
+
PROGRAM_ID
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
package/src/crypto.ts
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic utilities for Hula Privacy Protocol
|
|
3
|
+
*
|
|
4
|
+
* Includes Poseidon hashing, key derivation, and encryption
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { buildPoseidon, type Poseidon } from "circomlibjs";
|
|
8
|
+
import * as nacl from "tweetnacl";
|
|
9
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
10
|
+
import {
|
|
11
|
+
DOMAIN_OWNER,
|
|
12
|
+
DOMAIN_VIEWING,
|
|
13
|
+
DOMAIN_NULLIFIER,
|
|
14
|
+
DOMAIN_ENCRYPTION,
|
|
15
|
+
FIELD_PRIME,
|
|
16
|
+
} from "./constants";
|
|
17
|
+
import type { WalletKeys, EncryptedNote } from "./types";
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Poseidon Hasher
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
let poseidonInstance: Poseidon | null = null;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Initialize Poseidon hasher (must be called once before using hash functions)
|
|
27
|
+
*/
|
|
28
|
+
export async function initPoseidon(): Promise<void> {
|
|
29
|
+
if (!poseidonInstance) {
|
|
30
|
+
poseidonInstance = await buildPoseidon();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if Poseidon is initialized
|
|
36
|
+
*/
|
|
37
|
+
export function isPoseidonInitialized(): boolean {
|
|
38
|
+
return poseidonInstance !== null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get Poseidon instance (throws if not initialized)
|
|
43
|
+
*/
|
|
44
|
+
export function getPoseidon(): Poseidon {
|
|
45
|
+
if (!poseidonInstance) {
|
|
46
|
+
throw new Error("Poseidon not initialized. Call initPoseidon() first.");
|
|
47
|
+
}
|
|
48
|
+
return poseidonInstance;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Poseidon hash of inputs
|
|
53
|
+
*/
|
|
54
|
+
export function poseidonHash(inputs: bigint[]): bigint {
|
|
55
|
+
const poseidon = getPoseidon();
|
|
56
|
+
const hash = poseidon(inputs.map(x => poseidon.F.e(x)));
|
|
57
|
+
return poseidon.F.toObject(hash);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Byte Conversion Utilities
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Convert bytes to bigint (big-endian)
|
|
66
|
+
*/
|
|
67
|
+
export function bytesToBigInt(bytes: Uint8Array): bigint {
|
|
68
|
+
let result = 0n;
|
|
69
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
70
|
+
result = (result << 8n) + BigInt(bytes[i]);
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Convert bigint to bytes (big-endian)
|
|
77
|
+
*/
|
|
78
|
+
export function bigIntToBytes(value: bigint, length: number): Uint8Array {
|
|
79
|
+
const bytes = new Uint8Array(length);
|
|
80
|
+
let v = value;
|
|
81
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
82
|
+
bytes[i] = Number(v & 0xffn);
|
|
83
|
+
v >>= 8n;
|
|
84
|
+
}
|
|
85
|
+
return bytes;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Convert bigint to 32-byte array (big-endian)
|
|
90
|
+
*/
|
|
91
|
+
export function bigIntToBytes32(value: bigint): Uint8Array {
|
|
92
|
+
return bigIntToBytes(value, 32);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Convert hex string to bytes
|
|
97
|
+
*/
|
|
98
|
+
export function hexToBytes(hex: string): Uint8Array {
|
|
99
|
+
const cleaned = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
100
|
+
const bytes = new Uint8Array(cleaned.length / 2);
|
|
101
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
102
|
+
bytes[i] = parseInt(cleaned.substr(i * 2, 2), 16);
|
|
103
|
+
}
|
|
104
|
+
return bytes;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Convert bytes to hex string
|
|
109
|
+
*/
|
|
110
|
+
export function bytesToHex(bytes: Uint8Array): string {
|
|
111
|
+
return Array.from(bytes)
|
|
112
|
+
.map(b => b.toString(16).padStart(2, "0"))
|
|
113
|
+
.join("");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Convert PublicKey to bigint
|
|
118
|
+
*/
|
|
119
|
+
export function pubkeyToBigInt(pubkey: { toBytes(): Uint8Array }): bigint {
|
|
120
|
+
return bytesToBigInt(pubkey.toBytes());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// Key Generation & Derivation
|
|
125
|
+
// ============================================================================
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate a new random spending key
|
|
129
|
+
*/
|
|
130
|
+
export function generateSpendingKey(): bigint {
|
|
131
|
+
const randomBytes = nacl.randomBytes(32);
|
|
132
|
+
return bytesToBigInt(randomBytes) % (2n ** 253n);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Derive all wallet keys from spending key
|
|
137
|
+
*/
|
|
138
|
+
export function deriveKeys(spendingKey: bigint): WalletKeys {
|
|
139
|
+
const owner = poseidonHash([spendingKey, DOMAIN_OWNER]);
|
|
140
|
+
const viewingKey = poseidonHash([spendingKey, DOMAIN_VIEWING]);
|
|
141
|
+
const nullifierKey = poseidonHash([spendingKey, DOMAIN_NULLIFIER]);
|
|
142
|
+
const encryptionSeed = poseidonHash([spendingKey, DOMAIN_ENCRYPTION]);
|
|
143
|
+
|
|
144
|
+
// Derive X25519 keypair from encryption seed
|
|
145
|
+
const seedBytes = bigIntToBytes(encryptionSeed, 32);
|
|
146
|
+
const hashedSeed = sha256(seedBytes);
|
|
147
|
+
const encryptionKeyPair = nacl.box.keyPair.fromSecretKey(hashedSeed);
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
spendingKey,
|
|
151
|
+
owner,
|
|
152
|
+
viewingKey,
|
|
153
|
+
nullifierKey,
|
|
154
|
+
encryptionKeyPair,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Derive spending key from wallet signature
|
|
160
|
+
*
|
|
161
|
+
* This allows deterministic key derivation from a Solana wallet signature,
|
|
162
|
+
* enabling wallet recovery as long as the user has access to their wallet.
|
|
163
|
+
*/
|
|
164
|
+
export function deriveSpendingKeyFromSignature(signature: Uint8Array): bigint {
|
|
165
|
+
if (signature.length < 64) {
|
|
166
|
+
throw new Error("Signature must be at least 64 bytes");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Use SHA-256 of the signature to derive the spending key
|
|
170
|
+
const hash = sha256(signature);
|
|
171
|
+
return bytesToBigInt(hash) % FIELD_PRIME;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// Note Encryption
|
|
176
|
+
// ============================================================================
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Encrypt a note for a recipient
|
|
180
|
+
*
|
|
181
|
+
* The note contains the UTXO data needed for the recipient to claim it.
|
|
182
|
+
*/
|
|
183
|
+
export function encryptNote(
|
|
184
|
+
noteData: {
|
|
185
|
+
value: bigint;
|
|
186
|
+
mintTokenAddress: bigint;
|
|
187
|
+
secret: bigint;
|
|
188
|
+
leafIndex: number;
|
|
189
|
+
},
|
|
190
|
+
recipientEncryptionPubKey: Uint8Array
|
|
191
|
+
): EncryptedNote {
|
|
192
|
+
const payload = {
|
|
193
|
+
value: noteData.value.toString(),
|
|
194
|
+
mintTokenAddress: noteData.mintTokenAddress.toString(),
|
|
195
|
+
secret: noteData.secret.toString(),
|
|
196
|
+
leafIndex: noteData.leafIndex,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const message = new TextEncoder().encode(JSON.stringify(payload));
|
|
200
|
+
const nonce = nacl.randomBytes(24);
|
|
201
|
+
const ephemeralKeyPair = nacl.box.keyPair();
|
|
202
|
+
|
|
203
|
+
const ciphertext = nacl.box(
|
|
204
|
+
message,
|
|
205
|
+
nonce,
|
|
206
|
+
recipientEncryptionPubKey,
|
|
207
|
+
ephemeralKeyPair.secretKey
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
ephemeralPubKey: ephemeralKeyPair.publicKey,
|
|
212
|
+
ciphertext,
|
|
213
|
+
nonce,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Decrypt an encrypted note
|
|
219
|
+
*
|
|
220
|
+
* Returns null if decryption fails (not intended for this recipient)
|
|
221
|
+
*/
|
|
222
|
+
export function decryptNote(
|
|
223
|
+
encryptedNote: EncryptedNote,
|
|
224
|
+
encryptionSecretKey: Uint8Array
|
|
225
|
+
): { value: bigint; mintTokenAddress: bigint; secret: bigint; leafIndex: number } | null {
|
|
226
|
+
try {
|
|
227
|
+
const decrypted = nacl.box.open(
|
|
228
|
+
encryptedNote.ciphertext,
|
|
229
|
+
encryptedNote.nonce,
|
|
230
|
+
encryptedNote.ephemeralPubKey,
|
|
231
|
+
encryptionSecretKey
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (!decrypted) return null;
|
|
235
|
+
|
|
236
|
+
const noteData = JSON.parse(new TextDecoder().decode(decrypted));
|
|
237
|
+
return {
|
|
238
|
+
value: BigInt(noteData.value),
|
|
239
|
+
mintTokenAddress: BigInt(noteData.mintTokenAddress),
|
|
240
|
+
secret: BigInt(noteData.secret),
|
|
241
|
+
leafIndex: noteData.leafIndex,
|
|
242
|
+
};
|
|
243
|
+
} catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Serialize encrypted note for on-chain storage
|
|
250
|
+
*/
|
|
251
|
+
export function serializeEncryptedNote(note: EncryptedNote): Uint8Array {
|
|
252
|
+
const totalLength = 32 + 24 + 2 + note.ciphertext.length;
|
|
253
|
+
const buffer = new Uint8Array(totalLength);
|
|
254
|
+
|
|
255
|
+
buffer.set(note.ephemeralPubKey, 0);
|
|
256
|
+
buffer.set(note.nonce, 32);
|
|
257
|
+
|
|
258
|
+
// Ciphertext length (2 bytes, big-endian)
|
|
259
|
+
buffer[56] = (note.ciphertext.length >> 8) & 0xff;
|
|
260
|
+
buffer[57] = note.ciphertext.length & 0xff;
|
|
261
|
+
|
|
262
|
+
buffer.set(note.ciphertext, 58);
|
|
263
|
+
|
|
264
|
+
return buffer;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Deserialize encrypted note from on-chain data
|
|
269
|
+
*/
|
|
270
|
+
export function deserializeEncryptedNote(data: Uint8Array): EncryptedNote {
|
|
271
|
+
const ephemeralPubKey = data.slice(0, 32);
|
|
272
|
+
const nonce = data.slice(32, 56);
|
|
273
|
+
const ciphertextLength = (data[56] << 8) | data[57];
|
|
274
|
+
const ciphertext = data.slice(58, 58 + ciphertextLength);
|
|
275
|
+
|
|
276
|
+
return { ephemeralPubKey, nonce, ciphertext };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ============================================================================
|
|
280
|
+
// Formatting Utilities
|
|
281
|
+
// ============================================================================
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Format a commitment/nullifier for display (truncated hex)
|
|
285
|
+
*/
|
|
286
|
+
export function formatCommitment(value: bigint | Uint8Array, length: number = 16): string {
|
|
287
|
+
if (value instanceof Uint8Array) {
|
|
288
|
+
return `0x${bytesToHex(value).slice(0, length)}...`;
|
|
289
|
+
}
|
|
290
|
+
return `0x${value.toString(16).padStart(64, "0").slice(0, length)}...`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hula Privacy SDK
|
|
3
|
+
*
|
|
4
|
+
* Complete toolkit for privacy transactions on Solana.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { HulaWallet, initHulaSDK } from '@hula/sdk';
|
|
9
|
+
*
|
|
10
|
+
* // Initialize SDK
|
|
11
|
+
* await initHulaSDK();
|
|
12
|
+
*
|
|
13
|
+
* // Create wallet from Phantom signature
|
|
14
|
+
* const signature = await phantom.signMessage(getKeyDerivationMessage());
|
|
15
|
+
* const wallet = await HulaWallet.fromSignature(signature, {
|
|
16
|
+
* rpcUrl: 'https://api.devnet.solana.com',
|
|
17
|
+
* relayerUrl: 'https://relayer.hulaprivacy.io',
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Sync wallet to find your UTXOs
|
|
21
|
+
* await wallet.sync();
|
|
22
|
+
*
|
|
23
|
+
* // Check balance
|
|
24
|
+
* const balance = wallet.getBalance(mintAddress);
|
|
25
|
+
* console.log('Private balance:', balance);
|
|
26
|
+
*
|
|
27
|
+
* // Deposit tokens
|
|
28
|
+
* const depositTx = await wallet.deposit(mintAddress, 1000000n);
|
|
29
|
+
*
|
|
30
|
+
* // Transfer privately
|
|
31
|
+
* const transferTx = await wallet.transfer(
|
|
32
|
+
* mintAddress,
|
|
33
|
+
* 500000n,
|
|
34
|
+
* recipientOwnerHash,
|
|
35
|
+
* recipientEncryptionPubKey
|
|
36
|
+
* );
|
|
37
|
+
*
|
|
38
|
+
* // Withdraw to public address
|
|
39
|
+
* const withdrawTx = await wallet.withdraw(
|
|
40
|
+
* mintAddress,
|
|
41
|
+
* 200000n,
|
|
42
|
+
* recipientPublicKey
|
|
43
|
+
* );
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Main Exports
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
// Wallet
|
|
52
|
+
export { HulaWallet, initHulaSDK, getKeyDerivationMessage } from "./wallet";
|
|
53
|
+
|
|
54
|
+
// Relayer API
|
|
55
|
+
export { RelayerClient, getRelayerClient, setDefaultRelayerUrl } from "./api";
|
|
56
|
+
|
|
57
|
+
// Crypto
|
|
58
|
+
export {
|
|
59
|
+
initPoseidon,
|
|
60
|
+
isPoseidonInitialized,
|
|
61
|
+
getPoseidon,
|
|
62
|
+
poseidonHash,
|
|
63
|
+
deriveKeys,
|
|
64
|
+
generateSpendingKey,
|
|
65
|
+
deriveSpendingKeyFromSignature,
|
|
66
|
+
encryptNote,
|
|
67
|
+
decryptNote,
|
|
68
|
+
serializeEncryptedNote,
|
|
69
|
+
deserializeEncryptedNote,
|
|
70
|
+
bytesToBigInt,
|
|
71
|
+
bigIntToBytes,
|
|
72
|
+
bigIntToBytes32,
|
|
73
|
+
bytesToHex,
|
|
74
|
+
hexToBytes,
|
|
75
|
+
pubkeyToBigInt,
|
|
76
|
+
formatCommitment,
|
|
77
|
+
} from "./crypto";
|
|
78
|
+
|
|
79
|
+
// UTXO
|
|
80
|
+
export {
|
|
81
|
+
computeCommitment,
|
|
82
|
+
computeNullifier,
|
|
83
|
+
computeNullifierFromKeys,
|
|
84
|
+
createUTXO,
|
|
85
|
+
createDummyUTXO,
|
|
86
|
+
serializeUTXO,
|
|
87
|
+
deserializeUTXO,
|
|
88
|
+
scanNotesForUTXOs,
|
|
89
|
+
syncUTXOs,
|
|
90
|
+
selectUTXOs,
|
|
91
|
+
calculateBalance,
|
|
92
|
+
} from "./utxo";
|
|
93
|
+
|
|
94
|
+
// Merkle
|
|
95
|
+
export {
|
|
96
|
+
computeZeros,
|
|
97
|
+
getZeroAtLevel,
|
|
98
|
+
getEmptyTreeRoot,
|
|
99
|
+
computeMerklePathFromLeaves,
|
|
100
|
+
computeMerkleRoot,
|
|
101
|
+
verifyMerklePath,
|
|
102
|
+
fetchMerklePath,
|
|
103
|
+
fetchMerkleRoot,
|
|
104
|
+
getNextLeafIndex,
|
|
105
|
+
getCurrentTreeIndex,
|
|
106
|
+
} from "./merkle";
|
|
107
|
+
|
|
108
|
+
// Proof
|
|
109
|
+
export {
|
|
110
|
+
setCircuitPaths,
|
|
111
|
+
getCircuitPaths,
|
|
112
|
+
verifyCircuitFiles,
|
|
113
|
+
parseProof,
|
|
114
|
+
generateProof,
|
|
115
|
+
generateProofInMemory,
|
|
116
|
+
} from "./proof";
|
|
117
|
+
|
|
118
|
+
// Transaction
|
|
119
|
+
export {
|
|
120
|
+
buildTransaction,
|
|
121
|
+
buildTransactionAccounts,
|
|
122
|
+
toAnchorPublicInputs,
|
|
123
|
+
} from "./transaction";
|
|
124
|
+
|
|
125
|
+
// Constants
|
|
126
|
+
export {
|
|
127
|
+
PROGRAM_ID,
|
|
128
|
+
TOKEN_2022_PROGRAM_ID,
|
|
129
|
+
POOL_SEED,
|
|
130
|
+
VAULT_SEED,
|
|
131
|
+
MERKLE_TREE_SEED,
|
|
132
|
+
NULLIFIER_SEED,
|
|
133
|
+
NUM_INPUT_UTXOS,
|
|
134
|
+
NUM_OUTPUT_UTXOS,
|
|
135
|
+
MERKLE_TREE_DEPTH,
|
|
136
|
+
MAX_LEAVES,
|
|
137
|
+
PROOF_SIZE,
|
|
138
|
+
DOMAIN_OWNER,
|
|
139
|
+
DOMAIN_VIEWING,
|
|
140
|
+
DOMAIN_NULLIFIER,
|
|
141
|
+
DOMAIN_ENCRYPTION,
|
|
142
|
+
FIELD_PRIME,
|
|
143
|
+
getPoolPDA,
|
|
144
|
+
getMerkleTreePDA,
|
|
145
|
+
getVaultPDA,
|
|
146
|
+
getNullifierPDA,
|
|
147
|
+
} from "./constants";
|
|
148
|
+
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Type Exports
|
|
151
|
+
// ============================================================================
|
|
152
|
+
|
|
153
|
+
export type {
|
|
154
|
+
// Core types
|
|
155
|
+
UTXO,
|
|
156
|
+
SerializableUTXO,
|
|
157
|
+
WalletKeys,
|
|
158
|
+
EncryptedNote,
|
|
159
|
+
|
|
160
|
+
// Merkle types
|
|
161
|
+
MerklePath,
|
|
162
|
+
LeafData,
|
|
163
|
+
|
|
164
|
+
// Transaction types
|
|
165
|
+
CircuitInputs,
|
|
166
|
+
PublicInputs,
|
|
167
|
+
OutputSpec,
|
|
168
|
+
TransactionRequest,
|
|
169
|
+
BuiltTransaction,
|
|
170
|
+
|
|
171
|
+
// API types
|
|
172
|
+
PaginatedResponse,
|
|
173
|
+
PoolData,
|
|
174
|
+
TreeData,
|
|
175
|
+
TransactionData,
|
|
176
|
+
NoteData,
|
|
177
|
+
StatsData,
|
|
178
|
+
|
|
179
|
+
// Config types
|
|
180
|
+
HulaSDKConfig,
|
|
181
|
+
SyncProgress,
|
|
182
|
+
SyncResult,
|
|
183
|
+
} from "./types";
|
|
184
|
+
|
|
185
|
+
|