privacycash 1.0.6

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 (56) hide show
  1. package/.github/workflows/npm-publish.yml +67 -0
  2. package/README.md +22 -0
  3. package/__tests__/e2e.test.ts +52 -0
  4. package/__tests__/encryption.test.ts +1635 -0
  5. package/circuit2/transaction2.wasm +0 -0
  6. package/circuit2/transaction2.zkey +0 -0
  7. package/dist/config.d.ts +7 -0
  8. package/dist/config.js +16 -0
  9. package/dist/deposit.d.ts +18 -0
  10. package/dist/deposit.js +402 -0
  11. package/dist/exportUtils.d.ts +6 -0
  12. package/dist/exportUtils.js +6 -0
  13. package/dist/getUtxos.d.ts +27 -0
  14. package/dist/getUtxos.js +352 -0
  15. package/dist/index.d.ts +61 -0
  16. package/dist/index.js +169 -0
  17. package/dist/models/keypair.d.ts +26 -0
  18. package/dist/models/keypair.js +43 -0
  19. package/dist/models/utxo.d.ts +49 -0
  20. package/dist/models/utxo.js +76 -0
  21. package/dist/utils/address_lookup_table.d.ts +8 -0
  22. package/dist/utils/address_lookup_table.js +21 -0
  23. package/dist/utils/constants.d.ts +14 -0
  24. package/dist/utils/constants.js +15 -0
  25. package/dist/utils/encryption.d.ts +107 -0
  26. package/dist/utils/encryption.js +374 -0
  27. package/dist/utils/logger.d.ts +9 -0
  28. package/dist/utils/logger.js +35 -0
  29. package/dist/utils/merkle_tree.d.ts +92 -0
  30. package/dist/utils/merkle_tree.js +186 -0
  31. package/dist/utils/node-shim.d.ts +5 -0
  32. package/dist/utils/node-shim.js +5 -0
  33. package/dist/utils/prover.d.ts +33 -0
  34. package/dist/utils/prover.js +123 -0
  35. package/dist/utils/utils.d.ts +67 -0
  36. package/dist/utils/utils.js +151 -0
  37. package/dist/withdraw.d.ts +21 -0
  38. package/dist/withdraw.js +270 -0
  39. package/package.json +48 -0
  40. package/src/config.ts +28 -0
  41. package/src/deposit.ts +496 -0
  42. package/src/exportUtils.ts +6 -0
  43. package/src/getUtxos.ts +466 -0
  44. package/src/index.ts +191 -0
  45. package/src/models/keypair.ts +52 -0
  46. package/src/models/utxo.ts +97 -0
  47. package/src/utils/address_lookup_table.ts +29 -0
  48. package/src/utils/constants.ts +26 -0
  49. package/src/utils/encryption.ts +461 -0
  50. package/src/utils/logger.ts +42 -0
  51. package/src/utils/merkle_tree.ts +207 -0
  52. package/src/utils/node-shim.ts +6 -0
  53. package/src/utils/prover.ts +189 -0
  54. package/src/utils/utils.ts +213 -0
  55. package/src/withdraw.ts +334 -0
  56. package/tsconfig.json +28 -0
