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.
- package/README.md +5 -5
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -1
- package/dist/deposit.js +2 -2
- package/dist/depositSPL.d.ts +4 -3
- package/dist/depositSPL.js +75 -61
- package/dist/exportUtils.d.ts +1 -0
- package/dist/exportUtils.js +1 -0
- package/dist/getUtxosSPL.d.ts +3 -2
- package/dist/getUtxosSPL.js +32 -13
- package/dist/index.d.ts +35 -1
- package/dist/index.js +70 -7
- package/dist/utils/address_lookup_table.js +4 -3
- package/dist/utils/constants.d.ts +12 -0
- package/dist/utils/constants.js +34 -0
- package/dist/withdraw.js +3 -3
- package/dist/withdrawSPL.d.ts +4 -3
- package/dist/withdrawSPL.js +41 -24
- package/package.json +1 -1
- package/src/config.ts +2 -1
- package/src/deposit.ts +3 -2
- package/src/depositSPL.ts +82 -68
- package/src/exportUtils.ts +3 -1
- package/src/getUtxosSPL.ts +40 -16
- package/src/index.ts +85 -7
- package/src/utils/address_lookup_table.ts +4 -3
- package/src/utils/constants.ts +45 -1
- package/src/withdraw.ts +3 -3
- package/src/withdrawSPL.ts +49 -29
package/src/utils/constants.ts
CHANGED
|
@@ -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
|
-
|
|
317
|
+
logger.info(`retryTimes: ${retryTimes}`)
|
|
318
318
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
319
|
-
|
|
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
|
-
|
|
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
|
}
|
package/src/withdrawSPL.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, 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
|
|
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
|
-
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
96
|
+
token.pubkey,
|
|
77
97
|
recipient,
|
|
78
98
|
true
|
|
79
99
|
);
|
|
80
100
|
|
|
81
101
|
let feeRecipientTokenAccount = getAssociatedTokenAddressSync(
|
|
82
|
-
|
|
102
|
+
token.pubkey,
|
|
83
103
|
FEE_RECIPIENT,
|
|
84
104
|
true
|
|
85
105
|
);
|
|
86
106
|
let signerTokenAccount = getAssociatedTokenAddressSync(
|
|
87
|
-
|
|
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'),
|
|
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(
|
|
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:
|
|
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,
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
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:
|
|
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
|
-
|
|
382
|
+
logger.info(`retryTimes: ${retryTimes}`)
|
|
363
383
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
364
|
-
|
|
365
|
-
let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=
|
|
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
|
-
|
|
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
|
}
|