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/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.j
|
|
|
2
2
|
import { deposit } from './deposit.js';
|
|
3
3
|
import { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
|
|
4
4
|
import { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
|
|
5
|
-
import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, USDC_MINT } from './utils/constants.js';
|
|
5
|
+
import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, tokens, USDC_MINT } from './utils/constants.js';
|
|
6
6
|
import { logger, setLogger } from './utils/logger.js';
|
|
7
7
|
import { EncryptionService } from './utils/encryption.js';
|
|
8
8
|
import { WasmFactory } from '@lightprotocol/hasher.rs';
|
|
@@ -62,9 +62,8 @@ export class PrivacyCash {
|
|
|
62
62
|
storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(this.publicKey));
|
|
63
63
|
storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(this.publicKey));
|
|
64
64
|
// spl
|
|
65
|
-
let
|
|
66
|
-
|
|
67
|
-
let ata = await getAssociatedTokenAddress(mintAddress, this.publicKey);
|
|
65
|
+
for (let token of tokens) {
|
|
66
|
+
let ata = await getAssociatedTokenAddress(token.pubkey, this.publicKey);
|
|
68
67
|
storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(ata));
|
|
69
68
|
storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(ata));
|
|
70
69
|
}
|
|
@@ -139,7 +138,7 @@ export class PrivacyCash {
|
|
|
139
138
|
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
140
139
|
storage
|
|
141
140
|
});
|
|
142
|
-
|
|
141
|
+
logger.debug(`Withdraw successful. Recipient ${recipient} received ${res.amount_in_lamports / LAMPORTS_PER_SOL} SOL, with ${res.fee_in_lamports / LAMPORTS_PER_SOL} SOL relayers fees`);
|
|
143
142
|
this.isRuning = false;
|
|
144
143
|
return res;
|
|
145
144
|
}
|
|
@@ -164,7 +163,7 @@ export class PrivacyCash {
|
|
|
164
163
|
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
165
164
|
storage
|
|
166
165
|
});
|
|
167
|
-
|
|
166
|
+
logger.debug(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`);
|
|
168
167
|
this.isRuning = false;
|
|
169
168
|
return res;
|
|
170
169
|
}
|
|
@@ -179,7 +178,7 @@ export class PrivacyCash {
|
|
|
179
178
|
return getBalanceFromUtxos(utxos);
|
|
180
179
|
}
|
|
181
180
|
/**
|
|
182
|
-
* Returns the amount of
|
|
181
|
+
* Returns the amount of base unites current wallet has in Privacy Cash.
|
|
183
182
|
*/
|
|
184
183
|
async getPrivateBalanceUSDC() {
|
|
185
184
|
logger.info('getting private balance');
|
|
@@ -188,6 +187,21 @@ export class PrivacyCash {
|
|
|
188
187
|
this.isRuning = false;
|
|
189
188
|
return getBalanceFromUtxosSPL(utxos);
|
|
190
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Returns the amount of base unites current wallet has in Privacy Cash.
|
|
192
|
+
*/
|
|
193
|
+
async getPrivateBalanceSpl(mintAddress) {
|
|
194
|
+
this.isRuning = true;
|
|
195
|
+
let utxos = await getUtxosSPL({
|
|
196
|
+
publicKey: this.publicKey,
|
|
197
|
+
connection: this.connection,
|
|
198
|
+
encryptionService: this.encryptionService,
|
|
199
|
+
storage,
|
|
200
|
+
mintAddress
|
|
201
|
+
});
|
|
202
|
+
this.isRuning = false;
|
|
203
|
+
return getBalanceFromUtxosSPL(utxos);
|
|
204
|
+
}
|
|
191
205
|
/**
|
|
192
206
|
* Returns true if the code is running in a browser.
|
|
193
207
|
*/
|
|
@@ -206,6 +220,55 @@ export class PrivacyCash {
|
|
|
206
220
|
await new Promise(r => setTimeout(r, 250));
|
|
207
221
|
}
|
|
208
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Deposit SPL to the Privacy Cash.
|
|
225
|
+
*/
|
|
226
|
+
async depositSPL({ base_units, mintAddress, amount }) {
|
|
227
|
+
this.isRuning = true;
|
|
228
|
+
logger.info('start depositting');
|
|
229
|
+
let lightWasm = await WasmFactory.getInstance();
|
|
230
|
+
let res = await depositSPL({
|
|
231
|
+
lightWasm,
|
|
232
|
+
base_units,
|
|
233
|
+
amount,
|
|
234
|
+
connection: this.connection,
|
|
235
|
+
encryptionService: this.encryptionService,
|
|
236
|
+
publicKey: this.publicKey,
|
|
237
|
+
transactionSigner: async (tx) => {
|
|
238
|
+
tx.sign([this.keypair]);
|
|
239
|
+
return tx;
|
|
240
|
+
},
|
|
241
|
+
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
242
|
+
storage,
|
|
243
|
+
mintAddress
|
|
244
|
+
});
|
|
245
|
+
this.isRuning = false;
|
|
246
|
+
return res;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Withdraw SPL from the Privacy Cash.
|
|
250
|
+
*/
|
|
251
|
+
async withdrawSPL({ base_units, mintAddress, recipientAddress, amount }) {
|
|
252
|
+
this.isRuning = true;
|
|
253
|
+
logger.info('start withdrawing');
|
|
254
|
+
let lightWasm = await WasmFactory.getInstance();
|
|
255
|
+
let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey;
|
|
256
|
+
let res = await withdrawSPL({
|
|
257
|
+
lightWasm,
|
|
258
|
+
base_units,
|
|
259
|
+
amount,
|
|
260
|
+
connection: this.connection,
|
|
261
|
+
encryptionService: this.encryptionService,
|
|
262
|
+
publicKey: this.publicKey,
|
|
263
|
+
recipient,
|
|
264
|
+
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
265
|
+
storage,
|
|
266
|
+
mintAddress
|
|
267
|
+
});
|
|
268
|
+
logger.debug(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`);
|
|
269
|
+
this.isRuning = false;
|
|
270
|
+
return res;
|
|
271
|
+
}
|
|
209
272
|
}
|
|
210
273
|
function getSolanaKeypair(secret) {
|
|
211
274
|
try {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { PublicKey, SystemProgram, ComputeBudgetProgram } from '@solana/web3.js';
|
|
2
2
|
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
3
|
+
import { logger } from './logger';
|
|
3
4
|
/**
|
|
4
5
|
* Helper function to use an existing ALT (recommended for production)
|
|
5
6
|
* Use create_alt.ts to create the ALT once, then hardcode the address and use this function
|
|
6
7
|
*/
|
|
7
8
|
export async function useExistingALT(connection, altAddress) {
|
|
8
9
|
try {
|
|
9
|
-
|
|
10
|
+
logger.debug(`Using existing ALT: ${altAddress.toString()}`);
|
|
10
11
|
const altAccount = await connection.getAddressLookupTable(altAddress);
|
|
11
12
|
if (altAccount.value) {
|
|
12
|
-
|
|
13
|
+
logger.debug(`✅ ALT found with ${altAccount.value.state.addresses.length} addresses`);
|
|
13
14
|
}
|
|
14
15
|
else {
|
|
15
|
-
|
|
16
|
+
logger.error('❌ ALT not found');
|
|
16
17
|
}
|
|
17
18
|
return altAccount;
|
|
18
19
|
}
|
|
@@ -13,3 +13,15 @@ export declare const SIGN_MESSAGE = "Privacy Money account sign in";
|
|
|
13
13
|
export declare const LSK_FETCH_OFFSET = "fetch_offset";
|
|
14
14
|
export declare const LSK_ENCRYPTED_OUTPUTS = "encrypted_outputs";
|
|
15
15
|
export declare const USDC_MINT: PublicKey;
|
|
16
|
+
declare const tokenList: readonly ["sol", "usdc", "usdt", "zec", "ore"];
|
|
17
|
+
export type TokenList = typeof tokenList[number];
|
|
18
|
+
declare const splList: readonly ["usdc", "usdt", "ore"];
|
|
19
|
+
export type SplList = typeof splList[number];
|
|
20
|
+
export type Token = {
|
|
21
|
+
name: 'sol' | 'usdc' | 'usdt' | 'zec' | 'ore';
|
|
22
|
+
prefix: string;
|
|
23
|
+
units_per_token: number;
|
|
24
|
+
pubkey: PublicKey;
|
|
25
|
+
};
|
|
26
|
+
export declare const tokens: Token[];
|
|
27
|
+
export {};
|
package/dist/utils/constants.js
CHANGED
|
@@ -14,3 +14,37 @@ export const SIGN_MESSAGE = `Privacy Money account sign in`;
|
|
|
14
14
|
export const LSK_FETCH_OFFSET = 'fetch_offset';
|
|
15
15
|
export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs';
|
|
16
16
|
export const USDC_MINT = process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
17
|
+
const tokenList = ['sol', 'usdc', 'usdt', 'zec', 'ore'];
|
|
18
|
+
const splList = ['usdc', 'usdt', 'ore'];
|
|
19
|
+
export const tokens = [
|
|
20
|
+
{
|
|
21
|
+
name: 'sol',
|
|
22
|
+
pubkey: new PublicKey('So11111111111111111111111111111111111111112'),
|
|
23
|
+
prefix: '',
|
|
24
|
+
units_per_token: 1e9
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'usdc',
|
|
28
|
+
pubkey: process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
|
|
29
|
+
prefix: 'usdc_',
|
|
30
|
+
units_per_token: 1e6
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'usdt',
|
|
34
|
+
pubkey: process.env.NEXT_PUBLIC_USDT_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDT_MINT) : new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'),
|
|
35
|
+
prefix: 'usdt_',
|
|
36
|
+
units_per_token: 1e6
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'zec',
|
|
40
|
+
pubkey: process.env.NEXT_PUBLIC_ZEC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ZEC_MINT) : new PublicKey('A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS'),
|
|
41
|
+
prefix: 'zec_',
|
|
42
|
+
units_per_token: 1e8
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'ore',
|
|
46
|
+
pubkey: process.env.NEXT_PUBLIC_ORE_MINT ? new PublicKey(process.env.NEXT_PUBLIC_ORE_MINT) : new PublicKey('oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp'),
|
|
47
|
+
prefix: 'ore_',
|
|
48
|
+
units_per_token: 1e11
|
|
49
|
+
}
|
|
50
|
+
];
|
package/dist/withdraw.js
CHANGED
|
@@ -253,12 +253,12 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
253
253
|
const encryptedOutputStr = Buffer.from(encryptedOutput1).toString('hex');
|
|
254
254
|
let start = Date.now();
|
|
255
255
|
while (true) {
|
|
256
|
-
|
|
256
|
+
logger.info(`retryTimes: ${retryTimes}`);
|
|
257
257
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
258
|
-
|
|
258
|
+
logger.info('Fetching updated tree state...');
|
|
259
259
|
let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr);
|
|
260
260
|
let resJson = await res.json();
|
|
261
|
-
|
|
261
|
+
logger.debug('resJson:', resJson);
|
|
262
262
|
if (resJson.exists) {
|
|
263
263
|
return { isPartial, tx: signature, recipient: recipient.toString(), amount_in_lamports, fee_in_lamports };
|
|
264
264
|
}
|
package/dist/withdrawSPL.d.ts
CHANGED
|
@@ -4,15 +4,16 @@ import { EncryptionService } from './utils/encryption.js';
|
|
|
4
4
|
type WithdrawParams = {
|
|
5
5
|
publicKey: PublicKey;
|
|
6
6
|
connection: Connection;
|
|
7
|
-
base_units
|
|
7
|
+
base_units?: number;
|
|
8
|
+
amount?: number;
|
|
8
9
|
keyBasePath: string;
|
|
9
10
|
encryptionService: EncryptionService;
|
|
10
11
|
lightWasm: hasher.LightWasm;
|
|
11
12
|
recipient: PublicKey;
|
|
12
|
-
mintAddress: PublicKey;
|
|
13
|
+
mintAddress: PublicKey | string;
|
|
13
14
|
storage: Storage;
|
|
14
15
|
};
|
|
15
|
-
export declare function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, encryptionService, keyBasePath, mintAddress }: WithdrawParams): Promise<{
|
|
16
|
+
export declare function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, amount, encryptionService, keyBasePath, mintAddress }: WithdrawParams): Promise<{
|
|
16
17
|
isPartial: boolean;
|
|
17
18
|
tx: string;
|
|
18
19
|
recipient: string;
|
package/dist/withdrawSPL.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Buffer } from 'buffer';
|
|
|
4
4
|
import { Keypair as UtxoKeypair } from './models/keypair.js';
|
|
5
5
|
import { Utxo } from './models/utxo.js';
|
|
6
6
|
import { parseProofToBytesArray, parseToBytesArray, prove } from './utils/prover.js';
|
|
7
|
-
import { ALT_ADDRESS, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID } from './utils/constants.js';
|
|
7
|
+
import { ALT_ADDRESS, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH, PROGRAM_ID, tokens } from './utils/constants.js';
|
|
8
8
|
import { serializeProofAndExtData } from './utils/encryption.js';
|
|
9
9
|
import { fetchMerkleProof, findNullifierPDAs, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs, getMintAddressField, getExtDataHash } from './utils/utils.js';
|
|
10
10
|
import { getUtxosSPL } from './getUtxosSPL.js';
|
|
@@ -36,26 +36,43 @@ async function submitWithdrawToIndexer(params) {
|
|
|
36
36
|
throw error;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, encryptionService, keyBasePath, mintAddress }) {
|
|
40
|
-
|
|
39
|
+
export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, amount, encryptionService, keyBasePath, mintAddress }) {
|
|
40
|
+
if (typeof mintAddress == 'string') {
|
|
41
|
+
mintAddress = new PublicKey(mintAddress);
|
|
42
|
+
}
|
|
43
|
+
let token = tokens.find(t => t.pubkey.toString() == mintAddress.toString());
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new Error('token not found: ' + mintAddress.toString());
|
|
46
|
+
}
|
|
47
|
+
if (amount) {
|
|
48
|
+
base_units = amount * token.units_per_token;
|
|
49
|
+
}
|
|
50
|
+
if (!base_units) {
|
|
51
|
+
throw new Error('You must input at leaset one of "base_units" or "amount"');
|
|
52
|
+
}
|
|
53
|
+
let mintInfo = await getMint(connection, token.pubkey);
|
|
41
54
|
let units_per_token = 10 ** mintInfo.decimals;
|
|
42
55
|
let withdraw_fee_rate = await getConfig('withdraw_fee_rate');
|
|
43
|
-
let
|
|
44
|
-
let
|
|
56
|
+
let withdraw_rent_fees = await getConfig('rent_fees');
|
|
57
|
+
let token_rent_fee = withdraw_rent_fees[token.name];
|
|
58
|
+
if (!token_rent_fee) {
|
|
59
|
+
throw new Error('can not find token_rent_fee for ' + token.name);
|
|
60
|
+
}
|
|
61
|
+
let fee_base_units = Math.floor(base_units * withdraw_fee_rate + units_per_token * token_rent_fee);
|
|
45
62
|
base_units -= fee_base_units;
|
|
46
63
|
if (base_units <= 0) {
|
|
47
|
-
throw new Error('withdraw amount too low');
|
|
64
|
+
throw new Error('withdraw amount too low, at least ' + fee_base_units / token_rent_fee);
|
|
48
65
|
}
|
|
49
66
|
let isPartial = false;
|
|
50
|
-
let recipient_ata = getAssociatedTokenAddressSync(
|
|
51
|
-
let feeRecipientTokenAccount = getAssociatedTokenAddressSync(
|
|
52
|
-
let signerTokenAccount = getAssociatedTokenAddressSync(
|
|
67
|
+
let recipient_ata = getAssociatedTokenAddressSync(token.pubkey, recipient, true);
|
|
68
|
+
let feeRecipientTokenAccount = getAssociatedTokenAddressSync(token.pubkey, FEE_RECIPIENT, true);
|
|
69
|
+
let signerTokenAccount = getAssociatedTokenAddressSync(token.pubkey, publicKey);
|
|
53
70
|
logger.debug('Encryption key generated from user keypair');
|
|
54
71
|
// Derive tree account PDA with mint address for SPL (different from SOL version)
|
|
55
|
-
const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree'),
|
|
72
|
+
const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree'), token.pubkey.toBuffer()], PROGRAM_ID);
|
|
56
73
|
const { globalConfigAccount, treeTokenAccount } = getProgramAccounts();
|
|
57
74
|
// Get current tree state
|
|
58
|
-
const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState(
|
|
75
|
+
const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState(token.name);
|
|
59
76
|
logger.debug(`Using tree root: ${root}`);
|
|
60
77
|
logger.debug(`New UTXOs will be inserted at indices: ${currentNextIndex} and ${currentNextIndex + 1}`);
|
|
61
78
|
// Generate a deterministic private key derived from the wallet keypair
|
|
@@ -69,7 +86,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
69
86
|
// Fetch existing UTXOs for this user
|
|
70
87
|
logger.debug('\nFetching existing UTXOs...');
|
|
71
88
|
const mintUtxos = await getUtxosSPL({ connection, publicKey, encryptionService, storage, mintAddress });
|
|
72
|
-
logger.debug(`Found ${mintUtxos.length} total UTXOs`);
|
|
89
|
+
logger.debug(`Found ${mintUtxos.length} total UTXOs for ${token.name}`);
|
|
73
90
|
// Calculate and log total unspent UTXO balance
|
|
74
91
|
const totalUnspentBalance = mintUtxos.reduce((sum, utxo) => sum.add(utxo.amount), new BN(0));
|
|
75
92
|
logger.debug(`Total unspent UTXO balance before: ${totalUnspentBalance.toString()} lamports (${totalUnspentBalance.toNumber() / 1e9} SOL)`);
|
|
@@ -84,7 +101,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
84
101
|
lightWasm,
|
|
85
102
|
keypair: utxoKeypair,
|
|
86
103
|
amount: '0',
|
|
87
|
-
mintAddress:
|
|
104
|
+
mintAddress: token.pubkey.toString()
|
|
88
105
|
});
|
|
89
106
|
const inputs = [firstInput, secondInput];
|
|
90
107
|
logger.debug(`firstInput index: ${firstInput.index}, commitment: ${firstInput.getCommitment()}`);
|
|
@@ -113,7 +130,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
113
130
|
}
|
|
114
131
|
// For real UTXOs, fetch the proof from API
|
|
115
132
|
const commitment = await utxo.getCommitment();
|
|
116
|
-
return fetchMerkleProof(commitment,
|
|
133
|
+
return fetchMerkleProof(commitment, token.name);
|
|
117
134
|
}));
|
|
118
135
|
// Extract path elements and indices
|
|
119
136
|
const inputMerklePathElements = inputMerkleProofs.map(proof => proof.pathElements);
|
|
@@ -125,14 +142,14 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
125
142
|
amount: changeAmount.toString(),
|
|
126
143
|
keypair: utxoKeypairV2,
|
|
127
144
|
index: currentNextIndex,
|
|
128
|
-
mintAddress:
|
|
145
|
+
mintAddress: token.pubkey.toString()
|
|
129
146
|
}), // Change output
|
|
130
147
|
new Utxo({
|
|
131
148
|
lightWasm,
|
|
132
149
|
amount: '0',
|
|
133
150
|
keypair: utxoKeypairV2,
|
|
134
151
|
index: currentNextIndex + 1,
|
|
135
|
-
mintAddress:
|
|
152
|
+
mintAddress: token.pubkey.toString()
|
|
136
153
|
}) // Empty UTXO
|
|
137
154
|
];
|
|
138
155
|
// For withdrawals, extAmount is negative (funds leaving the system)
|
|
@@ -185,7 +202,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
185
202
|
encryptedOutput2: encryptedOutput2,
|
|
186
203
|
fee: new BN(fee_base_units),
|
|
187
204
|
feeRecipient: feeRecipientTokenAccount,
|
|
188
|
-
mintAddress:
|
|
205
|
+
mintAddress: token.pubkey.toString()
|
|
189
206
|
};
|
|
190
207
|
// Calculate the extDataHash with the encrypted outputs
|
|
191
208
|
const calculatedExtDataHash = getExtDataHash(extData);
|
|
@@ -193,7 +210,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
193
210
|
const input = {
|
|
194
211
|
// Common transaction data
|
|
195
212
|
root: root,
|
|
196
|
-
mintAddress: getMintAddressField(
|
|
213
|
+
mintAddress: getMintAddressField(token.pubkey), // new mint address
|
|
197
214
|
publicAmount: publicAmountForCircuit.toString(), // Use proper field arithmetic result
|
|
198
215
|
extDataHash: calculatedExtDataHash,
|
|
199
216
|
// Input UTXO data (UTXOs being spent) - ensure all values are in decimal format
|
|
@@ -239,7 +256,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
239
256
|
const serializedProof = serializeProofAndExtData(proofToSubmit, extData, true);
|
|
240
257
|
logger.debug(`Total instruction data size: ${serializedProof.length} bytes`);
|
|
241
258
|
const [globalConfigPda, globalConfigPdaBump] = await PublicKey.findProgramAddressSync([Buffer.from("global_config")], PROGRAM_ID);
|
|
242
|
-
const treeAta = getAssociatedTokenAddressSync(
|
|
259
|
+
const treeAta = getAssociatedTokenAddressSync(token.pubkey, globalConfigPda, true);
|
|
243
260
|
// Prepare withdraw parameters for indexer backend
|
|
244
261
|
const withdrawParams = {
|
|
245
262
|
serializedProof: serializedProof.toString('base64'),
|
|
@@ -258,7 +275,7 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
258
275
|
senderAddress: publicKey.toString(),
|
|
259
276
|
treeAta: treeAta.toString(),
|
|
260
277
|
recipientAta: recipient_ata.toString(),
|
|
261
|
-
mintAddress:
|
|
278
|
+
mintAddress: token.pubkey.toString(),
|
|
262
279
|
feeRecipientTokenAccount: feeRecipientTokenAccount.toString()
|
|
263
280
|
};
|
|
264
281
|
logger.debug('Prepared withdraw parameters for indexer backend');
|
|
@@ -272,12 +289,12 @@ export async function withdrawSPL({ recipient, lightWasm, storage, publicKey, co
|
|
|
272
289
|
const encryptedOutputStr = Buffer.from(encryptedOutput1).toString('hex');
|
|
273
290
|
let start = Date.now();
|
|
274
291
|
while (true) {
|
|
275
|
-
|
|
292
|
+
logger.info(`retryTimes: ${retryTimes}`);
|
|
276
293
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
277
|
-
|
|
278
|
-
let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=
|
|
294
|
+
logger.info('Fetching updated tree state...');
|
|
295
|
+
let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=' + token.name);
|
|
279
296
|
let resJson = await res.json();
|
|
280
|
-
|
|
297
|
+
logger.debug('resJson:', resJson);
|
|
281
298
|
if (resJson.exists) {
|
|
282
299
|
return { isPartial, tx: signature, recipient: recipient.toString(), base_units, fee_base_units };
|
|
283
300
|
}
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -5,6 +5,7 @@ type Config = {
|
|
|
5
5
|
withdraw_rent_fee: number
|
|
6
6
|
deposit_fee_rate: number
|
|
7
7
|
usdc_withdraw_rent_fee: number
|
|
8
|
+
rent_fees: any
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
let config: Config | undefined
|
|
@@ -14,7 +15,7 @@ export async function getConfig<K extends keyof Config>(key: K): Promise<Config[
|
|
|
14
15
|
const res = await fetch(RELAYER_API_URL + '/config')
|
|
15
16
|
config = await res.json()
|
|
16
17
|
}
|
|
17
|
-
if (typeof config![key]
|
|
18
|
+
if (typeof config![key] == 'undefined') {
|
|
18
19
|
throw new Error(`can not get ${key} from ${RELAYER_API_URL}/config`)
|
|
19
20
|
}
|
|
20
21
|
return config![key]
|
package/src/deposit.ts
CHANGED
|
@@ -67,6 +67,7 @@ type DepositParams = {
|
|
|
67
67
|
export async function deposit({ lightWasm, storage, keyBasePath, publicKey, connection, amount_in_lamports, encryptionService, transactionSigner, referrer }: DepositParams) {
|
|
68
68
|
// check limit
|
|
69
69
|
let limitAmount = await checkDepositLimit(connection)
|
|
70
|
+
|
|
70
71
|
if (limitAmount && amount_in_lamports > limitAmount * LAMPORTS_PER_SOL) {
|
|
71
72
|
throw new Error(`Don't deposit more than ${limitAmount} SOL`)
|
|
72
73
|
}
|
|
@@ -451,11 +452,11 @@ async function checkDepositLimit(connection: Connection) {
|
|
|
451
452
|
const accountInfo = await connection.getAccountInfo(treeAccount);
|
|
452
453
|
|
|
453
454
|
if (!accountInfo) {
|
|
454
|
-
console.error('❌ Tree account not found. Make sure the program is initialized.');
|
|
455
|
+
console.error('❌ Tree account not found. Make sure the program is initialized.' + PROGRAM_ID);
|
|
455
456
|
return;
|
|
456
457
|
}
|
|
457
458
|
|
|
458
|
-
|
|
459
|
+
logger.debug(`Account data size: ${accountInfo.data.length} bytes`);
|
|
459
460
|
const authority = new PublicKey(accountInfo.data.slice(8, 40));
|
|
460
461
|
const nextIndex = new BN(accountInfo.data.slice(40, 48), 'le');
|
|
461
462
|
const rootIndex = new BN(accountInfo.data.slice(4112, 4120), 'le');
|