@@ -0,0 +1,35 @@
1
+ const defaultLogger = (level, message) => {
2
+ const prefix = `[${level.toUpperCase()}]`;
3
+ console.log(prefix, message);
4
+ };
5
+ let userLogger = defaultLogger;
6
+ export function setLogger(logger) {
7
+ userLogger = logger;
8
+ }
9
+ function argToStr(args) {
10
+ return args.map(arg => {
11
+ if (typeof arg === "object" && arg !== null) {
12
+ try {
13
+ return JSON.stringify(arg);
14
+ }
15
+ catch {
16
+ return String(arg);
17
+ }
18
+ }
19
+ return String(arg);
20
+ }).join(" ");
21
+ }
22
+ export const logger = {
23
+ debug: (...args) => {
24
+ userLogger('debug', argToStr(args));
25
+ },
26
+ info: (...args) => {
27
+ userLogger('info', argToStr(args));
28
+ },
29
+ warn: (...args) => {
30
+ userLogger('warn', argToStr(args));
31
+ },
32
+ error: (...args) => {
33
+ userLogger('error', argToStr(args));
34
+ },
35
+ };
@@ -0,0 +1,92 @@
1
+ import * as hasher from '@lightprotocol/hasher.rs';
2
+ export declare const DEFAULT_ZERO = 0;
3
+ /**
4
+ * @callback hashFunction
5
+ * @param left Left leaf
6
+ * @param right Right leaf
7
+ */
8
+ /**
9
+ * Merkle tree
10
+ */
11
+ export declare class MerkleTree {
12
+ /**
13
+ * Constructor
14
+ * @param {number} levels Number of levels in the tree
15
+ * @param {Array} [elements] Initial elements
16
+ * @param {Object} options
17
+ * @param {hashFunction} [options.hashFunction] Function used to hash 2 leaves
18
+ * @param [options.zeroElement] Value for non-existent leaves
19
+ */
20
+ levels: number;
21
+ capacity: number;
22
+ zeroElement: string;
23
+ _zeros: string[];
24
+ _layers: string[][];
25
+ _lightWasm: hasher.LightWasm;
26
+ constructor(levels: number, lightWasm: hasher.LightWasm, elements?: string[], { zeroElement }?: {
27
+ zeroElement?: number | undefined;
28
+ });
29
+ _rebuild(): void;
30
+ /**
31
+ * Get tree root
32
+ * @returns {*}
33
+ */
34
+ root(): string;
35
+ /**
36
+ * Insert new element into the tree
37
+ * @param element Element to insert
38
+ */
39
+ insert(element: string): void;
40
+ /**
41
+ * Insert multiple elements into the tree. Tree will be fully rebuilt during this operation.
42
+ * @param {Array} elements Elements to insert
43
+ */
44
+ bulkInsert(elements: string[]): void;
45
+ /**
46
+ * Change an element in the tree
47
+ * @param {number} index Index of element to change
48
+ * @param element Updated element value
49
+ */
50
+ update(index: number, element: string): void;
51
+ /**
52
+ * Get merkle path to a leaf
53
+ * @param {number} index Leaf index to generate path for
54
+ * @returns {{pathElements: number[], pathIndex: number[]}} An object containing adjacent elements and left-right index
55
+ */
56
+ path(index: number): {
57
+ pathElements: string[];
58
+ pathIndices: number[];
59
+ };
60
+ /**
61
+ * Find an element in the tree
62
+ * @param element An element to find
63
+ * @param comparator A function that checks leaf value equality
64
+ * @returns {number} Index if element is found, otherwise -1
65
+ */
66
+ indexOf(element: string, comparator?: Function | null): number;
67
+ /**
68
+ * Returns a copy of non-zero tree elements
69
+ * @returns {Object[]}
70
+ */
71
+ elements(): string[];
72
+ /**
73
+ * Serialize entire tree state including intermediate layers into a plain object
74
+ * Deserializing it back will not require to recompute any hashes
75
+ * Elements are not converted to a plain type, this is responsibility of the caller
76
+ */
77
+ serialize(): {
78
+ levels: number;
79
+ _zeros: string[];
80
+ _layers: string[][];
81
+ };
82
+ /**
83
+ * Deserialize data into a MerkleTree instance
84
+ * Make sure to provide the same hashFunction as was used in the source tree,
85
+ * otherwise the tree state will be invalid
86
+ *
87
+ * @param data
88
+ * @param hashFunction
89
+ * @returns {MerkleTree}
90
+ */
91
+ static deserialize(data: any, hashFunction: Function): any;
92
+ }
@@ -0,0 +1,186 @@
1
+ export const DEFAULT_ZERO = 0;
2
+ /**
3
+ * @callback hashFunction
4
+ * @param left Left leaf
5
+ * @param right Right leaf
6
+ */
7
+ /**
8
+ * Merkle tree
9
+ */
10
+ export class MerkleTree {
11
+ /**
12
+ * Constructor
13
+ * @param {number} levels Number of levels in the tree
14
+ * @param {Array} [elements] Initial elements
15
+ * @param {Object} options
16
+ * @param {hashFunction} [options.hashFunction] Function used to hash 2 leaves
17
+ * @param [options.zeroElement] Value for non-existent leaves
18
+ */
19
+ levels;
20
+ capacity;
21
+ zeroElement;
22
+ _zeros;
23
+ _layers;
24
+ _lightWasm;
25
+ constructor(levels, lightWasm, elements = [], { zeroElement = DEFAULT_ZERO } = {}) {
26
+ this.levels = levels;
27
+ this.capacity = 2 ** levels;
28
+ this.zeroElement = zeroElement.toString();
29
+ this._lightWasm = lightWasm;
30
+ if (elements.length > this.capacity) {
31
+ throw new Error("Tree is full");
32
+ }
33
+ this._zeros = [];
34
+ this._layers = [];
35
+ this._layers[0] = elements;
36
+ this._zeros[0] = this.zeroElement;
37
+ for (let i = 1; i <= levels; i++) {
38
+ this._zeros[i] = this._lightWasm.poseidonHashString([
39
+ this._zeros[i - 1],
40
+ this._zeros[i - 1],
41
+ ]);
42
+ }
43
+ this._rebuild();
44
+ }
45
+ _rebuild() {
46
+ for (let level = 1; level <= this.levels; level++) {
47
+ this._layers[level] = [];
48
+ for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) {
49
+ this._layers[level][i] = this._lightWasm.poseidonHashString([
50
+ this._layers[level - 1][i * 2],
51
+ i * 2 + 1 < this._layers[level - 1].length
52
+ ? this._layers[level - 1][i * 2 + 1]
53
+ : this._zeros[level - 1],
54
+ ]);
55
+ }
56
+ }
57
+ }
58
+ /**
59
+ * Get tree root
60
+ * @returns {*}
61
+ */
62
+ root() {
63
+ return this._layers[this.levels].length > 0
64
+ ? this._layers[this.levels][0]
65
+ : this._zeros[this.levels];
66
+ }
67
+ /**
68
+ * Insert new element into the tree
69
+ * @param element Element to insert
70
+ */
71
+ insert(element) {
72
+ if (this._layers[0].length >= this.capacity) {
73
+ throw new Error("Tree is full");
74
+ }
75
+ this.update(this._layers[0].length, element);
76
+ }
77
+ /**
78
+ * Insert multiple elements into the tree. Tree will be fully rebuilt during this operation.
79
+ * @param {Array} elements Elements to insert
80
+ */
81
+ bulkInsert(elements) {
82
+ if (this._layers[0].length + elements.length > this.capacity) {
83
+ throw new Error("Tree is full");
84
+ }
85
+ this._layers[0].push(...elements);
86
+ this._rebuild();
87
+ }
88
+ // TODO: update does not work debug
89
+ /**
90
+ * Change an element in the tree
91
+ * @param {number} index Index of element to change
92
+ * @param element Updated element value
93
+ */
94
+ update(index, element) {
95
+ // index 0 and 1 and element is the commitment hash
96
+ if (isNaN(Number(index)) ||
97
+ index < 0 ||
98
+ index > this._layers[0].length ||
99
+ index >= this.capacity) {
100
+ throw new Error("Insert index out of bounds: " + index);
101
+ }
102
+ this._layers[0][index] = element;
103
+ for (let level = 1; level <= this.levels; level++) {
104
+ index >>= 1;
105
+ this._layers[level][index] = this._lightWasm.poseidonHashString([
106
+ this._layers[level - 1][index * 2],
107
+ index * 2 + 1 < this._layers[level - 1].length
108
+ ? this._layers[level - 1][index * 2 + 1]
109
+ : this._zeros[level - 1],
110
+ ]);
111
+ }
112
+ }
113
+ /**
114
+ * Get merkle path to a leaf
115
+ * @param {number} index Leaf index to generate path for
116
+ * @returns {{pathElements: number[], pathIndex: number[]}} An object containing adjacent elements and left-right index
117
+ */
118
+ path(index) {
119
+ if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
120
+ throw new Error("Index out of bounds: " + index);
121
+ }
122
+ const pathElements = [];
123
+ const pathIndices = [];
124
+ for (let level = 0; level < this.levels; level++) {
125
+ pathIndices[level] = index % 2;
126
+ pathElements[level] =
127
+ (index ^ 1) < this._layers[level].length
128
+ ? this._layers[level][index ^ 1]
129
+ : this._zeros[level];
130
+ index >>= 1;
131
+ }
132
+ return {
133
+ pathElements,
134
+ pathIndices,
135
+ };
136
+ }
137
+ /**
138
+ * Find an element in the tree
139
+ * @param element An element to find
140
+ * @param comparator A function that checks leaf value equality
141
+ * @returns {number} Index if element is found, otherwise -1
142
+ */
143
+ indexOf(element, comparator = null) {
144
+ if (comparator) {
145
+ return this._layers[0].findIndex((el) => comparator(element, el));
146
+ }
147
+ else {
148
+ return this._layers[0].indexOf(element);
149
+ }
150
+ }
151
+ /**
152
+ * Returns a copy of non-zero tree elements
153
+ * @returns {Object[]}
154
+ */
155
+ elements() {
156
+ return this._layers[0].slice();
157
+ }
158
+ /**
159
+ * Serialize entire tree state including intermediate layers into a plain object
160
+ * Deserializing it back will not require to recompute any hashes
161
+ * Elements are not converted to a plain type, this is responsibility of the caller
162
+ */
163
+ serialize() {
164
+ return {
165
+ levels: this.levels,
166
+ _zeros: this._zeros,
167
+ _layers: this._layers,
168
+ };
169
+ }
170
+ /**
171
+ * Deserialize data into a MerkleTree instance
172
+ * Make sure to provide the same hashFunction as was used in the source tree,
173
+ * otherwise the tree state will be invalid
174
+ *
175
+ * @param data
176
+ * @param hashFunction
177
+ * @returns {MerkleTree}
178
+ */
179
+ static deserialize(data, hashFunction) {
180
+ const instance = Object.assign(Object.create(this.prototype), data);
181
+ instance._hash = hashFunction;
182
+ instance.capacity = 2 ** instance.levels;
183
+ instance.zeroElement = instance._zeros[0];
184
+ return instance;
185
+ }
186
+ }
@@ -0,0 +1,5 @@
1
+ import { LocalStorage } from "node-localstorage";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import { fileURLToPath } from "url";
5
+ export { LocalStorage, path, fs, fileURLToPath };
@@ -0,0 +1,5 @@
1
+ import { LocalStorage } from "node-localstorage";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import { fileURLToPath } from "url";
5
+ export { LocalStorage, path, fs, fileURLToPath };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ZK Proof Generation Utilities
3
+ *
4
+ * This file provides functions for generating zero-knowledge proofs for privacy-preserving
5
+ * transactions on Solana. It handles both snarkjs and zkutil proof generation workflows.
6
+ *
7
+ * Inspired by: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/prover.js
8
+ */
9
+ interface Proof {
10
+ pi_a: string[];
11
+ pi_b: string[][];
12
+ pi_c: string[];
13
+ protocol: string;
14
+ curve: string;
15
+ }
16
+ /**
17
+ * Generates a ZK proof using snarkjs and formats it for use on-chain
18
+ *
19
+ * @param input The circuit inputs to generate a proof for
20
+ * @param keyBasePath The base path for the circuit keys (.wasm and .zkey files)
21
+ * @returns A proof object with formatted proof elements and public signals
22
+ */
23
+ declare function prove(input: any, keyBasePath: string): Promise<{
24
+ proof: Proof;
25
+ publicSignals: string[];
26
+ }>;
27
+ export declare function parseProofToBytesArray(proof: Proof, compressed?: boolean): {
28
+ proofA: number[];
29
+ proofB: number[][];
30
+ proofC: number[];
31
+ };
32
+ export declare function parseToBytesArray(publicSignals: string[]): number[][];
33
+ export { prove, type Proof };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ZK Proof Generation Utilities
3
+ *
4
+ * This file provides functions for generating zero-knowledge proofs for privacy-preserving
5
+ * transactions on Solana. It handles both snarkjs and zkutil proof generation workflows.
6
+ *
7
+ * Inspired by: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/prover.js
8
+ */
9
+ /// <reference types="node" />
10
+ import * as anchor from "@coral-xyz/anchor";
11
+ import { wtns, groth16 } from 'snarkjs';
12
+ import { FIELD_SIZE } from './constants.js';
13
+ // @ts-ignore - ignore TypeScript errors for ffjavascript
14
+ import { utils } from 'ffjavascript';
15
+ // Cast imported modules to their types
16
+ const wtnsTyped = wtns;
17
+ const groth16Typed = groth16;
18
+ const utilsTyped = utils;
19
+ /**
20
+ * Generates a ZK proof using snarkjs and formats it for use on-chain
21
+ *
22
+ * @param input The circuit inputs to generate a proof for
23
+ * @param keyBasePath The base path for the circuit keys (.wasm and .zkey files)
24
+ * @returns A proof object with formatted proof elements and public signals
25
+ */
26
+ async function prove(input, keyBasePath) {
27
+ return await groth16Typed.fullProve(utilsTyped.stringifyBigInts(input), `${keyBasePath}.wasm`, `${keyBasePath}.zkey`);
28
+ }
29
+ export function parseProofToBytesArray(proof, compressed = false) {
30
+ const proofJson = JSON.stringify(proof, null, 1);
31
+ const mydata = JSON.parse(proofJson.toString());
32
+ try {
33
+ for (const i in mydata) {
34
+ if (i == "pi_a" || i == "pi_c") {
35
+ for (const j in mydata[i]) {
36
+ mydata[i][j] = Array.from(utils.leInt2Buff(utils.unstringifyBigInts(mydata[i][j]), 32)).reverse();
37
+ }
38
+ }
39
+ else if (i == "pi_b") {
40
+ for (const j in mydata[i]) {
41
+ for (const z in mydata[i][j]) {
42
+ mydata[i][j][z] = Array.from(utils.leInt2Buff(utils.unstringifyBigInts(mydata[i][j][z]), 32));
43
+ }
44
+ }
45
+ }
46
+ }
47
+ if (compressed) {
48
+ const proofA = mydata.pi_a[0];
49
+ // negate proof by reversing the bitmask
50
+ const proofAIsPositive = yElementIsPositiveG1(new anchor.BN(mydata.pi_a[1]))
51
+ ? false
52
+ : true;
53
+ proofA[0] = addBitmaskToByte(proofA[0], proofAIsPositive);
54
+ const proofB = mydata.pi_b[0].flat().reverse();
55
+ const proofBY = mydata.pi_b[1].flat().reverse();
56
+ const proofBIsPositive = yElementIsPositiveG2(new anchor.BN(proofBY.slice(0, 32)), new anchor.BN(proofBY.slice(32, 64)));
57
+ proofB[0] = addBitmaskToByte(proofB[0], proofBIsPositive);
58
+ const proofC = mydata.pi_c[0];
59
+ const proofCIsPositive = yElementIsPositiveG1(new anchor.BN(mydata.pi_c[1]));
60
+ proofC[0] = addBitmaskToByte(proofC[0], proofCIsPositive);
61
+ return {
62
+ proofA,
63
+ proofB,
64
+ proofC,
65
+ };
66
+ }
67
+ return {
68
+ proofA: [mydata.pi_a[0], mydata.pi_a[1]].flat(),
69
+ proofB: [
70
+ mydata.pi_b[0].flat().reverse(),
71
+ mydata.pi_b[1].flat().reverse(),
72
+ ].flat(),
73
+ proofC: [mydata.pi_c[0], mydata.pi_c[1]].flat(),
74
+ };
75
+ }
76
+ catch (error) {
77
+ console.error("Error while parsing the proof.", error.message);
78
+ throw error;
79
+ }
80
+ }
81
+ // mainly used to parse the public signals of groth16 fullProve
82
+ export function parseToBytesArray(publicSignals) {
83
+ const publicInputsJson = JSON.stringify(publicSignals, null, 1);
84
+ const publicInputsBytesJson = JSON.parse(publicInputsJson.toString());
85
+ try {
86
+ const publicInputsBytes = new Array();
87
+ for (const i in publicInputsBytesJson) {
88
+ const ref = Array.from([
89
+ ...utils.leInt2Buff(utils.unstringifyBigInts(publicInputsBytesJson[i]), 32),
90
+ ]).reverse();
91
+ publicInputsBytes.push(ref);
92
+ }
93
+ return publicInputsBytes;
94
+ }
95
+ catch (error) {
96
+ console.error("Error while parsing public inputs.", error.message);
97
+ throw error;
98
+ }
99
+ }
100
+ function yElementIsPositiveG1(yElement) {
101
+ return yElement.lte(FIELD_SIZE.sub(yElement));
102
+ }
103
+ function yElementIsPositiveG2(yElement1, yElement2) {
104
+ const fieldMidpoint = FIELD_SIZE.div(new anchor.BN(2));
105
+ // Compare the first component of the y coordinate
106
+ if (yElement1.lt(fieldMidpoint)) {
107
+ return true;
108
+ }
109
+ else if (yElement1.gt(fieldMidpoint)) {
110
+ return false;
111
+ }
112
+ // If the first component is equal to the midpoint, compare the second component
113
+ return yElement2.lt(fieldMidpoint);
114
+ }
115
+ function addBitmaskToByte(byte, yIsPositive) {
116
+ if (!yIsPositive) {
117
+ return (byte |= 1 << 7);
118
+ }
119
+ else {
120
+ return byte;
121
+ }
122
+ }
123
+ export { prove };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Utility functions for ZK Cash
3
+ *
4
+ * Provides common utility functions for the ZK Cash system
5
+ * Based on: https://github.com/tornadocash/tornado-nova
6
+ */
7
+ import BN from 'bn.js';
8
+ import { Utxo } from '../models/utxo.js';
9
+ import { PublicKey } from '@solana/web3.js';
10
+ /**
11
+ * Calculate deposit fee based on deposit amount and fee rate
12
+ * @param depositAmount Amount being deposited in lamports
13
+ * @returns Fee amount in lamports
14
+ */
15
+ export declare function calculateDepositFee(depositAmount: number): Promise<number>;
16
+ /**
17
+ * Calculate withdrawal fee based on withdrawal amount and fee rate
18
+ * @param withdrawalAmount Amount being withdrawn in lamports
19
+ * @returns Fee amount in lamports
20
+ */
21
+ export declare function calculateWithdrawalFee(withdrawalAmount: number): Promise<number>;
22
+ /**
23
+ * Mock encryption function - in real implementation this would be proper encryption
24
+ * For testing, we just return a fixed prefix to ensure consistent extDataHash
25
+ * @param value Value to encrypt
26
+ * @returns Encrypted string representation
27
+ */
28
+ export declare function mockEncrypt(value: Utxo): string;
29
+ /**
30
+ * Calculates the hash of ext data using Borsh serialization
31
+ * @param extData External data object containing recipient, amount, encrypted outputs, fee, fee recipient, and mint address
32
+ * @returns The hash as a Uint8Array (32 bytes)
33
+ */
34
+ export declare function getExtDataHash(extData: {
35
+ recipient: string | PublicKey;
36
+ extAmount: string | number | BN;
37
+ encryptedOutput1?: string | Uint8Array;
38
+ encryptedOutput2?: string | Uint8Array;
39
+ fee: string | number | BN;
40
+ feeRecipient: string | PublicKey;
41
+ mintAddress: string | PublicKey;
42
+ }): Uint8Array;
43
+ export declare function fetchMerkleProof(commitment: string): Promise<{
44
+ pathElements: string[];
45
+ pathIndices: number[];
46
+ }>;
47
+ export declare function findNullifierPDAs(proof: any): {
48
+ nullifier0PDA: PublicKey;
49
+ nullifier1PDA: PublicKey;
50
+ };
51
+ export declare function findCommitmentPDAs(proof: any): {
52
+ commitment0PDA: PublicKey;
53
+ commitment1PDA: PublicKey;
54
+ };
55
+ export declare function queryRemoteTreeState(): Promise<{
56
+ root: string;
57
+ nextIndex: number;
58
+ }>;
59
+ export declare function getProgramAccounts(): {
60
+ treeAccount: PublicKey;
61
+ treeTokenAccount: PublicKey;
62
+ globalConfigAccount: PublicKey;
63
+ };
64
+ export declare function findCrossCheckNullifierPDAs(proof: any): {
65
+ nullifier2PDA: PublicKey;
66
+ nullifier3PDA: PublicKey;
67
+ };