pctestupgrade2 1.1.8

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.
Files changed (66) hide show
  1. package/.github/workflows/npm-publish.yml +55 -0
  2. package/README.md +31 -0
  3. package/__tests__/e2e.test.ts +56 -0
  4. package/__tests__/e2espl.test.ts +73 -0
  5. package/__tests__/encryption.test.ts +1635 -0
  6. package/circuit2/transaction2.wasm +0 -0
  7. package/circuit2/transaction2.zkey +0 -0
  8. package/dist/config.d.ts +9 -0
  9. package/dist/config.js +12 -0
  10. package/dist/deposit.d.ts +19 -0
  11. package/dist/deposit.js +396 -0
  12. package/dist/depositSPL.d.ts +21 -0
  13. package/dist/depositSPL.js +452 -0
  14. package/dist/exportUtils.d.ts +10 -0
  15. package/dist/exportUtils.js +10 -0
  16. package/dist/getUtxos.d.ts +29 -0
  17. package/dist/getUtxos.js +294 -0
  18. package/dist/getUtxosSPL.d.ts +33 -0
  19. package/dist/getUtxosSPL.js +395 -0
  20. package/dist/index.d.ts +128 -0
  21. package/dist/index.js +305 -0
  22. package/dist/models/keypair.d.ts +26 -0
  23. package/dist/models/keypair.js +43 -0
  24. package/dist/models/utxo.d.ts +49 -0
  25. package/dist/models/utxo.js +85 -0
  26. package/dist/utils/address_lookup_table.d.ts +9 -0
  27. package/dist/utils/address_lookup_table.js +45 -0
  28. package/dist/utils/constants.d.ts +27 -0
  29. package/dist/utils/constants.js +56 -0
  30. package/dist/utils/encryption.d.ts +107 -0
  31. package/dist/utils/encryption.js +376 -0
  32. package/dist/utils/logger.d.ts +9 -0
  33. package/dist/utils/logger.js +35 -0
  34. package/dist/utils/merkle_tree.d.ts +92 -0
  35. package/dist/utils/merkle_tree.js +186 -0
  36. package/dist/utils/node-shim.d.ts +5 -0
  37. package/dist/utils/node-shim.js +5 -0
  38. package/dist/utils/prover.d.ts +36 -0
  39. package/dist/utils/prover.js +147 -0
  40. package/dist/utils/utils.d.ts +64 -0
  41. package/dist/utils/utils.js +165 -0
  42. package/dist/withdraw.d.ts +22 -0
  43. package/dist/withdraw.js +272 -0
  44. package/dist/withdrawSPL.d.ts +24 -0
  45. package/dist/withdrawSPL.js +308 -0
  46. package/package.json +51 -0
  47. package/src/config.ts +22 -0
  48. package/src/deposit.ts +493 -0
  49. package/src/depositSPL.ts +575 -0
  50. package/src/exportUtils.ts +12 -0
  51. package/src/getUtxos.ts +396 -0
  52. package/src/getUtxosSPL.ts +528 -0
  53. package/src/index.ts +356 -0
  54. package/src/models/keypair.ts +52 -0
  55. package/src/models/utxo.ts +106 -0
  56. package/src/utils/address_lookup_table.ts +78 -0
  57. package/src/utils/constants.ts +77 -0
  58. package/src/utils/encryption.ts +464 -0
  59. package/src/utils/logger.ts +42 -0
  60. package/src/utils/merkle_tree.ts +207 -0
  61. package/src/utils/node-shim.ts +6 -0
  62. package/src/utils/prover.ts +222 -0
  63. package/src/utils/utils.ts +222 -0
  64. package/src/withdraw.ts +335 -0
  65. package/src/withdrawSPL.ts +399 -0
  66. package/tsconfig.json +28 -0
