privacycash 1.0.21 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ import { EncryptionService } from './utils/encryption.js';
6
6
  import { WasmFactory } from '@lightprotocol/hasher.rs';
7
7
  //@ts-ignore
8
8
  import * as ffjavascript from 'ffjavascript';
9
- import { FETCH_UTXOS_GROUP_SIZE, RELAYER_API_URL, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, PROGRAM_ID } from './utils/constants.js';
9
+ import { FETCH_UTXOS_GROUP_SIZE, RELAYER_API_URL, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, PROGRAM_ID, SplList, tokens } from './utils/constants.js';
10
10
  import { logger } from './utils/logger.js';
11
11
  import { getAssociatedTokenAddress } from '@solana/spl-token';
12
12
 
@@ -55,12 +55,12 @@ let decryptionTaskFinished = 0;
55
55
  * @returns Array of decrypted UTXOs that belong to the user
56
56
  */
57
57
 
58
- export async function getUtxosSPL({ publicKey, connection, encryptionService, storage, mintAddress, abortSignal, offset }: {
58
+ export async function getUtxosSPL({ publicKey, connection, encryptionService, storage, abortSignal, offset, mintAddress }: {
59
59
  publicKey: PublicKey,
60
60
  connection: Connection,
61
61
  encryptionService: EncryptionService,
62
62
  storage: Storage,
63
- mintAddress: PublicKey,
63
+ mintAddress: PublicKey | string,
64
64
  abortSignal?: AbortSignal
65
65
  offset?: number
66
66
  }): Promise<Utxo[]> {
@@ -68,9 +68,21 @@ export async function getUtxosSPL({ publicKey, connection, encryptionService, st
68
68
  let valid_strings: string[] = []
69
69
  let history_indexes: number[] = []
70
70
  let publicKey_ata: PublicKey
71
+
72
+ if (typeof mintAddress == 'string') {
73
+ mintAddress = new PublicKey(mintAddress)
74
+ }
75
+
76
+ let token = tokens.find(t => t.pubkey.toString() == mintAddress.toString())
77
+ if (!token) {
78
+ throw new Error('token not found: ' + mintAddress.toString())
79
+ }
80
+
81
+ logger.debug('token name: ' + token.name + ', token address' + token.pubkey.toString())
82
+
71
83
  try {
72
84
  publicKey_ata = await getAssociatedTokenAddress(
73
- mintAddress,
85
+ token.pubkey,
74
86
  publicKey
75
87
  );
76
88
  let offsetStr = storage.getItem(LSK_FETCH_OFFSET + localstorageKey(publicKey_ata))
@@ -93,9 +105,10 @@ export async function getUtxosSPL({ publicKey, connection, encryptionService, st
93
105
  if (offset) {
94
106
  fetch_utxo_offset = Math.max(offset, fetch_utxo_offset)
95
107
  }
108
+ console.log(' ####fetch_utxo_offset', fetch_utxo_offset)
96
109
  let fetch_utxo_end = fetch_utxo_offset + FETCH_UTXOS_GROUP_SIZE
97
- let fetch_utxo_url = `${RELAYER_API_URL}/utxos/range?token=usdc&start=${fetch_utxo_offset}&end=${fetch_utxo_end}`
98
- let fetched = await fetchUserUtxos({ publicKey, connection, url: fetch_utxo_url, encryptionService, storage, publicKey_ata, initOffset: offset })
110
+ let fetch_utxo_url = `${RELAYER_API_URL}/utxos/range?token=${token.name}&start=${fetch_utxo_offset}&end=${fetch_utxo_end}`
111
+ let fetched = await fetchUserUtxos({ url: fetch_utxo_url, encryptionService, storage, publicKey_ata, tokenName: token.name })
99
112
  let am = 0
100
113
 
101
114
  const nonZeroUtxos: Utxo[] = [];
@@ -150,17 +163,20 @@ export async function getUtxosSPL({ publicKey, connection, encryptionService, st
150
163
  logger.debug(`valid_strings len after set: ${valid_strings.length}`)
151
164
  storage.setItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(publicKey_ata), JSON.stringify(valid_strings))
152
165
  // reorgnize
153
- return valid_utxos.filter(u => u.mintAddress == mintAddress.toString())
166
+ if (valid_utxos.length) {
167
+ console.log('filter mint', valid_utxos[0].mintAddress, token.pubkey.toString())
168
+ }
169
+ let filtered_utxos = valid_utxos.filter(u => u.mintAddress == token.pubkey.toString())
170
+ console.log('filtered_utxos.len', filtered_utxos.length)
171
+ return filtered_utxos
154
172
  }
155
173
 
156
- async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionService, publicKey_ata, initOffset }: {
157
- publicKey: PublicKey,
158
- connection: Connection,
174
+ async function fetchUserUtxos({ url, storage, encryptionService, publicKey_ata, tokenName }: {
159
175
  url: string,
160
176
  encryptionService: EncryptionService,
161
177
  storage: Storage,
162
178
  publicKey_ata: PublicKey
163
- initOffset: number
179
+ tokenName: string
164
180
  }): Promise<{
165
181
  encryptedOutputs: string[],
166
182
  utxos: Utxo[],
@@ -212,7 +228,7 @@ async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionS
212
228
 
213
229
 
214
230
  let decryptionTaskTotal = data.total + cachedStringNum - roundStartIndex;
215
- let batchRes = await decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm)
231
+ let batchRes = await decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm, tokenName)
216
232
  decryptionTaskFinished += encryptedOutputs.length
217
233
  logger.debug('batchReslen', batchRes.length)
218
234
  for (let i = 0; i < batchRes.length; i++) {
@@ -230,7 +246,7 @@ async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionS
230
246
  if (decryptionTaskFinished % 100 == 0) {
231
247
  logger.info(`(decrypting cached utxo: ${decryptionTaskFinished + 1}/${decryptionTaskTotal}...)`)
232
248
  }
233
- let batchRes = await decrypt_outputs(cachedEncryptedOutputs, encryptionService, utxoKeypair, lightWasm)
249
+ let batchRes = await decrypt_outputs(cachedEncryptedOutputs, encryptionService, utxoKeypair, lightWasm, tokenName)
234
250
  decryptionTaskFinished += cachedEncryptedOutputs.length
235
251
  logger.debug('cachedbatchReslen', batchRes.length, ' source', cachedEncryptedOutputs.length)
236
252
  for (let i = 0; i < batchRes.length; i++) {
@@ -346,11 +362,23 @@ async function areUtxosSpent(
346
362
  // Calculate total balance
347
363
  export function getBalanceFromUtxosSPL(utxos: Utxo[]): {
348
364
  base_units: number
365
+ amount: number
349
366
  /** @deprecated use base_units instead */
350
367
  lamports: number
351
368
  } {
369
+ if (!utxos.length) {
370
+ return { base_units: 0, amount: 0, lamports: 0 }
371
+ }
372
+ let token = tokens.find(t => t.pubkey.toString() == utxos[0].mintAddress.toString())
373
+ if (!token) {
374
+ throw new Error('token not found for ' + utxos[0].mintAddress.toString())
375
+ }
352
376
  const totalBalance = utxos.reduce((sum, utxo) => sum.add(utxo.amount), new BN(0));
353
- return { base_units: totalBalance.toNumber(), lamports: totalBalance.toNumber() }
377
+ return {
378
+ base_units: totalBalance.toNumber(),
379
+ lamports: totalBalance.toNumber(),
380
+ amount: totalBalance.toNumber() / token.units_per_token
381
+ }
354
382
  }
355
383
 
356
384
  // Decrypt single output to Utxo
@@ -454,6 +482,7 @@ async function decrypt_outputs(
454
482
  encryptionService: EncryptionService,
455
483
  utxoKeypair: UtxoKeypair,
456
484
  lightWasm: any,
485
+ tokenName: string
457
486
  ): Promise<DecryptRes[]> {
458
487
  let results: DecryptRes[] = [];
459
488
 
@@ -485,7 +514,7 @@ async function decrypt_outputs(
485
514
  let url = RELAYER_API_URL + `/utxos/indices`
486
515
  let res = await fetch(url, {
487
516
  method: 'POST', headers: { "Content-Type": "application/json" },
488
- body: JSON.stringify({ encrypted_outputs, token: 'usdc' })
517
+ body: JSON.stringify({ encrypted_outputs, token: tokenName })
489
518
  })
490
519
  let j = await res.json()
491
520
  if (!j.indices || !Array.isArray(j.indices) || j.indices.length != encrypted_outputs.length) {
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@ import { deposit } from './deposit.js';
3
3
  import { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
4
4
  import { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
5
5
 
6
- import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, USDC_MINT } from './utils/constants.js';
6
+ import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, SplList, TokenList, tokens, USDC_MINT } from './utils/constants.js';
7
7
  import { logger, type LoggerFn, setLogger } from './utils/logger.js';
8
8
  import { EncryptionService } from './utils/encryption.js';
9
9
  import { WasmFactory } from '@lightprotocol/hasher.rs';
@@ -70,10 +70,9 @@ export class PrivacyCash {
70
70
  storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(this.publicKey))
71
71
  storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(this.publicKey))
72
72
  // spl
73
- let mintAddresses = [USDC_MINT]
74
- for (let mintAddress of mintAddresses) {
73
+ for (let token of tokens) {
75
74
  let ata = await getAssociatedTokenAddress(
76
- mintAddress,
75
+ token.pubkey,
77
76
  this.publicKey
78
77
  );
79
78
  storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(ata))
@@ -206,7 +205,7 @@ export class PrivacyCash {
206
205
  }
207
206
 
208
207
  /**
209
- * Returns the amount of lamports current wallet has in Privacy Cash.
208
+ * Returns the amount of base unites current wallet has in Privacy Cash.
210
209
  */
211
210
  async getPrivateBalanceUSDC() {
212
211
  logger.info('getting private balance')
@@ -216,6 +215,22 @@ export class PrivacyCash {
216
215
  return getBalanceFromUtxosSPL(utxos)
217
216
  }
218
217
 
218
+ /**
219
+ * Returns the amount of base unites current wallet has in Privacy Cash.
220
+ */
221
+ async getPrivateBalanceSpl(mintAddress: PublicKey | string) {
222
+ this.isRuning = true
223
+ let utxos = await getUtxosSPL({
224
+ publicKey: this.publicKey,
225
+ connection: this.connection,
226
+ encryptionService: this.encryptionService,
227
+ storage,
228
+ mintAddress
229
+ })
230
+ this.isRuning = false
231
+ return getBalanceFromUtxosSPL(utxos)
232
+ }
233
+
219
234
  /**
220
235
  * Returns true if the code is running in a browser.
221
236
  */
@@ -235,6 +250,69 @@ export class PrivacyCash {
235
250
  await new Promise(r => setTimeout(r, 250));
236
251
  }
237
252
  }
253
+
254
+ /**
255
+ * Deposit SPL to the Privacy Cash.
256
+ */
257
+ async depositSPL({ base_units, mintAddress, amount }: {
258
+ base_units?: number,
259
+ amount?: number,
260
+ mintAddress: PublicKey | string
261
+ }) {
262
+ this.isRuning = true
263
+ logger.info('start depositting')
264
+ let lightWasm = await WasmFactory.getInstance()
265
+ let res = await depositSPL({
266
+ lightWasm,
267
+ base_units,
268
+ amount,
269
+ connection: this.connection,
270
+ encryptionService: this.encryptionService,
271
+ publicKey: this.publicKey,
272
+ transactionSigner: async (tx: VersionedTransaction) => {
273
+ tx.sign([this.keypair])
274
+ return tx
275
+ },
276
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
277
+ storage,
278
+ mintAddress
279
+ })
280
+ this.isRuning = false
281
+ return res
282
+ }
283
+
284
+ /**
285
+ * Withdraw SPL from the Privacy Cash.
286
+ */
287
+ async withdrawSPL({ base_units, mintAddress, recipientAddress, amount }: {
288
+ base_units?: number,
289
+ amount?: number,
290
+ mintAddress: PublicKey | string,
291
+ recipientAddress?: string
292
+ }) {
293
+ this.isRuning = true
294
+ logger.info('start withdrawing')
295
+ let lightWasm = await WasmFactory.getInstance()
296
+ let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey
297
+
298
+ let res = await withdrawSPL({
299
+ lightWasm,
300
+ base_units,
301
+ amount,
302
+ connection: this.connection,
303
+ encryptionService: this.encryptionService,
304
+ publicKey: this.publicKey,
305
+ recipient,
306
+ keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
307
+ storage,
308
+ mintAddress
309
+ })
310
+ console.log(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`)
311
+ this.isRuning = false
312
+ return res
313
+ }
314
+
315
+
238
316
  }
239
317
 
240
318
  function getSolanaKeypair(
@@ -25,4 +25,48 @@ export const SIGN_MESSAGE = `Privacy Money account sign in`
25
25
  export const LSK_FETCH_OFFSET = 'fetch_offset'
26
26
  export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs'
27
27
 
28
- export const USDC_MINT = process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')
28
+ export const USDC_MINT = process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')
29
+
30
+ const tokenList = ['sol', 'usdc', 'usdt', 'zec', 'ore'] as const;
31
+ export type TokenList = typeof tokenList[number];
32
+ const splList = ['usdc', 'usdt', 'ore'] as const;
33
+ export type SplList = typeof splList[number];
34
+ export type Token = {
35
+ name: 'sol' | 'usdc' | 'usdt' | 'zec' | 'ore'
36
+ prefix: string
37
+ units_per_token: number
38
+ pubkey: PublicKey
39
+ }
40
+ export const tokens: Token[] = [
41
+ {
42
+ name: 'sol',
43
+ pubkey: new PublicKey('So11111111111111111111111111111111111111112'),
44
+ prefix: '',
45
+ units_per_token: 1e9
46
+ },
47
+ {
48
+ name: 'usdc',
49
+ pubkey: process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
50
+ prefix: 'usdc_',
51
+ units_per_token: 1e6
52
+ },
53
+ {
54
+ name: 'usdt',
55
+ pubkey: process.env.NEXT_PUBLIC_USDT_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDT_MINT) : new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'),
56
+ prefix: 'usdt_',
57
+ units_per_token: 1e6
58
+ },
59
+ {
60
+ name: 'zec',
61
+ pubkey: process.env.NEXT_PUBLIC_ZEC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ZEC_MINT) : new PublicKey('A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS'),
62
+ prefix: 'zec_',
63
+ units_per_token: 1e8
64
+ }
65
+ ,
66
+ {
67
+ name: 'ore',
68
+ pubkey: process.env.NEXT_PUBLIC_ORE_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ORE_MINT) : new PublicKey('oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp'),
69
+ prefix: 'ore_',
70
+ units_per_token: 1e11
71
+ }
72
+ ]
@@ -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, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID } from './utils/constants.js';
9
+ import { ALT_ADDRESS, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID, SplList, tokens } from './utils/constants.js';
10
10
  import { EncryptionService, serializeProofAndExtData } from './utils/encryption.js';
11
11
  import { fetchMerkleProof, findNullifierPDAs, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs, getMintAddressField, getExtDataHash } from './utils/utils.js';
12
12
 
@@ -20,7 +20,6 @@ import { getAssociatedTokenAddressSync, getMint } from '@solana/spl-token';
20
20
  // Function to submit withdraw request to indexer backend
21
21
  async function submitWithdrawToIndexer(params: any): Promise<string> {
22
22
  try {
23
-
24
23
  const response = await fetch(`${RELAYER_API_URL}/withdraw/spl`, {
25
24
  method: 'POST',
26
25
  headers: {
@@ -48,43 +47,64 @@ async function submitWithdrawToIndexer(params: any): Promise<string> {
48
47
  type WithdrawParams = {
49
48
  publicKey: PublicKey,
50
49
  connection: Connection,
51
- base_units: number,
50
+ base_units?: number,
51
+ amount?: number,
52
52
  keyBasePath: string,
53
53
  encryptionService: EncryptionService,
54
54
  lightWasm: hasher.LightWasm,
55
55
  recipient: PublicKey,
56
- mintAddress: PublicKey,
57
- storage: Storage
56
+ mintAddress: PublicKey | string,
57
+ storage: Storage,
58
58
  }
59
59
 
60
- export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, encryptionService, keyBasePath, mintAddress }: WithdrawParams) {
61
- let mintInfo = await getMint(connection, mintAddress)
60
+ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, amount, encryptionService, keyBasePath, mintAddress }: WithdrawParams) {
61
+ if (typeof mintAddress == 'string') {
62
+ mintAddress = new PublicKey(mintAddress)
63
+ }
64
+ let token = tokens.find(t => t.pubkey.toString() == mintAddress.toString())
65
+ if (!token) {
66
+ throw new Error('token not found: ' + mintAddress.toString())
67
+ }
68
+
69
+ if (amount) {
70
+ base_units = amount * token.units_per_token
71
+ }
72
+
73
+ if (!base_units) {
74
+ throw new Error('You must input at leaset one of "base_units" or "amount"')
75
+ }
76
+
77
+
78
+ let mintInfo = await getMint(connection, token.pubkey)
62
79
  let units_per_token = 10 ** mintInfo.decimals
63
80
 
64
81
  let withdraw_fee_rate = await getConfig('withdraw_fee_rate')
65
- let withdraw_rent_fee = await getConfig('usdc_withdraw_rent_fee')
66
-
67
- let fee_base_units = Math.floor(base_units * withdraw_fee_rate + units_per_token * withdraw_rent_fee)
82
+ let withdraw_rent_fees = await getConfig('rent_fees')
83
+ let token_rent_fee = withdraw_rent_fees[token.name]
84
+ if (!token_rent_fee) {
85
+ throw new Error('can not find token_rent_fee for ' + token.name)
86
+ }
87
+ let fee_base_units = Math.floor(base_units * withdraw_fee_rate + units_per_token * token_rent_fee)
68
88
  base_units -= fee_base_units
69
89
 
70
90
  if (base_units <= 0) {
71
- throw new Error('withdraw amount too low')
91
+ throw new Error('withdraw amount too low, at least ' + fee_base_units / token_rent_fee)
72
92
  }
73
93
  let isPartial = false
74
94
 
75
95
  let recipient_ata = getAssociatedTokenAddressSync(
76
- mintAddress,
96
+ token.pubkey,
77
97
  recipient,
78
98
  true
79
99
  );
80
100
 
81
101
  let feeRecipientTokenAccount = getAssociatedTokenAddressSync(
82
- mintAddress,
102
+ token.pubkey,
83
103
  FEE_RECIPIENT,
84
104
  true
85
105
  );
86
106
  let signerTokenAccount = getAssociatedTokenAddressSync(
87
- mintAddress,
107
+ token.pubkey,
88
108
  publicKey
89
109
  );
90
110
 
@@ -93,14 +113,14 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
93
113
 
94
114
  // Derive tree account PDA with mint address for SPL (different from SOL version)
95
115
  const [treeAccount] = PublicKey.findProgramAddressSync(
96
- [Buffer.from('merkle_tree'), mintAddress.toBuffer()],
116
+ [Buffer.from('merkle_tree'), token.pubkey.toBuffer()],
97
117
  PROGRAM_ID
98
118
  );
99
119
 
100
120
  const { globalConfigAccount, treeTokenAccount } = getProgramAccounts()
101
121
 
102
122
  // Get current tree state
103
- const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState('usdc');
123
+ const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState(token.name);
104
124
  logger.debug(`Using tree root: ${root}`);
105
125
  logger.debug(`New UTXOs will be inserted at indices: ${currentNextIndex} and ${currentNextIndex + 1}`);
106
126
 
@@ -119,7 +139,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
119
139
  logger.debug('\nFetching existing UTXOs...');
120
140
  const mintUtxos = await getUtxosSPL({ connection, publicKey, encryptionService, storage, mintAddress });
121
141
 
122
- logger.debug(`Found ${mintUtxos.length} total UTXOs`);
142
+ logger.debug(`Found ${mintUtxos.length} total UTXOs for ${token.name}`);
123
143
 
124
144
  // Calculate and log total unspent UTXO balance
125
145
  const totalUnspentBalance = mintUtxos.reduce((sum, utxo) => sum.add(utxo.amount), new BN(0));
@@ -138,7 +158,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
138
158
  lightWasm,
139
159
  keypair: utxoKeypair,
140
160
  amount: '0',
141
- mintAddress: mintAddress.toString()
161
+ mintAddress: token.pubkey.toString()
142
162
  });
143
163
 
144
164
  const inputs = [firstInput, secondInput];
@@ -171,7 +191,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
171
191
  }
172
192
  // For real UTXOs, fetch the proof from API
173
193
  const commitment = await utxo.getCommitment();
174
- return fetchMerkleProof(commitment, 'usdc');
194
+ return fetchMerkleProof(commitment, token.name);
175
195
  })
176
196
  );
177
197
 
@@ -186,14 +206,14 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
186
206
  amount: changeAmount.toString(),
187
207
  keypair: utxoKeypairV2,
188
208
  index: currentNextIndex,
189
- mintAddress: mintAddress.toString()
209
+ mintAddress: token.pubkey.toString()
190
210
  }), // Change output
191
211
  new Utxo({
192
212
  lightWasm,
193
213
  amount: '0',
194
214
  keypair: utxoKeypairV2,
195
215
  index: currentNextIndex + 1,
196
- mintAddress: mintAddress.toString()
216
+ mintAddress: token.pubkey.toString()
197
217
  }) // Empty UTXO
198
218
  ];
199
219
 
@@ -255,7 +275,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
255
275
  encryptedOutput2: encryptedOutput2,
256
276
  fee: new BN(fee_base_units),
257
277
  feeRecipient: feeRecipientTokenAccount,
258
- mintAddress: mintAddress.toString()
278
+ mintAddress: token.pubkey.toString()
259
279
  };
260
280
  // Calculate the extDataHash with the encrypted outputs
261
281
  const calculatedExtDataHash = getExtDataHash(extData);
@@ -264,7 +284,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
264
284
  const input = {
265
285
  // Common transaction data
266
286
  root: root,
267
- mintAddress: getMintAddressField(mintAddress),// new mint address
287
+ mintAddress: getMintAddressField(token.pubkey),// new mint address
268
288
  publicAmount: publicAmountForCircuit.toString(), // Use proper field arithmetic result
269
289
  extDataHash: calculatedExtDataHash,
270
290
 
@@ -322,7 +342,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
322
342
  [Buffer.from("global_config")],
323
343
  PROGRAM_ID
324
344
  );
325
- const treeAta = getAssociatedTokenAddressSync(mintAddress, globalConfigPda, true);
345
+ const treeAta = getAssociatedTokenAddressSync(token.pubkey, globalConfigPda, true);
326
346
 
327
347
  // Prepare withdraw parameters for indexer backend
328
348
  const withdrawParams = {
@@ -342,7 +362,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
342
362
  senderAddress: publicKey.toString(),
343
363
  treeAta: treeAta.toString(),
344
364
  recipientAta: recipient_ata.toString(),
345
- mintAddress: mintAddress.toString(),
365
+ mintAddress: token.pubkey.toString(),
346
366
  feeRecipientTokenAccount: feeRecipientTokenAccount.toString()
347
367
  };
348
368
 
@@ -362,7 +382,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
362
382
  console.log(`retryTimes: ${retryTimes}`)
363
383
  await new Promise(resolve => setTimeout(resolve, itv * 1000));
364
384
  console.log('Fetching updated tree state...');
365
- let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=usdc')
385
+ let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=' + token.name)
366
386
  let resJson = await res.json()
367
387
  console.log('resJson:', resJson)
368
388
  if (resJson.exists) {