privacycash 1.0.21 → 1.1.1

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.
@@ -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
+ ]
package/src/withdraw.ts CHANGED
@@ -314,12 +314,12 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
314
314
  const encryptedOutputStr = Buffer.from(encryptedOutput1).toString('hex')
315
315
  let start = Date.now()
316
316
  while (true) {
317
- console.log(`retryTimes: ${retryTimes}`)
317
+ logger.info(`retryTimes: ${retryTimes}`)
318
318
  await new Promise(resolve => setTimeout(resolve, itv * 1000));
319
- console.log('Fetching updated tree state...');
319
+ logger.info('Fetching updated tree state...');
320
320
  let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr)
321
321
  let resJson = await res.json()
322
- console.log('resJson:', resJson)
322
+ logger.debug('resJson:', resJson)
323
323
  if (resJson.exists) {
324
324
  return { isPartial, tx: signature, recipient: recipient.toString(), amount_in_lamports, fee_in_lamports }
325
325
  }
@@ -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
 
@@ -359,12 +379,12 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
359
379
  const encryptedOutputStr = Buffer.from(encryptedOutput1).toString('hex')
360
380
  let start = Date.now()
361
381
  while (true) {
362
- console.log(`retryTimes: ${retryTimes}`)
382
+ logger.info(`retryTimes: ${retryTimes}`)
363
383
  await new Promise(resolve => setTimeout(resolve, itv * 1000));
364
- console.log('Fetching updated tree state...');
365
- let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=usdc')
384
+ logger.info('Fetching updated tree state...');
385
+ let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=' + token.name)
366
386
  let resJson = await res.json()
367
- console.log('resJson:', resJson)
387
+ logger.debug('resJson:', resJson)
368
388
  if (resJson.exists) {
369
389
  return { isPartial, tx: signature, recipient: recipient.toString(), base_units, fee_base_units }
370
390
  }