privacycash 1.0.16 → 1.0.18

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 (45) hide show
  1. package/__tests__/e2e.test.ts +5 -1
  2. package/__tests__/e2espl.test.ts +73 -0
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.js +6 -10
  5. package/dist/deposit.js +4 -11
  6. package/dist/depositSPL.d.ts +19 -0
  7. package/dist/depositSPL.js +433 -0
  8. package/dist/exportUtils.d.ts +3 -0
  9. package/dist/exportUtils.js +3 -0
  10. package/dist/getUtxos.d.ts +2 -1
  11. package/dist/getUtxos.js +68 -79
  12. package/dist/getUtxosSPL.d.ts +31 -0
  13. package/dist/getUtxosSPL.js +369 -0
  14. package/dist/index.d.ts +31 -1
  15. package/dist/index.js +73 -3
  16. package/dist/models/utxo.js +10 -1
  17. package/dist/utils/address_lookup_table.d.ts +1 -0
  18. package/dist/utils/address_lookup_table.js +23 -0
  19. package/dist/utils/constants.d.ts +3 -1
  20. package/dist/utils/constants.js +6 -3
  21. package/dist/utils/encryption.d.ts +1 -1
  22. package/dist/utils/encryption.js +5 -3
  23. package/dist/utils/prover.d.ts +4 -1
  24. package/dist/utils/prover.js +26 -2
  25. package/dist/utils/utils.d.ts +3 -2
  26. package/dist/utils/utils.js +26 -6
  27. package/dist/withdraw.js +3 -3
  28. package/dist/withdrawSPL.d.ts +22 -0
  29. package/dist/withdrawSPL.js +290 -0
  30. package/package.json +5 -3
  31. package/src/config.ts +7 -14
  32. package/src/deposit.ts +4 -11
  33. package/src/depositSPL.ts +555 -0
  34. package/src/exportUtils.ts +5 -1
  35. package/src/getUtxos.ts +73 -78
  36. package/src/getUtxosSPL.ts +495 -0
  37. package/src/index.ts +84 -3
  38. package/src/models/utxo.ts +10 -1
  39. package/src/utils/address_lookup_table.ts +54 -6
  40. package/src/utils/constants.ts +8 -3
  41. package/src/utils/encryption.ts +6 -3
  42. package/src/utils/prover.ts +36 -3
  43. package/src/utils/utils.ts +29 -6
  44. package/src/withdraw.ts +4 -4
  45. package/src/withdrawSPL.ts +379 -0
package/src/index.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey, VersionedTransaction } from '@solana/web3.js';
2
2
  import { deposit } from './deposit.js';
3
3
  import { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
4
+ import { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
4
5
 
5
- import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET } from './utils/constants.js';
6
+ import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, USDC_MINT } from './utils/constants.js';
6
7
  import { logger, type LoggerFn, setLogger } from './utils/logger.js';
7
8
  import { EncryptionService } from './utils/encryption.js';
8
9
  import { WasmFactory } from '@lightprotocol/hasher.rs';
@@ -10,6 +11,9 @@ import bs58 from 'bs58'
10
11
  import { withdraw } from './withdraw.js';
11
12
  import { LocalStorage } from "node-localstorage";
12
13
  import path from 'node:path'
14
+ import { depositSPL } from './depositSPL.js';
15
+ import { withdrawSPL } from './withdrawSPL.js';
16
+ import { getAssociatedTokenAddress } from '@solana/spl-token';
13
17
 
14
18
  let storage = new LocalStorage(path.join(process.cwd(), "cache"));
15
19
 
@@ -65,6 +69,16 @@ export class PrivacyCash {
65
69
  }
66
70
  storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(this.publicKey))
67
71
  storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(this.publicKey))
72
+ // spl
73
+ let mintAddresses = [USDC_MINT]
74
+ for (let mintAddress of mintAddresses) {
75
+ let ata = await getAssociatedTokenAddress(
76
+ mintAddress,
77
+ this.publicKey
78
+ );
79
+ storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(ata))
80
+ storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(ata))
81
+ }
68
82
  return this