package/dist/index.js ADDED
@@ -0,0 +1,305 @@
1
+ import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
2
+ import { deposit } from './deposit.js';
3
+ import { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
4
+ import { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
5
+ import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, tokens, USDC_MINT } from './utils/constants.js';
6
+ import { logger, setLogger } from './utils/logger.js';
7
+ import { EncryptionService } from './utils/encryption.js';
8
+ import { WasmFactory } from '@lightprotocol/hasher.rs';
9
+ import bs58 from 'bs58';
10
+ import { withdraw } from './withdraw.js';
11
+ import { LocalStorage } from "node-localstorage";
12
+ import path from 'node:path';
13
+ import { depositSPL } from './depositSPL.js';
14
+ import { withdrawSPL } from './withdrawSPL.js';
15
+ import { getAssociatedTokenAddress } from '@solana/spl-token';
16
+ let storage = new LocalStorage(path.join(process.cwd(), "cache"));
17
+ export class PrivacyCash {
18
+ connection;
19
+ publicKey;
20
+ encryptionService;
21
+ keypair;
22
+ isRuning = false;
23
+ status = '';
24
+ constructor({ RPC_url, owner, enableDebug }) {
25
+ let keypair = getSolanaKeypair(owner);
26
+ if (!keypair) {
27
+ throw new Error('param "owner" is not a valid Private Key or Keypair');
28
+ }
29
+ this.keypair = keypair;
30
+ this.connection = new Connection(RPC_url, 'confirmed');
31
+ this.publicKey = keypair.publicKey;
32
+ this.encryptionService = new EncryptionService();
33
+ this.encryptionService.deriveEncryptionKeyFromWallet(this.keypair);
34
+ if (!enableDebug) {
35
+ this.startStatusRender();
36
+ this.setLogger((level, message) => {
37
+ if (level == 'info') {
38
+ this.status = message;
39
+ }
40
+ else if (level == 'error') {
41
+ console.log('error message: ', message);
42
+ }
43
+ });
44
+ }
45
+ }
46
+ setLogger(loger) {
47
+ setLogger(loger);
48
+ return this;
49
+ }
50
+ /**
51
+ * Clears the cache of utxos.
52
+ *
53
+ * By default, downloaded utxos will be cached in the local storage. Thus the next time when you makes another
54
+ * deposit or withdraw or getPrivateBalance, the SDK only fetches the utxos that are not in the cache.
55
+ *
56
+ * This method clears the cache of utxos.
57
+ */
58
+ async clearCache() {
59
+ if (!this.publicKey) {
60
+ return this;
61
+ }
62
+ storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(this.publicKey));
63
+ storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(this.publicKey));
64
+ // spl
65
+ for (let token of tokens) {
66
+ let ata = await getAssociatedTokenAddress(token.pubkey, this.publicKey);
67
+ storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(ata));
68
+ storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(ata));
69
+ }
70
+ return this;
71
+ }
72
+ /**
73
+ * Deposit SOL to the Privacy Cash.
74
+ *
75
+ * Lamports is the amount of SOL in lamports. e.g. if you want to deposit 0.01 SOL (10000000 lamports), call deposit({ lamports: 10000000 })
76
+ */
77
+ async deposit({ lamports }) {
78
+ this.isRuning = true;
79
+ logger.info('start depositting');
80
+ let lightWasm = await WasmFactory.getInstance();
81
+ let res = await deposit({
82
+ lightWasm,
83
+ amount_in_lamports: lamports,
84
+ connection: this.connection,
85
+ encryptionService: this.encryptionService,
86
+ publicKey: this.publicKey,
87
+ transactionSigner: async (tx) => {
88
+ tx.sign([this.keypair]);
89
+ return tx;
90
+ },
91
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
92
+ storage
93
+ });
94
+ this.isRuning = false;
95
+ return res;
96
+ }
97
+ /**
98
+ * Deposit USDC to the Privacy Cash.
99
+ */
100
+ async depositUSDC({ base_units }) {
101
+ this.isRuning = true;
102
+ logger.info('start depositting');
103
+ let lightWasm = await WasmFactory.getInstance();
104
+ let res = await depositSPL({
105
+ mintAddress: USDC_MINT,
106
+ lightWasm,
107
+ base_units: base_units,
108
+ connection: this.connection,
109
+ encryptionService: this.encryptionService,
110
+ publicKey: this.publicKey,
111
+ transactionSigner: async (tx) => {
112
+ tx.sign([this.keypair]);
113
+ return tx;
114
+ },
115
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
116
+ storage
117
+ });
118
+ this.isRuning = false;
119
+ return res;
120
+ }
121
+ /**
122
+ * Withdraw SOL from the Privacy Cash.
123
+ *
124
+ * Lamports is the amount of SOL in lamports. e.g. if you want to withdraw 0.01 SOL (10000000 lamports), call withdraw({ lamports: 10000000 })
125
+ */
126
+ async withdraw({ lamports, recipientAddress, referrer }) {
127
+ this.isRuning = true;
128
+ logger.info('start withdrawing');
129
+ let lightWasm = await WasmFactory.getInstance();
130
+ let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey;
131
+ let res = await withdraw({
132
+ lightWasm,
133
+ amount_in_lamports: lamports,
134
+ connection: this.connection,
135
+ encryptionService: this.encryptionService,
136
+ publicKey: this.publicKey,
137
+ recipient,
138
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
139
+ storage,
140
+ referrer
141
+ });
142
+ logger.debug(`Withdraw successful. Recipient ${recipient} received ${res.amount_in_lamports / LAMPORTS_PER_SOL} SOL, with ${res.fee_in_lamports / LAMPORTS_PER_SOL} SOL relayers fees`);
143
+ this.isRuning = false;
144
+ return res;
145
+ }
146
+ /**
147
+ * Withdraw USDC from the Privacy Cash.
148
+ *
149
+ * base_units is the amount of USDC in base unit. e.g. if you want to withdraw 1 USDC (1,000,000 base unit), call withdraw({ base_units: 1000000, recipientAddress: 'some_address' })
150
+ */
151
+ async withdrawUSDC({ base_units, recipientAddress, referrer }) {
152
+ this.isRuning = true;
153
+ logger.info('start withdrawing');
154
+ let lightWasm = await WasmFactory.getInstance();
155
+ let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey;
156
+ let res = await withdrawSPL({
157
+ mintAddress: USDC_MINT,
158
+ lightWasm,
159
+ base_units,
160
+ connection: this.connection,
161
+ encryptionService: this.encryptionService,
162
+ publicKey: this.publicKey,
163
+ recipient,
164
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
165
+ storage,
166
+ referrer
167
+ });
168
+ logger.debug(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`);
169
+ this.isRuning = false;
170
+ return res;
171
+ }
172
+ /**
173
+ * Returns the amount of lamports current wallet has in Privacy Cash.
174
+ */
175
+ async getPrivateBalance(abortSignal) {
176
+ logger.info('getting private balance');
177
+ this.isRuning = true;
178
+ let utxos = await getUtxos({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, abortSignal });
179
+ this.isRuning = false;
180
+ return getBalanceFromUtxos(utxos);
181
+ }
182
+ /**
183
+ * Returns the amount of base unites current wallet has in Privacy Cash.
184
+ */
185
+ async getPrivateBalanceUSDC() {
186
+ logger.info('getting private balance');
187
+ this.isRuning = true;
188
+ let utxos = await getUtxosSPL({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, mintAddress: USDC_MINT });
189
+ this.isRuning = false;
190
+ return getBalanceFromUtxosSPL(utxos);
191
+ }
192
+ /**
193
+ * Returns the amount of base unites current wallet has in Privacy Cash.
194
+ */
195
+ async getPrivateBalanceSpl(mintAddress) {
196
+ this.isRuning = true;
197
+ let utxos = await getUtxosSPL({
198
+ publicKey: this.publicKey,
199
+ connection: this.connection,
200
+ encryptionService: this.encryptionService,
201
+ storage,
202
+ mintAddress
203
+ });
204
+ this.isRuning = false;
205
+ return getBalanceFromUtxosSPL(utxos);
206
+ }
207
+ /**
208
+ * Returns true if the code is running in a browser.
209
+ */
210
+ isBrowser() {
211
+ return typeof window !== "undefined";
212
+ }
213
+ async startStatusRender() {
214
+ let frames = ['-', '\\', '|', '/'];
215
+ let i = 0;
216
+ while (true) {
217
+ if (this.isRuning) {
218
+ let k = i % frames.length;
219
+ i++;
220
+ stdWrite(this.status, frames[k]);
221
+ }
222
+ await new Promise(r => setTimeout(r, 250));
223
+ }
224
+ }
225
+ /**
226
+ * Deposit SPL to the Privacy Cash.
227
+ */
228
+ async depositSPL({ base_units, mintAddress, amount }) {
229
+ this.isRuning = true;
230
+ logger.info('start depositting');
231
+ let lightWasm = await WasmFactory.getInstance();
232
+ let res = await depositSPL({
233
+ lightWasm,
234
+ base_units,
235
+ amount,
236
+ connection: this.connection,
237
+ encryptionService: this.encryptionService,
238
+ publicKey: this.publicKey,
239
+ transactionSigner: async (tx) => {
240
+ tx.sign([this.keypair]);
241
+ return tx;
242
+ },
243
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
244
+ storage,
245
+ mintAddress
246
+ });
247
+ this.isRuning = false;
248
+ return res;
249
+ }
250
+ /**
251
+ * Withdraw SPL from the Privacy Cash.
252
+ */
253
+ async withdrawSPL({ base_units, mintAddress, recipientAddress, amount, referrer }) {
254
+ this.isRuning = true;
255
+ logger.info('start withdrawing');
256
+ let lightWasm = await WasmFactory.getInstance();
257
+ let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey;
258
+ let res = await withdrawSPL({
259
+ lightWasm,
260
+ base_units,
261
+ amount,
262
+ connection: this.connection,
263
+ encryptionService: this.encryptionService,
264
+ publicKey: this.publicKey,
265
+ recipient,
266
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
267
+ storage,
268
+ mintAddress,
269
+ referrer
270
+ });
271
+ logger.debug(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`);
272
+ this.isRuning = false;
273
+ return res;
274
+ }
275
+ }
276
+ function getSolanaKeypair(secret) {
277
+ try {
278
+ if (secret instanceof Keypair) {
279
+ return secret;
280
+ }
281
+ let keyArray;
282
+ if (typeof secret === "string") {
283
+ keyArray = bs58.decode(secret);
284
+ }
285
+ else if (secret instanceof Uint8Array) {
286
+ keyArray = secret;
287
+ }
288
+ else {
289
+ // number[]
290
+ keyArray = Uint8Array.from(secret);
291
+ }
292
+ if (keyArray.length !== 32 && keyArray.length !== 64) {
293
+ return null;
294
+ }
295
+ return Keypair.fromSecretKey(keyArray);
296
+ }
297
+ catch {
298
+ return null;
299
+ }
300
+ }
301
+ function stdWrite(status, frame) {
302
+ let blue = "\x1b[34m";
303
+ let reset = "\x1b[0m";
304
+ process.stdout.write(`${frame}status: ${blue}${status}${reset}\r`);
305
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Keypair module for ZK Cash
3
+ *
4
+ * Provides cryptographic keypair functionality for the ZK Cash system
5
+ * Based on: https://github.com/tornadocash/tornado-nova
6
+ */
7
+ import BN from 'bn.js';
8
+ import * as hasher from '@lightprotocol/hasher.rs';
9
+ /**
10
+ * Simplified version of Keypair
11
+ */
12
+ export declare class Keypair {
13
+ privkey: BN;
14
+ pubkey: BN;
15
+ private lightWasm;
16
+ constructor(privkeyHex: string, lightWasm: hasher.LightWasm);
17
+ /**
18
+ * Sign a message using keypair private key
19
+ *
20
+ * @param {string|number|BigNumber} commitment a hex string with commitment
21
+ * @param {string|number|BigNumber} merklePath a hex string with merkle path
22
+ * @returns {BigNumber} a hex string with signature
23
+ */
24
+ sign(commitment: string, merklePath: string): string;
25
+ static generateNew(lightWasm: hasher.LightWasm): Promise<Keypair>;
26
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Keypair module for ZK Cash
3
+ *
4
+ * Provides cryptographic keypair functionality for the ZK Cash system
5
+ * Based on: https://github.com/tornadocash/tornado-nova
6
+ */
7
+ import BN from 'bn.js';
8
+ import { ethers } from 'ethers';
9
+ // Field size constant
10
+ const FIELD_SIZE = new BN('21888242871839275222246405745257275088548364400416034343698204186575808495617');
11
+ /**
12
+ * Simplified version of Keypair
13
+ */
14
+ export class Keypair {
15
+ privkey;
16
+ pubkey;
17
+ lightWasm;
18
+ constructor(privkeyHex, lightWasm) {
19
+ const rawDecimal = BigInt(privkeyHex);
20
+ this.privkey = new BN((rawDecimal % BigInt(FIELD_SIZE.toString())).toString());
21
+ this.lightWasm = lightWasm;
22
+ // TODO: lazily compute pubkey
23
+ this.pubkey = new BN(this.lightWasm.poseidonHashString([this.privkey.toString()]));
24
+ }
25
+ /**
26
+ * Sign a message using keypair private key
27
+ *
28
+ * @param {string|number|BigNumber} commitment a hex string with commitment
29
+ * @param {string|number|BigNumber} merklePath a hex string with merkle path
30
+ * @returns {BigNumber} a hex string with signature
31
+ */
32
+ sign(commitment, merklePath) {
33
+ return this.lightWasm.poseidonHashString([this.privkey.toString(), commitment, merklePath]);
34
+ }
35
+ static async generateNew(lightWasm) {
36
+ // Tornado Cash Nova uses ethers.js to generate a random private key
37
+ // We can't generate Solana keypairs because it won't fit in the field size
38
+ // It's OK to use ethereum secret keys, because the secret key is only used for the proof generation.
39
+ // Namely, it's used to guarantee the uniqueness of the nullifier.
40
+ const wallet = ethers.Wallet.createRandom();
41
+ return new Keypair(wallet.privateKey, lightWasm);
42
+ }
43
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * UTXO (Unspent Transaction Output) module for ZK Cash
3
+ *
4
+ * Provides UTXO functionality for the ZK Cash system
5
+ * Based on: https://github.com/tornadocash/tornado-nova
6
+ */
7
+ import BN from 'bn.js';
8
+ import { Keypair } from './keypair.js';
9
+ import * as hasher from '@lightprotocol/hasher.rs';
10
+ /**
11
+ * Simplified Utxo class inspired by Tornado Cash Nova
12
+ * Based on: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/utxo.js
13
+ */
14
+ export declare class Utxo {
15
+ amount: BN;
16
+ blinding: BN;
17
+ keypair: Keypair;
18
+ index: number;
19
+ mintAddress: string;
20
+ version: 'v1' | 'v2';
21
+ private lightWasm;
22
+ constructor({ lightWasm, amount,
23
+ /**
24
+ * Tornado nova doesn't use solana eddsa with curve 25519 but their own "keypair"
25
+ * which is:
26
+ * - private key: random [31;u8]
27
+ * - public key: PoseidonHash(privateKey)
28
+ *
29
+ * Generate a new keypair for each UTXO
30
+ */
31
+ keypair, blinding, // Use fixed value for consistency instead of randomBN()
32
+ index, mintAddress, // Default to Solana native SOL mint address,
33
+ version }: {
34
+ lightWasm: hasher.LightWasm;
35
+ amount?: BN | number | string;
36
+ keypair?: Keypair;
37
+ blinding?: BN | number | string;
38
+ index?: number;
39
+ mintAddress?: string;
40
+ version?: 'v1' | 'v2';
41
+ });
42
+ getCommitment(): Promise<string>;
43
+ getNullifier(): Promise<string>;
44
+ /**
45
+ * Log all the UTXO's public properties and derived values in JSON format
46
+ * @returns Promise that resolves once all logging is complete
47
+ */
48
+ log(): Promise<void>;
49
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * UTXO (Unspent Transaction Output) module for ZK Cash
3
+ *
4
+ * Provides UTXO functionality for the ZK Cash system
5
+ * Based on: https://github.com/tornadocash/tornado-nova
6
+ */
7
+ import BN from 'bn.js';
8
+ import { Keypair } from './keypair.js';
9
+ import { ethers } from 'ethers';
10
+ import { getMintAddressField } from '../utils/utils.js';
11
+ import { PublicKey } from '@solana/web3.js';
12
+ /**
13
+ * Simplified Utxo class inspired by Tornado Cash Nova
14
+ * Based on: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/utxo.js
15
+ */
16
+ export class Utxo {
17
+ amount;
18
+ blinding;
19
+ keypair;
20
+ index;
21
+ mintAddress;
22
+ version;
23
+ lightWasm;
24
+ constructor({ lightWasm, amount = new BN(0),
25
+ /**
26
+ * Tornado nova doesn't use solana eddsa with curve 25519 but their own "keypair"
27
+ * which is:
28
+ * - private key: random [31;u8]
29
+ * - public key: PoseidonHash(privateKey)
30
+ *
31
+ * Generate a new keypair for each UTXO
32
+ */
33
+ keypair, blinding = new BN(Math.floor(Math.random() * 1000000000)), // Use fixed value for consistency instead of randomBN()
34
+ index = 0, mintAddress = '11111111111111111111111111111112', // Default to Solana native SOL mint address,
35
+ version = 'v2' }) {
36
+ this.amount = new BN(amount.toString());
37
+ this.blinding = new BN(blinding.toString());
38
+ this.lightWasm = lightWasm;
39
+ this.keypair = keypair || new Keypair(ethers.Wallet.createRandom().privateKey, lightWasm);
40
+ this.index = index;
41
+ this.mintAddress = mintAddress;
42
+ this.version = version;
43
+ }
44
+ async getCommitment() {
45
+ // return this.lightWasm.poseidonHashString([this.amount.toString(), this.keypair.pubkey.toString(), this.blinding.toString(), this.mintAddress]);
46
+ const mintAddressField = getMintAddressField(new PublicKey(this.mintAddress));
47
+ return this.lightWasm.poseidonHashString([
48
+ this.amount.toString(),
49
+ this.keypair.pubkey.toString(),
50
+ this.blinding.toString(),
51
+ mintAddressField
52
+ ]);
53
+ }
54
+ async getNullifier() {
55
+ const commitmentValue = await this.getCommitment();
56
+ const signature = this.keypair.sign(commitmentValue, new BN(this.index).toString());
57
+ return this.lightWasm.poseidonHashString([commitmentValue, new BN(this.index).toString(), signature]);
58
+ }
59
+ /**
60
+ * Log all the UTXO's public properties and derived values in JSON format
61
+ * @returns Promise that resolves once all logging is complete
62
+ */
63
+ async log() {
64
+ // Prepare the UTXO data object
65
+ const utxoData = {
66
+ amount: this.amount.toString(),
67
+ blinding: this.blinding.toString(),
68
+ index: this.index,
69
+ mintAddress: this.mintAddress,
70
+ keypair: {
71
+ pubkey: this.keypair.pubkey.toString()
72
+ }
73
+ };
74
+ // Add derived values
75
+ try {
76
+ utxoData.commitment = await this.getCommitment();
77
+ utxoData.nullifier = await this.getNullifier();
78
+ }
79
+ catch (error) {
80
+ utxoData.error = error.message;
81
+ }
82
+ // Output as formatted JSON
83
+ console.log(JSON.stringify(utxoData, null, 2));
84
+ }
85
+ }
@@ -0,0 +1,9 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ /**
3
+ * Helper function to use an existing ALT (recommended for production)
4
+ * Use create_alt.ts to create the ALT once, then hardcode the address and use this function
5
+ */
6
+ export declare function useExistingALT(connection: Connection, altAddress: PublicKey): Promise<{
7
+ value: any;
8
+ } | null>;
9
+ export declare function getProtocolAddressesWithMint(programId: PublicKey, authority: PublicKey, treeAta: PublicKey, feeRecipient: PublicKey, feeRecipientAta: PublicKey): PublicKey[];
@@ -0,0 +1,45 @@
1
+ import { PublicKey, SystemProgram, ComputeBudgetProgram } from '@solana/web3.js';
2
+ import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
3
+ import { logger } from './logger.js';
4
+ /**
5
+ * Helper function to use an existing ALT (recommended for production)
6
+ * Use create_alt.ts to create the ALT once, then hardcode the address and use this function
7
+ */
8
+ export async function useExistingALT(connection, altAddress) {
9
+ try {
10
+ logger.debug(`Using existing ALT: ${altAddress.toString()}`);
11
+ const altAccount = await connection.getAddressLookupTable(altAddress);
12
+ if (altAccount.value) {
13
+ logger.debug(`✅ ALT found with ${altAccount.value.state.addresses.length} addresses`);
14
+ }
15
+ else {
16
+ logger.error('❌ ALT not found');
17
+ }
18
+ return altAccount;
19
+ }
20
+ catch (error) {
21
+ console.error('Error getting existing ALT:', error);
22
+ return null;
23
+ }
24
+ }
25
+ export function getProtocolAddressesWithMint(programId, authority, treeAta, feeRecipient, feeRecipientAta) {
26
+ // Derive global config PDA
27
+ const [globalConfigAccount] = PublicKey.findProgramAddressSync([Buffer.from('global_config')], programId);
28
+ // Derive tree accounts
29
+ const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree')], programId);
30
+ return [
31
+ // Core program accounts (constant)
32
+ programId,
33
+ treeAccount,
34
+ treeAta,
35
+ globalConfigAccount,
36
+ authority,
37
+ feeRecipient,
38
+ feeRecipientAta,
39
+ // System programs (constant)
40
+ SystemProgram.programId,
41
+ ComputeBudgetProgram.programId,
42
+ ASSOCIATED_TOKEN_PROGRAM_ID,
43
+ TOKEN_PROGRAM_ID,
44
+ ];
45
+ }
@@ -0,0 +1,27 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import BN from 'bn.js';
3
+ export declare const FIELD_SIZE: BN;
4
+ export declare const PROGRAM_ID: PublicKey;
5
+ export declare const FEE_RECIPIENT: PublicKey;
6
+ export declare const FETCH_UTXOS_GROUP_SIZE = 20000;
7
+ export declare const TRANSACT_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
8
+ export declare const TRANSACT_SPL_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
9
+ export declare const MERKLE_TREE_DEPTH = 26;
10
+ export declare const ALT_ADDRESS: PublicKey;
11
+ export declare const RELAYER_API_URL: string;
12
+ export declare const SIGN_MESSAGE = "Privacy Money account sign in";
13
+ export declare const LSK_FETCH_OFFSET = "fetch_offset";
14
+ export declare const LSK_ENCRYPTED_OUTPUTS = "encrypted_outputs";
15
+ export declare const USDC_MINT: PublicKey;
16
+ declare const tokenList: readonly ["sol", "usdc", "usdt", "zec", "ore", "store"];
17
+ export type TokenList = typeof tokenList[number];
18
+ declare const splList: readonly ["usdc", "usdt", "zec", "ore", "store"];
19
+ export type SplList = typeof splList[number];
20
+ export type Token = {
21
+ name: TokenList;
22
+ prefix: string;
23
+ units_per_token: number;
24
+ pubkey: PublicKey;
25
+ };
26
+ export declare const tokens: Token[];
27
+ export {};
@@ -0,0 +1,56 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import BN from 'bn.js';
3
+ export const FIELD_SIZE = new BN('21888242871839275222246405745257275088548364400416034343698204186575808495617');
4
+ export const PROGRAM_ID = process.env.NEXT_PUBLIC_PROGRAM_ID ? new PublicKey(process.env.NEXT_PUBLIC_PROGRAM_ID) : new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
5
+ export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
6
+ export const FETCH_UTXOS_GROUP_SIZE = 20_000;
7
+ export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
8
+ export const TRANSACT_SPL_IX_DISCRIMINATOR = Buffer.from([154, 66, 244, 204, 78, 225, 163, 151]);
9
+ export const MERKLE_TREE_DEPTH = 26;
10
+ export const ALT_ADDRESS = process.env.NEXT_PUBLIC_ALT_ADDRESS ? new PublicKey(process.env.NEXT_PUBLIC_ALT_ADDRESS) : new PublicKey('HEN49U2ySJ85Vc78qprSW9y6mFDhs1NczRxyppNHjofe');
11
+ export const RELAYER_API_URL = process.env.NEXT_PUBLIC_RELAYER_API_URL ?? 'https://api3.privacycash.org';
12
+ export const SIGN_MESSAGE = `Privacy Money account sign in`;
13
+ // localStorage cache keys
14
+ export const LSK_FETCH_OFFSET = 'fetch_offset';
15
+ export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs';
16
+ export const USDC_MINT = process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
17
+ const tokenList = ['sol', 'usdc', 'usdt', 'zec', 'ore', 'store'];
18
+ const splList = ['usdc', 'usdt', 'zec', 'ore', 'store'];
19
+ export const tokens = [
20
+ {
21
+ name: 'sol',
22
+ pubkey: new PublicKey('So11111111111111111111111111111111111111112'),
23
+ prefix: '',
24
+ units_per_token: 1e9
25
+ },
26
+ {
27
+ name: 'usdc',
28
+ pubkey: process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
29
+ prefix: 'usdc_',
30
+ units_per_token: 1e6
31
+ },
32
+ {
33
+ name: 'usdt',
34
+ pubkey: process.env.NEXT_PUBLIC_USDT_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDT_MINT) : new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'),
35
+ prefix: 'usdt_',
36
+ units_per_token: 1e6
37
+ },
38
+ {
39
+ name: 'zec',
40
+ pubkey: process.env.NEXT_PUBLIC_ZEC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ZEC_MINT) : new PublicKey('A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS'),
41
+ prefix: 'zec_',
42
+ units_per_token: 1e8
43
+ },
44
+ {
45
+ name: 'ore',
46
+ pubkey: process.env.NEXT_PUBLIC_ORE_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ORE_MINT) : new PublicKey('oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp'),
47
+ prefix: 'ore_',
48
+ units_per_token: 1e11
49
+ },
50
+ {
51
+ name: 'store',
52
+ pubkey: process.env.NEXT_PUBLIC_STORE_MINT ? new PublicKey(process.env.NEXT_PUBLIC_STORE_MINT) : new PublicKey('sTorERYB6xAZ1SSbwpK3zoK2EEwbBrc7TZAzg1uCGiH'),
53
+ prefix: 'store_',
54
+ units_per_token: 1e11
55
+ },
56
+ ];