privacycash 1.0.14 → 1.0.16
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 +5 -0
- package/dist/deposit.js +1 -4
- package/dist/getUtxos.js +1 -73
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/utils.d.ts +0 -4
- package/dist/utils/utils.js +0 -6
- package/dist/withdraw.js +1 -4
- package/package.json +1 -1
- package/src/deposit.ts +1 -4
- package/src/getUtxos.ts +1 -94
- package/src/utils/constants.ts +1 -1
- package/src/utils/utils.ts +0 -14
- package/src/withdraw.ts +2 -5
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
## Privacy Cash SDK
|
|
2
2
|
This is the SDK for Privacy Cash. It has been audited by Zigtur (https://x.com/zigtur).
|
|
3
3
|
|
|
4
|
+
### Disclaimer
|
|
5
|
+
This SDK powers Privacy Cash's frontend, assuming the single wallet use case. If you use it or published npm library from this repo, please fully test and beware of the inherent software risks or potential bugs.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
8
|
+
|
|
4
9
|
### Usage
|
|
5
10
|
This SDK provides APIs for developers to interact with Privacy Cash relayers easily. Developers can easily deposit/withdraw/query balances in Privacy Cash solana program.
|
|
6
11
|
|
package/dist/deposit.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PublicKey, TransactionInstruction, SystemProgram, ComputeBudgetProgram, VersionedTransaction, TransactionMessage, LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
2
2
|
import BN from 'bn.js';
|
|
3
3
|
import { Utxo } from './models/utxo.js';
|
|
4
|
-
import { fetchMerkleProof,
|
|
4
|
+
import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
|
|
5
5
|
import { prove, parseProofToBytesArray, parseToBytesArray } from './utils/prover.js';
|
|
6
6
|
import { MerkleTree } from './utils/merkle_tree.js';
|
|
7
7
|
import { serializeProofAndExtData } from './utils/encryption.js';
|
|
@@ -279,7 +279,6 @@ export async function deposit({ lightWasm, storage, keyBasePath, publicKey, conn
|
|
|
279
279
|
// Find PDAs for nullifiers and commitments
|
|
280
280
|
const { nullifier0PDA, nullifier1PDA } = findNullifierPDAs(proofToSubmit);
|
|
281
281
|
const { nullifier2PDA, nullifier3PDA } = findCrossCheckNullifierPDAs(proofToSubmit);
|
|
282
|
-
const { commitment0PDA, commitment1PDA } = findCommitmentPDAs(proofToSubmit);
|
|
283
282
|
// Address Lookup Table for transaction size optimization
|
|
284
283
|
logger.debug('Setting up Address Lookup Table...');
|
|
285
284
|
const ALT_ADDRESS = new PublicKey('72bpRay17JKp4k8H87p7ieU9C6aRDy5yCqwvtpTN2wuU');
|
|
@@ -298,8 +297,6 @@ export async function deposit({ lightWasm, storage, keyBasePath, publicKey, conn
|
|
|
298
297
|
{ pubkey: nullifier1PDA, isSigner: false, isWritable: true },
|
|
299
298
|
{ pubkey: nullifier2PDA, isSigner: false, isWritable: false },
|
|
300
299
|
{ pubkey: nullifier3PDA, isSigner: false, isWritable: false },
|
|
301
|
-
{ pubkey: commitment0PDA, isSigner: false, isWritable: true },
|
|
302
|
-
{ pubkey: commitment1PDA, isSigner: false, isWritable: true },
|
|
303
300
|
{ pubkey: treeTokenAccount, isSigner: false, isWritable: true },
|
|
304
301
|
{ pubkey: globalConfigAccount, isSigner: false, isWritable: false },
|
|
305
302
|
// recipient - just a placeholder, not actually used for deposits. using an ALT address to save bytes
|
package/dist/getUtxos.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function getUtxos({ publicKey, connection, encryptionService, stora
|
|
|
73
73
|
if (!fetched.hasMore) {
|
|
74
74
|
break;
|
|
75
75
|
}
|
|
76
|
-
await sleep(
|
|
76
|
+
await sleep(20);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
catch (e) {
|
|
@@ -254,78 +254,6 @@ export function getBalanceFromUtxos(utxos) {
|
|
|
254
254
|
// const remainderLamports = totalBalance.mod(LAMPORTS_PER_SOL);
|
|
255
255
|
return { lamports: totalBalance.toNumber() };
|
|
256
256
|
}
|
|
257
|
-
async function decrypt_output(encryptedOutput, encryptionService, utxoKeypair, lightWasm, connection) {
|
|
258
|
-
let res = { status: 'unDecrypted' };
|
|
259
|
-
try {
|
|
260
|
-
if (!encryptedOutput) {
|
|
261
|
-
return { status: 'skipped' };
|
|
262
|
-
}
|
|
263
|
-
// Try to decrypt the UTXO
|
|
264
|
-
res.utxo = await encryptionService.decryptUtxo(encryptedOutput, lightWasm);
|
|
265
|
-
// If we got here, decryption succeeded, so this UTXO belongs to the user
|
|
266
|
-
res.status = 'decrypted';
|
|
267
|
-
// Get the real index from the on-chain commitment account
|
|
268
|
-
try {
|
|
269
|
-
if (!res.utxo) {
|
|
270
|
-
throw new Error('res.utxo undefined');
|
|
271
|
-
}
|
|
272
|
-
const commitment = await res.utxo.getCommitment();
|
|
273
|
-
// Convert decimal commitment string to byte array (same format as in proofs)
|
|
274
|
-
const commitmentBytes = Array.from(leInt2Buff(unstringifyBigInts(commitment), 32)).reverse();
|
|
275
|
-
// Derive the commitment PDA (could be either commitment0 or commitment1)
|
|
276
|
-
// We'll try both seeds since we don't know which one it is
|
|
277
|
-
let commitmentAccount = null;
|
|
278
|
-
let realIndex = null;
|
|
279
|
-
// Try commitment0 seed
|
|
280
|
-
try {
|
|
281
|
-
const [commitment0PDA] = PublicKey.findProgramAddressSync([Buffer.from("commitment0"), Buffer.from(commitmentBytes)], PROGRAM_ID);
|
|
282
|
-
const account0Info = await connection.getAccountInfo(commitment0PDA);
|
|
283
|
-
if (account0Info) {
|
|
284
|
-
// Parse the index from the account data according to CommitmentAccount structure:
|
|
285
|
-
// 0-8: Anchor discriminator
|
|
286
|
-
// 8-40: commitment (32 bytes)
|
|
287
|
-
// 40-44: encrypted_output length (4 bytes)
|
|
288
|
-
// 44-44+len: encrypted_output data
|
|
289
|
-
// 44+len-52+len: index (8 bytes)
|
|
290
|
-
const encryptedOutputLength = account0Info.data.readUInt32LE(40);
|
|
291
|
-
const indexOffset = 44 + encryptedOutputLength;
|
|
292
|
-
const indexBytes = account0Info.data.slice(indexOffset, indexOffset + 8);
|
|
293
|
-
realIndex = new BN(indexBytes, 'le').toNumber();
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
catch (e) {
|
|
297
|
-
// Try commitment1 seed if commitment0 fails
|
|
298
|
-
try {
|
|
299
|
-
const [commitment1PDA] = PublicKey.findProgramAddressSync([Buffer.from("commitment1"), Buffer.from(commitmentBytes)], PROGRAM_ID);
|
|
300
|
-
const account1Info = await connection.getAccountInfo(commitment1PDA);
|
|
301
|
-
if (account1Info) {
|
|
302
|
-
// Parse the index from the account data according to CommitmentAccount structure
|
|
303
|
-
const encryptedOutputLength = account1Info.data.readUInt32LE(40);
|
|
304
|
-
const indexOffset = 44 + encryptedOutputLength;
|
|
305
|
-
const indexBytes = account1Info.data.slice(indexOffset, indexOffset + 8);
|
|
306
|
-
realIndex = new BN(indexBytes, 'le').toNumber();
|
|
307
|
-
logger.debug(`Found commitment1 account with index: ${realIndex}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
catch (e2) {
|
|
311
|
-
logger.debug(`Could not find commitment account for ${commitment}, using encrypted index: ${res.utxo.index}`);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
// Update the UTXO with the real index if we found it
|
|
315
|
-
if (realIndex !== null) {
|
|
316
|
-
const oldIndex = res.utxo.index;
|
|
317
|
-
res.utxo.index = realIndex;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
logger.debug(`Failed to get real index for UTXO: ${error.message}`);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
catch (error) {
|
|
325
|
-
// this UTXO doesn't belong to the user
|
|
326
|
-
}
|
|
327
|
-
return res;
|
|
328
|
-
}
|
|
329
257
|
async function decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm) {
|
|
330
258
|
let results = [];
|
|
331
259
|
// decript all UTXO
|
|
@@ -4,7 +4,7 @@ export declare const FIELD_SIZE: BN;
|
|
|
4
4
|
export declare const PROGRAM_ID: PublicKey;
|
|
5
5
|
export declare const DEPLOYER_ID: PublicKey;
|
|
6
6
|
export declare const FEE_RECIPIENT: PublicKey;
|
|
7
|
-
export declare const FETCH_UTXOS_GROUP_SIZE =
|
|
7
|
+
export declare const FETCH_UTXOS_GROUP_SIZE = 10000;
|
|
8
8
|
export declare const TRANSACT_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
|
|
9
9
|
export declare const MERKLE_TREE_DEPTH = 26;
|
|
10
10
|
export declare const ALT_ADDRESS: PublicKey;
|
package/dist/utils/constants.js
CHANGED
|
@@ -4,7 +4,7 @@ export const FIELD_SIZE = new BN('2188824287183927522224640574525727508854836440
|
|
|
4
4
|
export const PROGRAM_ID = new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
|
|
5
5
|
export const DEPLOYER_ID = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
|
|
6
6
|
export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
|
|
7
|
-
export const FETCH_UTXOS_GROUP_SIZE =
|
|
7
|
+
export const FETCH_UTXOS_GROUP_SIZE = 10_000;
|
|
8
8
|
export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
|
|
9
9
|
export const MERKLE_TREE_DEPTH = 26;
|
|
10
10
|
export const ALT_ADDRESS = new PublicKey('72bpRay17JKp4k8H87p7ieU9C6aRDy5yCqwvtpTN2wuU');
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -48,10 +48,6 @@ export declare function findNullifierPDAs(proof: any): {
|
|
|
48
48
|
nullifier0PDA: PublicKey;
|
|
49
49
|
nullifier1PDA: PublicKey;
|
|
50
50
|
};
|
|
51
|
-
export declare function findCommitmentPDAs(proof: any): {
|
|
52
|
-
commitment0PDA: PublicKey;
|
|
53
|
-
commitment1PDA: PublicKey;
|
|
54
|
-
};
|
|
55
51
|
export declare function queryRemoteTreeState(): Promise<{
|
|
56
52
|
root: string;
|
|
57
53
|
nextIndex: number;
|
package/dist/utils/utils.js
CHANGED
|
@@ -113,12 +113,6 @@ export function findNullifierPDAs(proof) {
|
|
|
113
113
|
const [nullifier1PDA] = PublicKey.findProgramAddressSync([Buffer.from("nullifier1"), Buffer.from(proof.inputNullifiers[1])], PROGRAM_ID);
|
|
114
114
|
return { nullifier0PDA, nullifier1PDA };
|
|
115
115
|
}
|
|
116
|
-
// Find commitment PDAs for the given proof
|
|
117
|
-
export function findCommitmentPDAs(proof) {
|
|
118
|
-
const [commitment0PDA] = PublicKey.findProgramAddressSync([Buffer.from("commitment0"), Buffer.from(proof.outputCommitments[0])], PROGRAM_ID);
|
|
119
|
-
const [commitment1PDA] = PublicKey.findProgramAddressSync([Buffer.from("commitment1"), Buffer.from(proof.outputCommitments[1])], PROGRAM_ID);
|
|
120
|
-
return { commitment0PDA, commitment1PDA };
|
|
121
|
-
}
|
|
122
116
|
// Function to query remote tree state from indexer API
|
|
123
117
|
export async function queryRemoteTreeState() {
|
|
124
118
|
try {
|
package/dist/withdraw.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Utxo } from './models/utxo.js';
|
|
|
6
6
|
import { parseProofToBytesArray, parseToBytesArray, prove } from './utils/prover.js';
|
|
7
7
|
import { ALT_ADDRESS, DEPLOYER_ID, FEE_RECIPIENT, FIELD_SIZE, INDEXER_API_URL, MERKLE_TREE_DEPTH } from './utils/constants.js';
|
|
8
8
|
import { serializeProofAndExtData } from './utils/encryption.js';
|
|
9
|
-
import { fetchMerkleProof,
|
|
9
|
+
import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
|
|
10
10
|
import { getUtxos } from './getUtxos.js';
|
|
11
11
|
import { logger } from './utils/logger.js';
|
|
12
12
|
import { getConfig } from './config.js';
|
|
@@ -221,7 +221,6 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
221
221
|
// Find PDAs for nullifiers and commitments
|
|
222
222
|
const { nullifier0PDA, nullifier1PDA } = findNullifierPDAs(proofToSubmit);
|
|
223
223
|
const { nullifier2PDA, nullifier3PDA } = findCrossCheckNullifierPDAs(proofToSubmit);
|
|
224
|
-
const { commitment0PDA, commitment1PDA } = findCommitmentPDAs(proofToSubmit);
|
|
225
224
|
// Serialize the proof and extData
|
|
226
225
|
const serializedProof = serializeProofAndExtData(proofToSubmit, extData);
|
|
227
226
|
logger.debug(`Total instruction data size: ${serializedProof.length} bytes`);
|
|
@@ -233,8 +232,6 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
233
232
|
nullifier1PDA: nullifier1PDA.toString(),
|
|
234
233
|
nullifier2PDA: nullifier2PDA.toString(),
|
|
235
234
|
nullifier3PDA: nullifier3PDA.toString(),
|
|
236
|
-
commitment0PDA: commitment0PDA.toString(),
|
|
237
|
-
commitment1PDA: commitment1PDA.toString(),
|
|
238
235
|
treeTokenAccount: treeTokenAccount.toString(),
|
|
239
236
|
globalConfigAccount: globalConfigAccount.toString(),
|
|
240
237
|
recipient: recipient.toString(),
|
package/package.json
CHANGED
package/src/deposit.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Connection, Keypair, PublicKey, TransactionInstruction, SystemProgram, ComputeBudgetProgram, VersionedTransaction, TransactionMessage, LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
2
2
|
import BN from 'bn.js';
|
|
3
3
|
import { Utxo } from './models/utxo.js';
|
|
4
|
-
import { fetchMerkleProof,
|
|
4
|
+
import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
|
|
5
5
|
import { prove, parseProofToBytesArray, parseToBytesArray } from './utils/prover.js';
|
|
6
6
|
import * as hasher from '@lightprotocol/hasher.rs';
|
|
7
7
|
import { MerkleTree } from './utils/merkle_tree.js';
|
|
@@ -344,7 +344,6 @@ export async function deposit({ lightWasm, storage, keyBasePath, publicKey, conn
|
|
|
344
344
|
// Find PDAs for nullifiers and commitments
|
|
345
345
|
const { nullifier0PDA, nullifier1PDA } = findNullifierPDAs(proofToSubmit);
|
|
346
346
|
const { nullifier2PDA, nullifier3PDA } = findCrossCheckNullifierPDAs(proofToSubmit);
|
|
347
|
-
const { commitment0PDA, commitment1PDA } = findCommitmentPDAs(proofToSubmit);
|
|
348
347
|
|
|
349
348
|
// Address Lookup Table for transaction size optimization
|
|
350
349
|
logger.debug('Setting up Address Lookup Table...');
|
|
@@ -368,8 +367,6 @@ export async function deposit({ lightWasm, storage, keyBasePath, publicKey, conn
|
|
|
368
367
|
{ pubkey: nullifier1PDA, isSigner: false, isWritable: true },
|
|
369
368
|
{ pubkey: nullifier2PDA, isSigner: false, isWritable: false },
|
|
370
369
|
{ pubkey: nullifier3PDA, isSigner: false, isWritable: false },
|
|
371
|
-
{ pubkey: commitment0PDA, isSigner: false, isWritable: true },
|
|
372
|
-
{ pubkey: commitment1PDA, isSigner: false, isWritable: true },
|
|
373
370
|
{ pubkey: treeTokenAccount, isSigner: false, isWritable: true },
|
|
374
371
|
{ pubkey: globalConfigAccount, isSigner: false, isWritable: false },
|
|
375
372
|
// recipient - just a placeholder, not actually used for deposits. using an ALT address to save bytes
|
package/src/getUtxos.ts
CHANGED
|
@@ -103,7 +103,7 @@ export async function getUtxos({ publicKey, connection, encryptionService, stora
|
|
|
103
103
|
if (!fetched.hasMore) {
|
|
104
104
|
break
|
|
105
105
|
}
|
|
106
|
-
await sleep(
|
|
106
|
+
await sleep(20)
|
|
107
107
|
}
|
|
108
108
|
} catch (e: any) {
|
|
109
109
|
throw e
|
|
@@ -335,99 +335,6 @@ export function getBalanceFromUtxos(utxos: Utxo[]) {
|
|
|
335
335
|
|
|
336
336
|
// Decrypt single output to Utxo
|
|
337
337
|
type DecryptRes = { status: 'decrypted' | 'skipped' | 'unDecrypted', utxo?: Utxo, encryptedOutput?: string }
|
|
338
|
-
async function decrypt_output(
|
|
339
|
-
encryptedOutput: string,
|
|
340
|
-
encryptionService: EncryptionService,
|
|
341
|
-
utxoKeypair: UtxoKeypair,
|
|
342
|
-
lightWasm: any,
|
|
343
|
-
connection: Connection
|
|
344
|
-
): Promise<DecryptRes> {
|
|
345
|
-
let res: DecryptRes = { status: 'unDecrypted' }
|
|
346
|
-
try {
|
|
347
|
-
if (!encryptedOutput) {
|
|
348
|
-
return { status: 'skipped' }
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Try to decrypt the UTXO
|
|
352
|
-
res.utxo = await encryptionService.decryptUtxo(
|
|
353
|
-
encryptedOutput,
|
|
354
|
-
lightWasm
|
|
355
|
-
);
|
|
356
|
-
|
|
357
|
-
// If we got here, decryption succeeded, so this UTXO belongs to the user
|
|
358
|
-
res.status = 'decrypted'
|
|
359
|
-
|
|
360
|
-
// Get the real index from the on-chain commitment account
|
|
361
|
-
try {
|
|
362
|
-
if (!res.utxo) {
|
|
363
|
-
throw new Error('res.utxo undefined')
|
|
364
|
-
}
|
|
365
|
-
const commitment = await res.utxo.getCommitment();
|
|
366
|
-
// Convert decimal commitment string to byte array (same format as in proofs)
|
|
367
|
-
const commitmentBytes = Array.from(
|
|
368
|
-
leInt2Buff(unstringifyBigInts(commitment), 32)
|
|
369
|
-
).reverse() as number[];
|
|
370
|
-
|
|
371
|
-
// Derive the commitment PDA (could be either commitment0 or commitment1)
|
|
372
|
-
// We'll try both seeds since we don't know which one it is
|
|
373
|
-
let commitmentAccount = null;
|
|
374
|
-
let realIndex = null;
|
|
375
|
-
// Try commitment0 seed
|
|
376
|
-
try {
|
|
377
|
-
const [commitment0PDA] = PublicKey.findProgramAddressSync(
|
|
378
|
-
[Buffer.from("commitment0"), Buffer.from(commitmentBytes)],
|
|
379
|
-
PROGRAM_ID
|
|
380
|
-
);
|
|
381
|
-
|
|
382
|
-
const account0Info = await connection.getAccountInfo(commitment0PDA);
|
|
383
|
-
if (account0Info) {
|
|
384
|
-
// Parse the index from the account data according to CommitmentAccount structure:
|
|
385
|
-
// 0-8: Anchor discriminator
|
|
386
|
-
// 8-40: commitment (32 bytes)
|
|
387
|
-
// 40-44: encrypted_output length (4 bytes)
|
|
388
|
-
// 44-44+len: encrypted_output data
|
|
389
|
-
// 44+len-52+len: index (8 bytes)
|
|
390
|
-
const encryptedOutputLength = account0Info.data.readUInt32LE(40);
|
|
391
|
-
const indexOffset = 44 + encryptedOutputLength;
|
|
392
|
-
const indexBytes = account0Info.data.slice(indexOffset, indexOffset + 8);
|
|
393
|
-
realIndex = new BN(indexBytes, 'le').toNumber();
|
|
394
|
-
}
|
|
395
|
-
} catch (e) {
|
|
396
|
-
// Try commitment1 seed if commitment0 fails
|
|
397
|
-
try {
|
|
398
|
-
const [commitment1PDA] = PublicKey.findProgramAddressSync(
|
|
399
|
-
[Buffer.from("commitment1"), Buffer.from(commitmentBytes)],
|
|
400
|
-
PROGRAM_ID
|
|
401
|
-
);
|
|
402
|
-
|
|
403
|
-
const account1Info = await connection.getAccountInfo(commitment1PDA);
|
|
404
|
-
if (account1Info) {
|
|
405
|
-
// Parse the index from the account data according to CommitmentAccount structure
|
|
406
|
-
const encryptedOutputLength = account1Info.data.readUInt32LE(40);
|
|
407
|
-
const indexOffset = 44 + encryptedOutputLength;
|
|
408
|
-
const indexBytes = account1Info.data.slice(indexOffset, indexOffset + 8);
|
|
409
|
-
realIndex = new BN(indexBytes, 'le').toNumber();
|
|
410
|
-
logger.debug(`Found commitment1 account with index: ${realIndex}`);
|
|
411
|
-
}
|
|
412
|
-
} catch (e2) {
|
|
413
|
-
logger.debug(`Could not find commitment account for ${commitment}, using encrypted index: ${res.utxo.index}`);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Update the UTXO with the real index if we found it
|
|
418
|
-
if (realIndex !== null) {
|
|
419
|
-
const oldIndex = res.utxo.index;
|
|
420
|
-
res.utxo.index = realIndex;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
} catch (error: any) {
|
|
424
|
-
logger.debug(`Failed to get real index for UTXO: ${error.message}`);
|
|
425
|
-
}
|
|
426
|
-
} catch (error: any) {
|
|
427
|
-
// this UTXO doesn't belong to the user
|
|
428
|
-
}
|
|
429
|
-
return res
|
|
430
|
-
}
|
|
431
338
|
|
|
432
339
|
async function decrypt_outputs(
|
|
433
340
|
encryptedOutputs: string[],
|
package/src/utils/constants.ts
CHANGED
|
@@ -9,7 +9,7 @@ export const DEPLOYER_ID = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8
|
|
|
9
9
|
|
|
10
10
|
export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM')
|
|
11
11
|
|
|
12
|
-
export const FETCH_UTXOS_GROUP_SIZE =
|
|
12
|
+
export const FETCH_UTXOS_GROUP_SIZE = 10_000
|
|
13
13
|
|
|
14
14
|
export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
|
|
15
15
|
|
package/src/utils/utils.ts
CHANGED
|
@@ -146,20 +146,6 @@ export function findNullifierPDAs(proof: any) {
|
|
|
146
146
|
return { nullifier0PDA, nullifier1PDA };
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
// Find commitment PDAs for the given proof
|
|
150
|
-
export function findCommitmentPDAs(proof: any) {
|
|
151
|
-
const [commitment0PDA] = PublicKey.findProgramAddressSync(
|
|
152
|
-
[Buffer.from("commitment0"), Buffer.from(proof.outputCommitments[0])],
|
|
153
|
-
PROGRAM_ID
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const [commitment1PDA] = PublicKey.findProgramAddressSync(
|
|
157
|
-
[Buffer.from("commitment1"), Buffer.from(proof.outputCommitments[1])],
|
|
158
|
-
PROGRAM_ID
|
|
159
|
-
);
|
|
160
|
-
return { commitment0PDA, commitment1PDA };
|
|
161
|
-
}
|
|
162
|
-
|
|
163
149
|
// Function to query remote tree state from indexer API
|
|
164
150
|
export async function queryRemoteTreeState(): Promise<{ root: string, nextIndex: number }> {
|
|
165
151
|
try {
|
package/src/withdraw.ts
CHANGED
|
@@ -8,9 +8,9 @@ import { parseProofToBytesArray, parseToBytesArray, prove } from './utils/prover
|
|
|
8
8
|
|
|
9
9
|
import { ALT_ADDRESS, DEPLOYER_ID, FEE_RECIPIENT, FIELD_SIZE, INDEXER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID } from './utils/constants.js';
|
|
10
10
|
import { EncryptionService, serializeProofAndExtData } from './utils/encryption.js';
|
|
11
|
-
import { fetchMerkleProof,
|
|
11
|
+
import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
|
|
12
12
|
|
|
13
|
-
import { getUtxos
|
|
13
|
+
import { getUtxos } from './getUtxos.js';
|
|
14
14
|
import { logger } from './utils/logger.js';
|
|
15
15
|
import { getConfig } from './config.js';
|
|
16
16
|
// Indexer API endpoint
|
|
@@ -278,7 +278,6 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
278
278
|
// Find PDAs for nullifiers and commitments
|
|
279
279
|
const { nullifier0PDA, nullifier1PDA } = findNullifierPDAs(proofToSubmit);
|
|
280
280
|
const { nullifier2PDA, nullifier3PDA } = findCrossCheckNullifierPDAs(proofToSubmit);
|
|
281
|
-
const { commitment0PDA, commitment1PDA } = findCommitmentPDAs(proofToSubmit);
|
|
282
281
|
|
|
283
282
|
// Serialize the proof and extData
|
|
284
283
|
const serializedProof = serializeProofAndExtData(proofToSubmit, extData);
|
|
@@ -292,8 +291,6 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
292
291
|
nullifier1PDA: nullifier1PDA.toString(),
|
|
293
292
|
nullifier2PDA: nullifier2PDA.toString(),
|
|
294
293
|
nullifier3PDA: nullifier3PDA.toString(),
|
|
295
|
-
commitment0PDA: commitment0PDA.toString(),
|
|
296
|
-
commitment1PDA: commitment1PDA.toString(),
|
|
297
294
|
treeTokenAccount: treeTokenAccount.toString(),
|
|
298
295
|
globalConfigAccount: globalConfigAccount.toString(),
|
|
299
296
|
recipient: recipient.toString(),
|