69
83
  }
70
84
 
@@ -96,6 +110,33 @@ export class PrivacyCash {
96
110
  return res
97
111
  }
98
112
 
113
+ /**
114
+ * Deposit USDC to the Privacy Cash.
115
+ */
116
+ async depositUSDC({ base_units }: {
117
+ base_units: number
118
+ }) {
119
+ this.isRuning = true
120
+ logger.info('start depositting')
121
+ let lightWasm = await WasmFactory.getInstance()
122
+ let res = await depositSPL({
123
+ mintAddress: USDC_MINT,
124
+ lightWasm,
125
+ base_units: base_units,
126
+ connection: this.connection,
127
+ encryptionService: this.encryptionService,
128
+ publicKey: this.publicKey,
129
+ transactionSigner: async (tx: VersionedTransaction) => {
130
+ tx.sign([this.keypair])
131
+ return tx
132
+ },
133
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
134
+ storage
135
+ })
136
+ this.isRuning = false
137
+ return res
138
+ }
139
+
99
140
  /**
100
141
  * Withdraw SOL from the Privacy Cash.
101
142
  *
@@ -124,17 +165,57 @@ export class PrivacyCash {
124
165
  return res
125
166
  }
126
167
 
168
+ /**
169
+ * Withdraw USDC from the Privacy Cash.
170
+ *
171
+ * 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' })
172
+ */
173
+ async withdrawUSDC({ base_units, recipientAddress }: {
174
+ base_units: number,
175
+ recipientAddress?: string
176
+ }) {
177
+ this.isRuning = true
178
+ logger.info('start withdrawing')
179
+ let lightWasm = await WasmFactory.getInstance()
180
+ let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey
181
+ let res = await withdrawSPL({
182
+ mintAddress: USDC_MINT,
183
+ lightWasm,
184
+ base_units,
185
+ connection: this.connection,
186
+ encryptionService: this.encryptionService,
187
+ publicKey: this.publicKey,
188
+ recipient,
189
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
190
+ storage
191
+ })
192
+ console.log(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`)
193
+ this.isRuning = false
194
+ return res
195
+ }
196
+
127
197
  /**
128
198
  * Returns the amount of lamports current wallet has in Privacy Cash.
129
199
  */
130
- async getPrivateBalance() {
200
+ async getPrivateBalance(abortSignal?: AbortSignal) {
131
201
  logger.info('getting private balance')
132
202
  this.isRuning = true
133
- let utxos = await getUtxos({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage })
203
+ let utxos = await getUtxos({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, abortSignal })
134
204
  this.isRuning = false
135
205
  return getBalanceFromUtxos(utxos)
136
206
  }
137
207
 
208
+ /**
209
+ * Returns the amount of lamports current wallet has in Privacy Cash.
210
+ */
211
+ async getPrivateBalanceUSDC() {
212
+ logger.info('getting private balance')
213
+ this.isRuning = true
214
+ let utxos = await getUtxosSPL({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, mintAddress: USDC_MINT })
215
+ this.isRuning = false
216
+ return getBalanceFromUtxosSPL(utxos)
217
+ }
218
+
138
219
  /**
139
220
  * Returns true if the code is running in a browser.
140
221
  */
@@ -9,6 +9,8 @@ import BN from 'bn.js';
9
9
  import { Keypair } from './keypair.js';
10
10
  import * as hasher from '@lightprotocol/hasher.rs';
11
11
  import { ethers } from 'ethers';
12
+ import { getMintAddressField } from '../utils/utils.js';
13
+ import { PublicKey } from '@solana/web3.js';
12
14
  /**
13
15
  * Simplified Utxo class inspired by Tornado Cash Nova
14
16
  * Based on: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/utxo.js
@@ -57,7 +59,14 @@ export class Utxo {
57
59
  }
58
60
 
59
61
  async getCommitment(): Promise<string> {
60
- return this.lightWasm.poseidonHashString([this.amount.toString(), this.keypair.pubkey.toString(), this.blinding.toString(), this.mintAddress]);
62
+ // return this.lightWasm.poseidonHashString([this.amount.toString(), this.keypair.pubkey.toString(), this.blinding.toString(), this.mintAddress]);
63
+ const mintAddressField = getMintAddressField(new PublicKey(this.mintAddress));
64
+ return this.lightWasm.poseidonHashString([
65
+ this.amount.toString(),
66
+ this.keypair.pubkey.toString(),
67
+ this.blinding.toString(),
68
+ mintAddressField
69
+ ]);
61
70
  }
62
71
 
63
72
  async getNullifier(): Promise<string> {
@@ -1,7 +1,17 @@
1
- import {
2
- Connection,
3
- PublicKey
1
+ import {
2
+ Connection,
3
+ Keypair,
4
+ PublicKey,
5
+ SystemProgram,
6
+ AddressLookupTableProgram,
7
+ Transaction,
8
+ sendAndConfirmTransaction,
9
+ ComputeBudgetProgram,
10
+ VersionedTransaction,
11
+ TransactionMessage
4
12
  } from '@solana/web3.js';
13
+ import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
14
+
5
15
 
6
16
  /**
7
17
  * Helper function to use an existing ALT (recommended for production)
@@ -14,16 +24,54 @@ export async function useExistingALT(
14
24
  try {
15
25
  console.log(`Using existing ALT: ${altAddress.toString()}`);
16
26
  const altAccount = await connection.getAddressLookupTable(altAddress);
17
-
27
+
18
28
  if (altAccount.value) {
19
29
  console.log(`✅ ALT found with ${altAccount.value.state.addresses.length} addresses`);
20
30
  } else {
21
31
  console.log('❌ ALT not found');
22
32
  }
23
-
33
+
24
34
  return altAccount;
25
35
  } catch (error) {
26
36
  console.error('Error getting existing ALT:', error);
27
37
  return null;
28
38
  }
29
- }
39
+ }
40
+
41
+
42
+ export function getProtocolAddressesWithMint(
43
+ programId: PublicKey,
44
+ authority: PublicKey,
45
+ treeAta: PublicKey,
46
+ feeRecipient: PublicKey,
47
+ feeRecipientAta: PublicKey
48
+ ): PublicKey[] {
49
+ // Derive global config PDA
50
+ const [globalConfigAccount] = PublicKey.findProgramAddressSync(
51
+ [Buffer.from('global_config')],
52
+ programId
53
+ );
54
+
55
+ // Derive tree accounts
56
+ const [treeAccount] = PublicKey.findProgramAddressSync(
57
+ [Buffer.from('merkle_tree')],
58
+ programId
59
+ );
60
+
61
+ return [
62
+ // Core program accounts (constant)
63
+ programId,
64
+ treeAccount,
65
+ treeAta,
66
+ globalConfigAccount,
67
+ authority,
68
+ feeRecipient,
69
+ feeRecipientAta,
70
+
71
+ // System programs (constant)
72
+ SystemProgram.programId,
73
+ ComputeBudgetProgram.programId,
74
+ ASSOCIATED_TOKEN_PROGRAM_ID,
75
+ TOKEN_PROGRAM_ID,
76
+ ];
77
+ }
@@ -5,22 +5,27 @@ export const FIELD_SIZE = new BN('2188824287183927522224640574525727508854836440
5
5
 
6
6
  export const PROGRAM_ID = new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
7
7
 
8
- export const DEPLOYER_ID = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM')
8
+ export const DEPLOYER_ID = new PublicKey('97rSMQUukMDjA7PYErccyx7ZxbHvSDaeXp2ig5BwSrTf')
9
9
 
10
+ //BxuZn19npE43qkrQycBSb12vgruyD3vLygxwZss7eXLU
10
11
  export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM')
11
12
 
12
13
  export const FETCH_UTXOS_GROUP_SIZE = 10_000
13
14
 
14
15
  export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
15
16
 
17
+ export const TRANSACT_SPL_IX_DISCRIMINATOR = Buffer.from([154, 66, 244, 204, 78, 225, 163, 151]);
18
+
16
19
  export const MERKLE_TREE_DEPTH = 26;
17
20
 
18
- export const ALT_ADDRESS = new PublicKey('72bpRay17JKp4k8H87p7ieU9C6aRDy5yCqwvtpTN2wuU');
21
+ export const ALT_ADDRESS = new PublicKey('HEN49U2ySJ85Vc78qprSW9y6mFDhs1NczRxyppNHjofe');
19
22
 
20
- export const INDEXER_API_URL = process.env.NEXT_PUBLIC_INDEXER_API_URL ?? 'https://api3.privacycash.org';
23
+ export const RELAYER_API_URL = process.env.NEXT_PUBLIC_RELAYER_API_URL ?? 'https://api3.privacycash.org';
21
24
 
22
25
  export const SIGN_MESSAGE = `Privacy Money account sign in`
23
26
 
24
27
  // localStorage cache keys
25
28
  export const LSK_FETCH_OFFSET = 'fetch_offset'
26
29
  export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs'
30
+
31
+ export const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')
@@ -5,7 +5,7 @@ import { Utxo } from '../models/utxo.js';
5
5
  import { WasmFactory } from '@lightprotocol/hasher.rs';
6
6
  import { Keypair as UtxoKeypair } from '../models/keypair.js';
7
7
  import { keccak256 } from '@ethersproject/keccak256';
8
- import { PROGRAM_ID, TRANSACT_IX_DISCRIMINATOR } from './constants.js';
8
+ import { PROGRAM_ID, TRANSACT_IX_DISCRIMINATOR, TRANSACT_SPL_IX_DISCRIMINATOR } from './constants.js';
9
9
  import BN from 'bn.js';
10
10
 
11
11
 
@@ -426,16 +426,19 @@ export class EncryptionService {// Version identifier for encryption scheme (8-b
426
426
  }
427
427
  }
428
428
 
429
- export function serializeProofAndExtData(proof: any, extData: any) {
429
+ export function serializeProofAndExtData(proof: any, extData: any, isSpl: boolean = false) {
430
430
  // Create the ExtDataMinified object for the program call (only extAmount and fee)
431
431
  const extDataMinified = {
432
432
  extAmount: extData.extAmount,
433
433
  fee: extData.fee
434
434
  };
435
435
 
436
+ // Use the appropriate discriminator based on whether this is SPL or native SOL
437
+ const discriminator = isSpl ? TRANSACT_SPL_IX_DISCRIMINATOR : TRANSACT_IX_DISCRIMINATOR;
438
+
436
439
  // Use the same serialization approach as deposit script
437
440
  const instructionData = Buffer.concat([
438
- TRANSACT_IX_DISCRIMINATOR,
441
+ discriminator,
439
442
  // Serialize proof
440
443
  Buffer.from(proof.proofA),
441
444
  Buffer.from(proof.proofB),
@@ -23,7 +23,14 @@ type WtnsModule = {
23
23
  }
24
24
 
25
25
  type Groth16Module = {
26
- fullProve: (input: any, wasmFile: string, zkeyFile: string) => Promise<{ proof: Proof; publicSignals: string[] }>
26
+ fullProve: (
27
+ input: any,
28
+ wasmFile: string,
29
+ zkeyFile: string,
30
+ logger?: any,
31
+ wtnsCalcOptions?: { singleThread?: boolean },
32
+ proverOptions?: { singleThread?: boolean }
33
+ ) => Promise<{ proof: Proof; publicSignals: string[] }>
27
34
  verify: (vkeyData: any, publicSignals: any, proof: Proof) => Promise<boolean>
28
35
  }
29
36
 
@@ -53,23 +60,49 @@ interface ProofResult {
53
60
 
54
61
  /**
55
62
  * Generates a ZK proof using snarkjs and formats it for use on-chain
56
- *
63
+ *
57
64
  * @param input The circuit inputs to generate a proof for
58
65
  * @param keyBasePath The base path for the circuit keys (.wasm and .zkey files)
66
+ * @param options Optional proof generation options (e.g., singleThread for Deno/Bun)
59
67
  * @returns A proof object with formatted proof elements and public signals
60
68
  */
61
- async function prove(input: any, keyBasePath: string): Promise<{
69
+ async function prove(input: any, keyBasePath: string, options?: { singleThread?: boolean }): Promise<{
62
70
  proof: Proof
63
71
  publicSignals: string[];
64
72
  }> {
73
+ // Detect if we should use single-threaded mode (for Deno/Bun compatibility)
74
+ const useSingleThread = options?.singleThread ?? shouldUseSingleThread();
75
+
76
+ // Single-thread options need to be passed to BOTH witness calculation AND proving
77
+ const singleThreadOpts = useSingleThread ? { singleThread: true } : undefined;
65
78
 
79
+ // Call fullProve with all parameters:
80
+ // 1. input, 2. wasmFile, 3. zkeyFile, 4. logger, 5. wtnsCalcOptions, 6. proverOptions
66
81
  return await groth16Typed.fullProve(
67
82
  utilsTyped.stringifyBigInts(input),
68
83
  `${keyBasePath}.wasm`,
69
84
  `${keyBasePath}.zkey`,
85
+ undefined, // logger parameter
86
+ singleThreadOpts, // wtnsCalcOptions (5th param) - for witness calculation
87
+ singleThreadOpts // proverOptions (6th param) - for proving
70
88
  )
71
89
  }
72
90
 
91
+ /**
92
+ * Detect if single-threaded mode should be used
93
+ */
94
+ function shouldUseSingleThread(): boolean {
95
+ // @ts-ignore - Deno global
96
+ if (typeof Deno !== 'undefined') {
97
+ return true; // Deno has worker issues
98
+ }
99
+ // @ts-ignore - Bun global
100
+ if (typeof Bun !== 'undefined') {
101
+ return true; // Bun may have worker issues
102
+ }
103
+ return false;
104
+ }
105
+
73
106
  export function parseProofToBytesArray(
74
107
  proof: Proof,
75
108
  compressed: boolean = false,
@@ -10,7 +10,7 @@ import { Utxo } from '../models/utxo.js';
10
10
  import * as borsh from 'borsh';
11
11
  import { sha256 } from '@ethersproject/sha2';
12
12
  import { PublicKey } from '@solana/web3.js';
13
- import { INDEXER_API_URL, PROGRAM_ID } from './constants.js';
13
+ import { RELAYER_API_URL, PROGRAM_ID } from './constants.js';
14
14
  import { logger } from './logger.js';
15
15
  import { getConfig } from '../config.js';
16
16
 
@@ -115,12 +115,16 @@ export function getExtDataHash(extData: {
115
115
 
116
116
 
117
117
  // Function to fetch Merkle proof from API for a given commitment
118
- export async function fetchMerkleProof(commitment: string): Promise<{ pathElements: string[], pathIndices: number[] }> {
118
+ export async function fetchMerkleProof(commitment: string, tokenName?: string): Promise<{ pathElements: string[], pathIndices: number[] }> {
119
119
  try {
120
120
  logger.debug(`Fetching Merkle proof for commitment: ${commitment}`);
121
- const response = await fetch(`${INDEXER_API_URL}/merkle/proof/${commitment}`);
121
+ let url = `${RELAYER_API_URL}/merkle/proof/${commitment}`
122
+ if (tokenName) {
123
+ url += '?token=' + tokenName
124
+ }
125
+ const response = await fetch(url);
122
126
  if (!response.ok) {
123
- throw new Error(`Failed to fetch Merkle proof: ${response.status} ${response.statusText}`);
127
+ throw new Error(`Failed to fetch Merkle proof: ${url}`);
124
128
  }
125
129
  const data = await response.json() as { pathElements: string[], pathIndices: number[] };
126
130
  logger.debug(`✓ Fetched Merkle proof with ${data.pathElements.length} elements`);
@@ -147,10 +151,14 @@ export function findNullifierPDAs(proof: any) {
147
151
  }
148
152
 
149
153
  // Function to query remote tree state from indexer API
150
- export async function queryRemoteTreeState(): Promise<{ root: string, nextIndex: number }> {
154
+ export async function queryRemoteTreeState(tokenName?: string): Promise<{ root: string, nextIndex: number }> {
151
155
  try {
152
156
  logger.debug('Fetching Merkle root and nextIndex from API...');
153
- const response = await fetch(`${INDEXER_API_URL}/merkle/root`);
157
+ let url = `${RELAYER_API_URL}/merkle/root`
158
+ if (tokenName) {
159
+ url += '?token=' + tokenName
160
+ }
161
+ const response = await fetch(url);
154
162
  if (!response.ok) {
155
163
  throw new Error(`Failed to fetch Merkle root and nextIndex: ${response.status} ${response.statusText}`);
156
164
  }
@@ -196,4 +204,19 @@ export function findCrossCheckNullifierPDAs(proof: any) {
196
204
  );
197
205
 
198
206
  return { nullifier2PDA, nullifier3PDA };
207
+ }
208
+
209
+ export function getMintAddressField(mint: PublicKey): string {
210
+ const mintStr = mint.toString();
211
+
212
+ // Special case for SOL (system program)
213
+ if (mintStr === '11111111111111111111111111111112') {
214
+ return mintStr;
215
+ }
216
+
217
+ // For SPL tokens (USDC, USDT, etc): use first 31 bytes (248 bits)
218
+ // This provides better collision resistance than 8 bytes while still fitting in the field
219
+ // We will only suppport private SOL, USDC and USDT send, so there won't be any collision.
220
+ const mintBytes = mint.toBytes();
221
+ return new BN(mintBytes.slice(0, 31), 'be').toString();
199
222
  }
package/src/withdraw.ts CHANGED
@@ -6,7 +6,7 @@ import * as hasher from '@lightprotocol/hasher.rs';
6
6
  import { Utxo } from './models/utxo.js';
7
7
  import { parseProofToBytesArray, parseToBytesArray, prove } from './utils/prover.js';
8
8
 
9
- import { ALT_ADDRESS, DEPLOYER_ID, FEE_RECIPIENT, FIELD_SIZE, INDEXER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID } from './utils/constants.js';
9
+ import { ALT_ADDRESS, DEPLOYER_ID, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID } from './utils/constants.js';
10
10
  import { EncryptionService, serializeProofAndExtData } from './utils/encryption.js';
11
11
  import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
12
12
 
@@ -20,7 +20,7 @@ import { getConfig } from './config.js';
20
20
  async function submitWithdrawToIndexer(params: any): Promise<string> {
21
21
  try {
22
22
 
23
- const response = await fetch(`${INDEXER_API_URL}/withdraw`, {
23
+ const response = await fetch(`${RELAYER_API_URL}/withdraw`, {
24
24
  method: 'POST',
25
25
  headers: {
26
26
  'Content-Type': 'application/json',
@@ -319,7 +319,7 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
319
319
  console.log(`retryTimes: ${retryTimes}`)
320
320
  await new Promise(resolve => setTimeout(resolve, itv * 1000));
321
321
  console.log('Fetching updated tree state...');
322
- let res = await fetch(INDEXER_API_URL + '/utxos/check/' + encryptedOutputStr)
322
+ let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr)
323
323
  let resJson = await res.json()
324
324
  console.log('resJson:', resJson)
325
325
  if (resJson.exists) {
@@ -331,4 +331,4 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
331
331
  retryTimes++
332
332
  }
333
333
 
334
- }
334
+ }