privacycash 1.0.17 → 1.0.19
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 -1
- package/__tests__/e2e.test.ts +5 -1
- package/__tests__/e2espl.test.ts +73 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +6 -10
- package/dist/deposit.js +4 -11
- package/dist/depositSPL.d.ts +19 -0
- package/dist/depositSPL.js +434 -0
- package/dist/exportUtils.d.ts +3 -0
- package/dist/exportUtils.js +3 -0
- package/dist/getUtxos.d.ts +2 -1
- package/dist/getUtxos.js +68 -79
- package/dist/getUtxosSPL.d.ts +31 -0
- package/dist/getUtxosSPL.js +369 -0
- package/dist/index.d.ts +31 -1
- package/dist/index.js +73 -3
- package/dist/models/utxo.js +10 -1
- package/dist/utils/address_lookup_table.d.ts +1 -0
- package/dist/utils/address_lookup_table.js +23 -0
- package/dist/utils/constants.d.ts +3 -2
- package/dist/utils/constants.js +5 -4
- package/dist/utils/encryption.d.ts +1 -1
- package/dist/utils/encryption.js +5 -3
- package/dist/utils/utils.d.ts +3 -2
- package/dist/utils/utils.js +26 -6
- package/dist/withdraw.js +3 -4
- package/dist/withdrawSPL.d.ts +22 -0
- package/dist/withdrawSPL.js +289 -0
- package/package.json +5 -3
- package/src/config.ts +7 -14
- package/src/deposit.ts +4 -11
- package/src/depositSPL.ts +556 -0
- package/src/exportUtils.ts +5 -1
- package/src/getUtxos.ts +73 -78
- package/src/getUtxosSPL.ts +495 -0
- package/src/index.ts +84 -3
- package/src/models/utxo.ts +10 -1
- package/src/utils/address_lookup_table.ts +54 -6
- package/src/utils/constants.ts +7 -5
- package/src/utils/encryption.ts +6 -3
- package/src/utils/utils.ts +29 -6
- package/src/withdraw.ts +4 -6
- package/src/withdrawSPL.ts +377 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { deposit } from './deposit.js';
|
|
3
3
|
import { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
|
|
4
|
-
import {
|
|
4
|
+
import { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
|
|
5
|
+
import { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, USDC_MINT } from './utils/constants.js';
|
|
5
6
|
import { logger, setLogger } from './utils/logger.js';
|
|
6
7
|
import { EncryptionService } from './utils/encryption.js';
|
|
7
8
|
import { WasmFactory } from '@lightprotocol/hasher.rs';
|
|
@@ -9,6 +10,9 @@ import bs58 from 'bs58';
|
|
|
9
10
|
import { withdraw } from './withdraw.js';
|
|
10
11
|
import { LocalStorage } from "node-localstorage";
|
|
11
12
|
import path from 'node:path';
|
|
13
|
+
import { depositSPL } from './depositSPL.js';
|
|
14
|
+
import { withdrawSPL } from './withdrawSPL.js';
|
|
15
|
+
import { getAssociatedTokenAddress } from '@solana/spl-token';
|
|
12
16
|
let storage = new LocalStorage(path.join(process.cwd(), "cache"));
|
|
13
17
|
export class PrivacyCash {
|
|
14
18
|
connection;
|
|
@@ -57,6 +61,13 @@ export class PrivacyCash {
|
|
|
57
61
|
}
|
|
58
62
|
storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(this.publicKey));
|
|
59
63
|
storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(this.publicKey));
|
|
64
|
+
// spl
|
|
65
|
+
let mintAddresses = [USDC_MINT];
|
|
66
|
+
for (let mintAddress of mintAddresses) {
|
|
67
|
+
let ata = await getAssociatedTokenAddress(mintAddress, this.publicKey);
|
|
68
|
+
storage.removeItem(LSK_FETCH_OFFSET + localstorageKey(ata));
|
|
69
|
+
storage.removeItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(ata));
|
|
70
|
+
}
|
|
60
71
|
return this;
|
|
61
72
|
}
|
|
62
73
|
/**
|
|
@@ -84,6 +95,30 @@ export class PrivacyCash {
|
|
|
84
95
|
this.isRuning = false;
|
|
85
96
|
return res;
|
|
86
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Deposit USDC to the Privacy Cash.
|
|
100
|
+
*/
|
|
101
|
+
async depositUSDC({ base_units }) {
|
|
102
|
+
this.isRuning = true;
|
|
103
|
+
logger.info('start depositting');
|
|
104
|
+
let lightWasm = await WasmFactory.getInstance();
|
|
105
|
+
let res = await depositSPL({
|
|
106
|
+
mintAddress: USDC_MINT,
|
|
107
|
+
lightWasm,
|
|
108
|
+
base_units: base_units,
|
|
109
|
+
connection: this.connection,
|
|
110
|
+
encryptionService: this.encryptionService,
|
|
111
|
+
publicKey: this.publicKey,
|
|
112
|
+
transactionSigner: async (tx) => {
|
|
113
|
+
tx.sign([this.keypair]);
|
|
114
|
+
return tx;
|
|
115
|
+
},
|
|
116
|
+
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
117
|
+
storage
|
|
118
|
+
});
|
|
119
|
+
this.isRuning = false;
|
|
120
|
+
return res;
|
|
121
|
+
}
|
|
87
122
|
/**
|
|
88
123
|
* Withdraw SOL from the Privacy Cash.
|
|
89
124
|
*
|
|
@@ -108,16 +143,51 @@ export class PrivacyCash {
|
|
|
108
143
|
this.isRuning = false;
|
|
109
144
|
return res;
|
|
110
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Withdraw USDC from the Privacy Cash.
|
|
148
|
+
*
|
|
149
|
+
* 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' })
|
|
150
|
+
*/
|
|
151
|
+
async withdrawUSDC({ base_units, recipientAddress }) {
|
|
152
|
+
this.isRuning = true;
|
|
153
|
+
logger.info('start withdrawing');
|
|
154
|
+
let lightWasm = await WasmFactory.getInstance();
|
|
155
|
+
let recipient = recipientAddress ? new PublicKey(recipientAddress) : this.publicKey;
|
|
156
|
+
let res = await withdrawSPL({
|
|
157
|
+
mintAddress: USDC_MINT,
|
|
158
|
+
lightWasm,
|
|
159
|
+
base_units,
|
|
160
|
+
connection: this.connection,
|
|
161
|
+
encryptionService: this.encryptionService,
|
|
162
|
+
publicKey: this.publicKey,
|
|
163
|
+
recipient,
|
|
164
|
+
keyBasePath: path.join(import.meta.dirname, '..', 'circuit2', 'transaction2'),
|
|
165
|
+
storage
|
|
166
|
+
});
|
|
167
|
+
console.log(`Withdraw successful. Recipient ${recipient} received ${base_units} USDC units`);
|
|
168
|
+
this.isRuning = false;
|
|
169
|
+
return res;
|
|
170
|
+
}
|
|
111
171
|
/**
|
|
112
172
|
* Returns the amount of lamports current wallet has in Privacy Cash.
|
|
113
173
|
*/
|
|
114
|
-
async getPrivateBalance() {
|
|
174
|
+
async getPrivateBalance(abortSignal) {
|
|
115
175
|
logger.info('getting private balance');
|
|
116
176
|
this.isRuning = true;
|
|
117
|
-
let utxos = await getUtxos({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage });
|
|
177
|
+
let utxos = await getUtxos({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, abortSignal });
|
|
118
178
|
this.isRuning = false;
|
|
119
179
|
return getBalanceFromUtxos(utxos);
|
|
120
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Returns the amount of lamports current wallet has in Privacy Cash.
|
|
183
|
+
*/
|
|
184
|
+
async getPrivateBalanceUSDC() {
|
|
185
|
+
logger.info('getting private balance');
|
|
186
|
+
this.isRuning = true;
|
|
187
|
+
let utxos = await getUtxosSPL({ publicKey: this.publicKey, connection: this.connection, encryptionService: this.encryptionService, storage, mintAddress: USDC_MINT });
|
|
188
|
+
this.isRuning = false;
|
|
189
|
+
return getBalanceFromUtxosSPL(utxos);
|
|
190
|
+
}
|
|
121
191
|
/**
|
|
122
192
|
* Returns true if the code is running in a browser.
|
|
123
193
|
*/
|
package/dist/models/utxo.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import BN from 'bn.js';
|
|
8
8
|
import { Keypair } from './keypair.js';
|
|
9
9
|
import { ethers } from 'ethers';
|
|
10
|
+
import { getMintAddressField } from '../utils/utils.js';
|
|
11
|
+
import { PublicKey } from '@solana/web3.js';
|
|
10
12
|
/**
|
|
11
13
|
* Simplified Utxo class inspired by Tornado Cash Nova
|
|
12
14
|
* Based on: https://github.com/tornadocash/tornado-nova/blob/f9264eeffe48bf5e04e19d8086ee6ec58cdf0d9e/src/utxo.js
|
|
@@ -40,7 +42,14 @@ export class Utxo {
|
|
|
40
42
|
this.version = version;
|
|
41
43
|
}
|
|
42
44
|
async getCommitment() {
|
|
43
|
-
return this.lightWasm.poseidonHashString([this.amount.toString(), this.keypair.pubkey.toString(), this.blinding.toString(), this.mintAddress]);
|
|
45
|
+
// return this.lightWasm.poseidonHashString([this.amount.toString(), this.keypair.pubkey.toString(), this.blinding.toString(), this.mintAddress]);
|
|
46
|
+
const mintAddressField = getMintAddressField(new PublicKey(this.mintAddress));
|
|
47
|
+
return this.lightWasm.poseidonHashString([
|
|
48
|
+
this.amount.toString(),
|
|
49
|
+
this.keypair.pubkey.toString(),
|
|
50
|
+
this.blinding.toString(),
|
|
51
|
+
mintAddressField
|
|
52
|
+
]);
|
|
44
53
|
}
|
|
45
54
|
async getNullifier() {
|
|
46
55
|
const commitmentValue = await this.getCommitment();
|
|
@@ -6,3 +6,4 @@ import { Connection, PublicKey } from '@solana/web3.js';
|
|
|
6
6
|
export declare function useExistingALT(connection: Connection, altAddress: PublicKey): Promise<{
|
|
7
7
|
value: any;
|
|
8
8
|
} | null>;
|
|
9
|
+
export declare function getProtocolAddressesWithMint(programId: PublicKey, authority: PublicKey, treeAta: PublicKey, feeRecipient: PublicKey, feeRecipientAta: PublicKey): PublicKey[];
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram, ComputeBudgetProgram } from '@solana/web3.js';
|
|
2
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
1
3
|
/**
|
|
2
4
|
* Helper function to use an existing ALT (recommended for production)
|
|
3
5
|
* Use create_alt.ts to create the ALT once, then hardcode the address and use this function
|
|
@@ -19,3 +21,24 @@ export async function useExistingALT(connection, altAddress) {
|
|
|
19
21
|
return null;
|
|
20
22
|
}
|
|
21
23
|
}
|
|
24
|
+
export function getProtocolAddressesWithMint(programId, authority, treeAta, feeRecipient, feeRecipientAta) {
|
|
25
|
+
// Derive global config PDA
|
|
26
|
+
const [globalConfigAccount] = PublicKey.findProgramAddressSync([Buffer.from('global_config')], programId);
|
|
27
|
+
// Derive tree accounts
|
|
28
|
+
const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree')], programId);
|
|
29
|
+
return [
|
|
30
|
+
// Core program accounts (constant)
|
|
31
|
+
programId,
|
|
32
|
+
treeAccount,
|
|
33
|
+
treeAta,
|
|
34
|
+
globalConfigAccount,
|
|
35
|
+
authority,
|
|
36
|
+
feeRecipient,
|
|
37
|
+
feeRecipientAta,
|
|
38
|
+
// System programs (constant)
|
|
39
|
+
SystemProgram.programId,
|
|
40
|
+
ComputeBudgetProgram.programId,
|
|
41
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
42
|
+
TOKEN_PROGRAM_ID,
|
|
43
|
+
];
|
|
44
|
+
}
|
|
@@ -2,13 +2,14 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
2
2
|
import BN from 'bn.js';
|
|
3
3
|
export declare const FIELD_SIZE: BN;
|
|
4
4
|
export declare const PROGRAM_ID: PublicKey;
|
|
5
|
-
export declare const DEPLOYER_ID: PublicKey;
|
|
6
5
|
export declare const FEE_RECIPIENT: PublicKey;
|
|
7
6
|
export declare const FETCH_UTXOS_GROUP_SIZE = 10000;
|
|
8
7
|
export declare const TRANSACT_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
|
|
8
|
+
export declare const TRANSACT_SPL_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
|
|
9
9
|
export declare const MERKLE_TREE_DEPTH = 26;
|
|
10
10
|
export declare const ALT_ADDRESS: PublicKey;
|
|
11
|
-
export declare const
|
|
11
|
+
export declare const RELAYER_API_URL: string;
|
|
12
12
|
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
|
+
export declare const USDC_MINT: PublicKey;
|
package/dist/utils/constants.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { PublicKey } from '@solana/web3.js';
|
|
2
2
|
import BN from 'bn.js';
|
|
3
3
|
export const FIELD_SIZE = new BN('21888242871839275222246405745257275088548364400416034343698204186575808495617');
|
|
4
|
-
export const PROGRAM_ID = new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
|
|
5
|
-
export const DEPLOYER_ID = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
|
|
4
|
+
export const PROGRAM_ID = process.env.NEXT_PUBLIC_PROGRAM_ID ? new PublicKey(process.env.NEXT_PUBLIC_PROGRAM_ID) : new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
|
|
6
5
|
export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
|
|
7
6
|
export const FETCH_UTXOS_GROUP_SIZE = 10_000;
|
|
8
7
|
export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
|
|
8
|
+
export const TRANSACT_SPL_IX_DISCRIMINATOR = Buffer.from([154, 66, 244, 204, 78, 225, 163, 151]);
|
|
9
9
|
export const MERKLE_TREE_DEPTH = 26;
|
|
10
|
-
export const ALT_ADDRESS = new PublicKey('
|
|
11
|
-
export const
|
|
10
|
+
export const ALT_ADDRESS = process.env.NEXT_PUBLIC_ALT_ADDRESS ? new PublicKey(process.env.NEXT_PUBLIC_ALT_ADDRESS) : new PublicKey('HEN49U2ySJ85Vc78qprSW9y6mFDhs1NczRxyppNHjofe');
|
|
11
|
+
export const RELAYER_API_URL = process.env.NEXT_PUBLIC_RELAYER_API_URL ?? 'https://api3.privacycash.org';
|
|
12
12
|
export const SIGN_MESSAGE = `Privacy Money account sign in`;
|
|
13
13
|
// localStorage cache keys
|
|
14
14
|
export const LSK_FETCH_OFFSET = 'fetch_offset';
|
|
15
15
|
export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs';
|
|
16
|
+
export const USDC_MINT = process.env.NEXT_PUBLIC_USDC_MINT ? new PublicKey(process.env.NEXT_PUBLIC_USDC_MINT) : new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
@@ -104,4 +104,4 @@ export declare class EncryptionService {
|
|
|
104
104
|
*/
|
|
105
105
|
getUtxoPrivateKeyV2(): string;
|
|
106
106
|
}
|
|
107
|
-
export declare function serializeProofAndExtData(proof: any, extData: any): Buffer<ArrayBuffer>;
|
|
107
|
+
export declare function serializeProofAndExtData(proof: any, extData: any, isSpl?: boolean): Buffer<ArrayBuffer>;
|
package/dist/utils/encryption.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Utxo } from '../models/utxo.js';
|
|
|
4
4
|
import { WasmFactory } from '@lightprotocol/hasher.rs';
|
|
5
5
|
import { Keypair as UtxoKeypair } from '../models/keypair.js';
|
|
6
6
|
import { keccak256 } from '@ethersproject/keccak256';
|
|
7
|
-
import { TRANSACT_IX_DISCRIMINATOR } from './constants.js';
|
|
7
|
+
import { TRANSACT_IX_DISCRIMINATOR, TRANSACT_SPL_IX_DISCRIMINATOR } from './constants.js';
|
|
8
8
|
import BN from 'bn.js';
|
|
9
9
|
/**
|
|
10
10
|
* Service for handling encryption and decryption of UTXO data
|
|
@@ -341,15 +341,17 @@ export class EncryptionService {
|
|
|
341
341
|
return this.utxoPrivateKeyV2;
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
|
-
export function serializeProofAndExtData(proof, extData) {
|
|
344
|
+
export function serializeProofAndExtData(proof, extData, isSpl = false) {
|
|
345
345
|
// Create the ExtDataMinified object for the program call (only extAmount and fee)
|
|
346
346
|
const extDataMinified = {
|
|
347
347
|
extAmount: extData.extAmount,
|
|
348
348
|
fee: extData.fee
|
|
349
349
|
};
|
|
350
|
+
// Use the appropriate discriminator based on whether this is SPL or native SOL
|
|
351
|
+
const discriminator = isSpl ? TRANSACT_SPL_IX_DISCRIMINATOR : TRANSACT_IX_DISCRIMINATOR;
|
|
350
352
|
// Use the same serialization approach as deposit script
|
|
351
353
|
const instructionData = Buffer.concat([
|
|
352
|
-
|
|
354
|
+
discriminator,
|
|
353
355
|
// Serialize proof
|
|
354
356
|
Buffer.from(proof.proofA),
|
|
355
357
|
Buffer.from(proof.proofB),
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare function getExtDataHash(extData: {
|
|
|
40
40
|
feeRecipient: string | PublicKey;
|
|
41
41
|
mintAddress: string | PublicKey;
|
|
42
42
|
}): Uint8Array;
|
|
43
|
-
export declare function fetchMerkleProof(commitment: string): Promise<{
|
|
43
|
+
export declare function fetchMerkleProof(commitment: string, tokenName?: string): Promise<{
|
|
44
44
|
pathElements: string[];
|
|
45
45
|
pathIndices: number[];
|
|
46
46
|
}>;
|
|
@@ -48,7 +48,7 @@ export declare function findNullifierPDAs(proof: any): {
|
|
|
48
48
|
nullifier0PDA: PublicKey;
|
|
49
49
|
nullifier1PDA: PublicKey;
|
|
50
50
|
};
|
|
51
|
-
export declare function queryRemoteTreeState(): Promise<{
|
|
51
|
+
export declare function queryRemoteTreeState(tokenName?: string): Promise<{
|
|
52
52
|
root: string;
|
|
53
53
|
nextIndex: number;
|
|
54
54
|
}>;
|
|
@@ -61,3 +61,4 @@ export declare function findCrossCheckNullifierPDAs(proof: any): {
|
|
|
61
61
|
nullifier2PDA: PublicKey;
|
|
62
62
|
nullifier3PDA: PublicKey;
|
|
63
63
|
};
|
|
64
|
+
export declare function getMintAddressField(mint: PublicKey): string;
|
package/dist/utils/utils.js
CHANGED
|
@@ -8,7 +8,7 @@ import BN from 'bn.js';
|
|
|
8
8
|
import * as borsh from 'borsh';
|
|
9
9
|
import { sha256 } from '@ethersproject/sha2';
|
|
10
10
|
import { PublicKey } from '@solana/web3.js';
|
|
11
|
-
import {
|
|
11
|
+
import { RELAYER_API_URL, PROGRAM_ID } from './constants.js';
|
|
12
12
|
import { logger } from './logger.js';
|
|
13
13
|
import { getConfig } from '../config.js';
|
|
14
14
|
/**
|
|
@@ -91,12 +91,16 @@ export function getExtDataHash(extData) {
|
|
|
91
91
|
return Buffer.from(hashHex.slice(2), 'hex');
|
|
92
92
|
}
|
|
93
93
|
// Function to fetch Merkle proof from API for a given commitment
|
|
94
|
-
export async function fetchMerkleProof(commitment) {
|
|
94
|
+
export async function fetchMerkleProof(commitment, tokenName) {
|
|
95
95
|
try {
|
|
96
96
|
logger.debug(`Fetching Merkle proof for commitment: ${commitment}`);
|
|
97
|
-
|
|
97
|
+
let url = `${RELAYER_API_URL}/merkle/proof/${commitment}`;
|
|
98
|
+
if (tokenName) {
|
|
99
|
+
url += '?token=' + tokenName;
|
|
100
|
+
}
|
|
101
|
+
const response = await fetch(url);
|
|
98
102
|
if (!response.ok) {
|
|
99
|
-
throw new Error(`Failed to fetch Merkle proof: ${
|
|
103
|
+
throw new Error(`Failed to fetch Merkle proof: ${url}`);
|
|
100
104
|
}
|
|
101
105
|
const data = await response.json();
|
|
102
106
|
logger.debug(`✓ Fetched Merkle proof with ${data.pathElements.length} elements`);
|
|
@@ -114,10 +118,14 @@ export function findNullifierPDAs(proof) {
|
|
|
114
118
|
return { nullifier0PDA, nullifier1PDA };
|
|
115
119
|
}
|
|
116
120
|
// Function to query remote tree state from indexer API
|
|
117
|
-
export async function queryRemoteTreeState() {
|
|
121
|
+
export async function queryRemoteTreeState(tokenName) {
|
|
118
122
|
try {
|
|
119
123
|
logger.debug('Fetching Merkle root and nextIndex from API...');
|
|
120
|
-
|
|
124
|
+
let url = `${RELAYER_API_URL}/merkle/root`;
|
|
125
|
+
if (tokenName) {
|
|
126
|
+
url += '?token=' + tokenName;
|
|
127
|
+
}
|
|
128
|
+
const response = await fetch(url);
|
|
121
129
|
if (!response.ok) {
|
|
122
130
|
throw new Error(`Failed to fetch Merkle root and nextIndex: ${response.status} ${response.statusText}`);
|
|
123
131
|
}
|
|
@@ -143,3 +151,15 @@ export function findCrossCheckNullifierPDAs(proof) {
|
|
|
143
151
|
const [nullifier3PDA] = PublicKey.findProgramAddressSync([Buffer.from("nullifier1"), Buffer.from(proof.inputNullifiers[0])], PROGRAM_ID);
|
|
144
152
|
return { nullifier2PDA, nullifier3PDA };
|
|
145
153
|
}
|
|
154
|
+
export function getMintAddressField(mint) {
|
|
155
|
+
const mintStr = mint.toString();
|
|
156
|
+
// Special case for SOL (system program)
|
|
157
|
+
if (mintStr === '11111111111111111111111111111112') {
|
|
158
|
+
return mintStr;
|
|
159
|
+
}
|
|
160
|
+
// For SPL tokens (USDC, USDT, etc): use first 31 bytes (248 bits)
|
|
161
|
+
// This provides better collision resistance than 8 bytes while still fitting in the field
|
|
162
|
+
// We will only suppport private SOL, USDC and USDT send, so there won't be any collision.
|
|
163
|
+
const mintBytes = mint.toBytes();
|
|
164
|
+
return new BN(mintBytes.slice(0, 31), 'be').toString();
|
|
165
|
+
}
|
package/dist/withdraw.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,
|
|
7
|
+
import { ALT_ADDRESS, FEE_RECIPIENT, FIELD_SIZE, RELAYER_API_URL, MERKLE_TREE_DEPTH } from './utils/constants.js';
|
|
8
8
|
import { serializeProofAndExtData } from './utils/encryption.js';
|
|
9
9
|
import { fetchMerkleProof, findNullifierPDAs, getExtDataHash, getProgramAccounts, queryRemoteTreeState, findCrossCheckNullifierPDAs } from './utils/utils.js';
|
|
10
10
|
import { getUtxos } from './getUtxos.js';
|
|
@@ -14,7 +14,7 @@ import { getConfig } from './config.js';
|
|
|
14
14
|
// Function to submit withdraw request to indexer backend
|
|
15
15
|
async function submitWithdrawToIndexer(params) {
|
|
16
16
|
try {
|
|
17
|
-
const response = await fetch(`${
|
|
17
|
+
const response = await fetch(`${RELAYER_API_URL}/withdraw`, {
|
|
18
18
|
method: 'POST',
|
|
19
19
|
headers: {
|
|
20
20
|
'Content-Type': 'application/json',
|
|
@@ -40,7 +40,6 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
40
40
|
amount_in_lamports -= fee_in_lamports;
|
|
41
41
|
let isPartial = false;
|
|
42
42
|
logger.debug('Encryption key generated from user keypair');
|
|
43
|
-
logger.debug(`Deployer wallet: ${DEPLOYER_ID.toString()}`);
|
|
44
43
|
const { treeAccount, treeTokenAccount, globalConfigAccount } = getProgramAccounts();
|
|
45
44
|
// Get current tree state
|
|
46
45
|
const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState();
|
|
@@ -257,7 +256,7 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
|
|
|
257
256
|
console.log(`retryTimes: ${retryTimes}`);
|
|
258
257
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
259
258
|
console.log('Fetching updated tree state...');
|
|
260
|
-
let res = await fetch(
|
|
259
|
+
let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr);
|
|
261
260
|
let resJson = await res.json();
|
|
262
261
|
console.log('resJson:', resJson);
|
|
263
262
|
if (resJson.exists) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import * as hasher from '@lightprotocol/hasher.rs';
|
|
3
|
+
import { EncryptionService } from './utils/encryption.js';
|
|
4
|
+
type WithdrawParams = {
|
|
5
|
+
publicKey: PublicKey;
|
|
6
|
+
connection: Connection;
|
|
7
|
+
base_units: number;
|
|
8
|
+
keyBasePath: string;
|
|
9
|
+
encryptionService: EncryptionService;
|
|
10
|
+
lightWasm: hasher.LightWasm;
|
|
11
|
+
recipient: PublicKey;
|
|
12
|
+
mintAddress: PublicKey;
|
|
13
|
+
storage: Storage;
|
|
14
|
+
};
|
|
15
|
+
export declare function withdrawSPL({ recipient, lightWasm, storage, publicKey, connection, base_units, encryptionService, keyBasePath, mintAddress }: WithdrawParams): Promise<{
|
|
16
|
+
isPartial: boolean;
|
|
17
|
+
tx: string;
|
|
18
|
+
recipient: string;
|
|
19
|
+
base_units: number;
|
|
20
|
+
fee_base_units: number;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|