privacycash 1.0.19 → 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.
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -1
- package/dist/deposit.js +1 -1
- package/dist/depositSPL.d.ts +4 -3
- package/dist/depositSPL.js +57 -49
- package/dist/exportUtils.d.ts +1 -0
- package/dist/exportUtils.js +1 -0
- package/dist/getUtxos.d.ts +2 -1
- package/dist/getUtxos.js +10 -3
- package/dist/getUtxosSPL.d.ts +4 -2
- package/dist/getUtxosSPL.js +44 -12
- package/dist/index.d.ts +35 -1
- package/dist/index.js +68 -5
- package/dist/utils/constants.d.ts +13 -1
- package/dist/utils/constants.js +35 -1
- package/dist/withdrawSPL.d.ts +4 -3
- package/dist/withdrawSPL.js +38 -21
- package/package.json +1 -1
- package/src/config.ts +2 -1
- package/src/deposit.ts +2 -1
- package/src/depositSPL.ts +63 -53
- package/src/exportUtils.ts +3 -1
- package/src/getUtxos.ts +13 -3
- package/src/getUtxosSPL.ts +52 -14
- package/src/index.ts +83 -5
- package/src/utils/constants.ts +46 -2
- package/src/withdrawSPL.ts +46 -26
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -5,7 +5,7 @@ export async function getConfig(key) {
|
|
|
5
5
|
const res = await fetch(RELAYER_API_URL + '/config');
|
|
6
6
|
config = await res.json();
|
|
7
7
|
}
|
|
8
|
-
if (typeof config[key]
|
|
8
|
+
if (typeof config[key] == 'undefined') {
|
|
9
9
|
throw new Error(`can not get ${key} from ${RELAYER_API_URL}/config`);
|
|
10
10
|
}
|
|
11
11
|
return config[key];
|
package/dist/deposit.js
CHANGED
|
@@ -360,7 +360,7 @@ async function checkDepositLimit(connection) {
|
|
|
360
360
|
// Fetch the account data
|
|
361
361
|
const accountInfo = await connection.getAccountInfo(treeAccount);
|
|
362
362
|
if (!accountInfo) {
|
|
363
|
-
console.error('❌ Tree account not found. Make sure the program is initialized.');
|
|
363
|
+
console.error('❌ Tree account not found. Make sure the program is initialized.' + PROGRAM_ID);
|
|
364
364
|
return;
|
|
365
365
|
}
|
|
366
366
|
console.log(`Account data size: ${accountInfo.data.length} bytes`);
|
package/dist/depositSPL.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { Connection, PublicKey, VersionedTransaction } from '@solana/web3.js';
|
|
|
2
2
|
import * as hasher from '@lightprotocol/hasher.rs';
|
|
3
3
|
import { EncryptionService } from './utils/encryption.js';
|
|
4
4
|
type DepositParams = {
|
|
5
|
-
mintAddress: PublicKey;
|
|
5
|
+
mintAddress: PublicKey | string;
|
|
6
6
|
publicKey: PublicKey;
|
|
7
7
|
connection: Connection;
|
|
8
|
-
base_units
|
|
8
|
+
base_units?: number;
|
|
9
|
+
amount?: number;
|
|
9
10
|
storage: Storage;
|
|
10
11
|
encryptionService: EncryptionService;
|
|
11
12
|
keyBasePath: string;
|
|
@@ -13,7 +14,7 @@ type DepositParams = {
|
|
|
13
14
|
referrer?: string;
|
|
14
15
|
transactionSigner: (tx: VersionedTransaction) => Promise<VersionedTransaction>;
|
|
15
16
|
};
|
|
16
|
-
export declare function depositSPL({ lightWasm, storage, keyBasePath, publicKey, connection, base_units, encryptionService, transactionSigner, referrer, mintAddress }: DepositParams): Promise<{
|
|
17
|
+
export declare function depositSPL({ lightWasm, storage, keyBasePath, publicKey, connection, base_units, amount, encryptionService, transactionSigner, referrer, mintAddress }: DepositParams): Promise<{
|
|
17
18
|
tx: string;
|
|
18
19
|
}>;
|
|
19
20
|
export {};
|
package/dist/depositSPL.js
CHANGED
|
@@ -7,10 +7,10 @@ import { MerkleTree } from './utils/merkle_tree.js';
|
|
|
7
7
|
import { serializeProofAndExtData } from './utils/encryption.js';
|
|
8
8
|
import { Keypair as UtxoKeypair } from './models/keypair.js';
|
|
9
9
|
import { getUtxosSPL } from './getUtxosSPL.js';
|
|
10
|
-
import { FIELD_SIZE, FEE_RECIPIENT, MERKLE_TREE_DEPTH, RELAYER_API_URL, PROGRAM_ID, ALT_ADDRESS } from './utils/constants.js';
|
|
10
|
+
import { FIELD_SIZE, FEE_RECIPIENT, MERKLE_TREE_DEPTH, RELAYER_API_URL, PROGRAM_ID, ALT_ADDRESS, tokens } from './utils/constants.js';
|
|
11
11
|
import { useExistingALT } from './utils/address_lookup_table.js';
|
|
12
12
|
import { logger } from './utils/logger.js';
|
|
13
|
-
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync,
|
|
13
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, getAccount } from '@solana/spl-token';
|
|
14
14
|
// Function to relay pre-signed deposit transaction to indexer backend
|
|
15
15
|
async function relayDepositToIndexer({ signedTransaction, publicKey, referrer, mintAddress }) {
|
|
16
16
|
try {
|
|
@@ -22,7 +22,7 @@ async function relayDepositToIndexer({ signedTransaction, publicKey, referrer, m
|
|
|
22
22
|
if (referrer) {
|
|
23
23
|
params.referralWalletAddress = referrer;
|
|
24
24
|
}
|
|
25
|
-
params.mintAddress = mintAddress
|
|
25
|
+
params.mintAddress = mintAddress;
|
|
26
26
|
const response = await fetch(`${RELAYER_API_URL}/deposit/spl`, {
|
|
27
27
|
method: 'POST',
|
|
28
28
|
headers: {
|
|
@@ -46,38 +46,46 @@ async function relayDepositToIndexer({ signedTransaction, publicKey, referrer, m
|
|
|
46
46
|
throw error;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, connection, base_units, encryptionService, transactionSigner, referrer, mintAddress }) {
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, connection, base_units, amount, encryptionService, transactionSigner, referrer, mintAddress }) {
|
|
50
|
+
if (typeof mintAddress == 'string') {
|
|
51
|
+
mintAddress = new PublicKey(mintAddress);
|
|
52
|
+
}
|
|
53
|
+
let token = tokens.find(t => t.pubkey.toString() == mintAddress.toString());
|
|
54
|
+
if (!token) {
|
|
55
|
+
throw new Error('token not found: ' + mintAddress.toString());
|
|
56
|
+
}
|
|
57
|
+
if (amount) {
|
|
58
|
+
base_units = amount * token.units_per_token;
|
|
59
|
+
}
|
|
60
|
+
if (!base_units) {
|
|
61
|
+
throw new Error('You must input at least one of "base_units" or "amount"');
|
|
62
|
+
}
|
|
63
|
+
// let mintInfo = await getMint(connection, token.pubkey)
|
|
64
|
+
// let units_per_token = 10 ** mintInfo.decimals
|
|
52
65
|
let recipient = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
|
|
53
|
-
let recipient_ata = getAssociatedTokenAddressSync(
|
|
54
|
-
let feeRecipientTokenAccount = getAssociatedTokenAddressSync(
|
|
55
|
-
let signerTokenAccount = getAssociatedTokenAddressSync(
|
|
56
|
-
// Derive tree account PDA with mint address for SPL
|
|
57
|
-
const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree'),
|
|
58
|
-
let limitAmount = await checkDepositLimit(connection, treeAccount);
|
|
59
|
-
if (limitAmount && base_units > limitAmount *
|
|
60
|
-
throw new Error(`Don't deposit more than ${limitAmount}
|
|
66
|
+
let recipient_ata = getAssociatedTokenAddressSync(token.pubkey, recipient, true);
|
|
67
|
+
let feeRecipientTokenAccount = getAssociatedTokenAddressSync(token.pubkey, FEE_RECIPIENT, true);
|
|
68
|
+
let signerTokenAccount = getAssociatedTokenAddressSync(token.pubkey, publicKey);
|
|
69
|
+
// Derive tree account PDA with mint address for SPL
|
|
70
|
+
const [treeAccount] = PublicKey.findProgramAddressSync([Buffer.from('merkle_tree'), token.pubkey.toBuffer()], PROGRAM_ID);
|
|
71
|
+
let limitAmount = await checkDepositLimit(connection, treeAccount, token);
|
|
72
|
+
if (limitAmount && base_units > limitAmount * token.units_per_token) {
|
|
73
|
+
throw new Error(`Don't deposit more than ${limitAmount} ${token.name.toUpperCase()}`);
|
|
61
74
|
}
|
|
62
|
-
// check limit
|
|
63
|
-
// let limitAmount = await checkDepositLimit(connection)
|
|
64
|
-
// if (limitAmount && base_units > limitAmount * units_per_token) {
|
|
65
|
-
// throw new Error(`Don't deposit more than ${limitAmount} SOL`)
|
|
66
|
-
// }
|
|
67
75
|
// const base_units = amount_in_sol * units_per_token
|
|
68
76
|
const fee_base_units = 0;
|
|
69
77
|
logger.debug('Encryption key generated from user keypair');
|
|
70
78
|
logger.debug(`User wallet: ${publicKey.toString()}`);
|
|
71
|
-
logger.debug(`Deposit amount: ${base_units} base_units (${base_units / units_per_token}
|
|
72
|
-
logger.debug(`Calculated fee: ${fee_base_units} base_units (${fee_base_units / units_per_token}
|
|
79
|
+
logger.debug(`Deposit amount: ${base_units} base_units (${base_units / token.units_per_token} ${token.name.toUpperCase()})`);
|
|
80
|
+
logger.debug(`Calculated fee: ${fee_base_units} base_units (${fee_base_units / token.units_per_token} ${token.name.toUpperCase()})`);
|
|
73
81
|
// Check SPL balance
|
|
74
82
|
const accountInfo = await getAccount(connection, signerTokenAccount);
|
|
75
83
|
let balance = Number(accountInfo.amount);
|
|
76
|
-
logger.debug(`
|
|
84
|
+
logger.debug(`wallet balance: ${balance / token.units_per_token} ${token.name.toUpperCase()}`);
|
|
77
85
|
console.log('balance', balance);
|
|
78
86
|
console.log('base_units + fee_base_units', base_units + fee_base_units);
|
|
79
87
|
if (balance < (base_units + fee_base_units)) {
|
|
80
|
-
throw new Error(`Insufficient balance. Need at least ${(base_units + fee_base_units) / units_per_token}
|
|
88
|
+
throw new Error(`Insufficient balance. Need at least ${(base_units + fee_base_units) / token.units_per_token} ${token.name.toUpperCase()}.`);
|
|
81
89
|
}
|
|
82
90
|
// Check SOL balance
|
|
83
91
|
const solBalance = await connection.getBalance(publicKey);
|
|
@@ -89,7 +97,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
89
97
|
// Create the merkle tree with the pre-initialized poseidon hash
|
|
90
98
|
const tree = new MerkleTree(MERKLE_TREE_DEPTH, lightWasm);
|
|
91
99
|
// Initialize root and nextIndex variables
|
|
92
|
-
const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState(
|
|
100
|
+
const { root, nextIndex: currentNextIndex } = await queryRemoteTreeState(token.name);
|
|
93
101
|
logger.debug(`Using tree root: ${root}`);
|
|
94
102
|
logger.debug(`New UTXOs will be inserted at indices: ${currentNextIndex} and ${currentNextIndex + 1}`);
|
|
95
103
|
// Generate a deterministic private key derived from the wallet keypair
|
|
@@ -121,12 +129,12 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
121
129
|
new Utxo({
|
|
122
130
|
lightWasm,
|
|
123
131
|
keypair: utxoKeypair,
|
|
124
|
-
mintAddress:
|
|
132
|
+
mintAddress: token.pubkey.toString()
|
|
125
133
|
}),
|
|
126
134
|
new Utxo({
|
|
127
135
|
lightWasm,
|
|
128
136
|
keypair: utxoKeypair,
|
|
129
|
-
mintAddress:
|
|
137
|
+
mintAddress: token.pubkey.toString()
|
|
130
138
|
})
|
|
131
139
|
];
|
|
132
140
|
// Both inputs are dummy, so use mock indices and zero-filled Merkle paths
|
|
@@ -159,7 +167,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
159
167
|
lightWasm,
|
|
160
168
|
keypair: utxoKeypair,
|
|
161
169
|
amount: '0', // This UTXO will be inserted at currentNextIndex
|
|
162
|
-
mintAddress:
|
|
170
|
+
mintAddress: token.pubkey.toString()
|
|
163
171
|
});
|
|
164
172
|
inputs = [
|
|
165
173
|
firstUtxo, // Use the first existing UTXO
|
|
@@ -167,12 +175,12 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
167
175
|
];
|
|
168
176
|
// Fetch Merkle proofs for real UTXOs
|
|
169
177
|
const firstUtxoCommitment = await firstUtxo.getCommitment();
|
|
170
|
-
const firstUtxoMerkleProof = await fetchMerkleProof(firstUtxoCommitment,
|
|
178
|
+
const firstUtxoMerkleProof = await fetchMerkleProof(firstUtxoCommitment, token.name);
|
|
171
179
|
let secondUtxoMerkleProof;
|
|
172
180
|
if (secondUtxo.amount.gt(new BN(0))) {
|
|
173
181
|
// Second UTXO is real, fetch its proof
|
|
174
182
|
const secondUtxoCommitment = await secondUtxo.getCommitment();
|
|
175
|
-
secondUtxoMerkleProof = await fetchMerkleProof(secondUtxoCommitment,
|
|
183
|
+
secondUtxoMerkleProof = await fetchMerkleProof(secondUtxoCommitment, token.name);
|
|
176
184
|
logger.debug('\nSecond UTXO to be consolidated:');
|
|
177
185
|
await secondUtxo.log();
|
|
178
186
|
}
|
|
@@ -202,14 +210,14 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
202
210
|
amount: outputAmount,
|
|
203
211
|
keypair: utxoKeypair,
|
|
204
212
|
index: currentNextIndex, // This UTXO will be inserted at currentNextIndex
|
|
205
|
-
mintAddress:
|
|
213
|
+
mintAddress: token.pubkey.toString()
|
|
206
214
|
}), // Output with value (either deposit amount minus fee, or input amount minus fee)
|
|
207
215
|
new Utxo({
|
|
208
216
|
lightWasm,
|
|
209
217
|
amount: '0',
|
|
210
218
|
keypair: utxoKeypair,
|
|
211
219
|
index: currentNextIndex + 1, // This UTXO will be inserted at currentNextIndex
|
|
212
|
-
mintAddress:
|
|
220
|
+
mintAddress: token.pubkey.toString()
|
|
213
221
|
}) // Empty UTXO
|
|
214
222
|
];
|
|
215
223
|
// Verify this matches the circuit balance equation: sumIns + publicAmount = sumOuts
|
|
@@ -256,7 +264,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
256
264
|
encryptedOutput2: encryptedOutput2,
|
|
257
265
|
fee: new BN(fee_base_units),
|
|
258
266
|
feeRecipient: feeRecipientTokenAccount,
|
|
259
|
-
mintAddress:
|
|
267
|
+
mintAddress: token.pubkey.toString()
|
|
260
268
|
};
|
|
261
269
|
// Calculate the extDataHash with the encrypted outputs (now includes mintAddress for security)
|
|
262
270
|
const calculatedExtDataHash = getExtDataHash(extData);
|
|
@@ -264,7 +272,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
264
272
|
const input = {
|
|
265
273
|
// Common transaction data
|
|
266
274
|
root: root,
|
|
267
|
-
mintAddress: getMintAddressField(
|
|
275
|
+
mintAddress: getMintAddressField(token.pubkey), // new mint address
|
|
268
276
|
publicAmount: publicAmountForCircuit.toString(), // Use proper field arithmetic result
|
|
269
277
|
extDataHash: calculatedExtDataHash,
|
|
270
278
|
// Input UTXO data (UTXOs being spent) - ensure all values are in decimal format
|
|
@@ -307,7 +315,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
307
315
|
const { nullifier0PDA, nullifier1PDA } = findNullifierPDAs(proofToSubmit);
|
|
308
316
|
const { nullifier2PDA, nullifier3PDA } = findCrossCheckNullifierPDAs(proofToSubmit);
|
|
309
317
|
const [globalConfigPda, globalConfigPdaBump] = await PublicKey.findProgramAddressSync([Buffer.from("global_config")], PROGRAM_ID);
|
|
310
|
-
const treeAta = getAssociatedTokenAddressSync(
|
|
318
|
+
const treeAta = getAssociatedTokenAddressSync(token.pubkey, globalConfigPda, true);
|
|
311
319
|
const lookupTableAccount = await useExistingALT(connection, ALT_ADDRESS);
|
|
312
320
|
if (!lookupTableAccount?.value) {
|
|
313
321
|
throw new Error(`ALT not found at address ${ALT_ADDRESS.toString()} `);
|
|
@@ -327,7 +335,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
327
335
|
// signer
|
|
328
336
|
{ pubkey: publicKey, isSigner: true, isWritable: true },
|
|
329
337
|
// SPL token mint
|
|
330
|
-
{ pubkey:
|
|
338
|
+
{ pubkey: token.pubkey, isSigner: false, isWritable: false },
|
|
331
339
|
// signer's token account
|
|
332
340
|
{ pubkey: signerTokenAccount, isSigner: false, isWritable: true },
|
|
333
341
|
// recipient (placeholder)
|
|
@@ -369,7 +377,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
369
377
|
// Relay the pre-signed transaction to indexer backend
|
|
370
378
|
logger.info('submitting transaction to relayer...');
|
|
371
379
|
const signature = await relayDepositToIndexer({
|
|
372
|
-
mintAddress:
|
|
380
|
+
mintAddress: token.pubkey.toString(),
|
|
373
381
|
publicKey,
|
|
374
382
|
signedTransaction: serializedTransaction,
|
|
375
383
|
referrer
|
|
@@ -385,7 +393,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
385
393
|
logger.debug(`retryTimes: ${retryTimes}`);
|
|
386
394
|
await new Promise(resolve => setTimeout(resolve, itv * 1000));
|
|
387
395
|
logger.debug('Fetching updated tree state...');
|
|
388
|
-
let url = RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=
|
|
396
|
+
let url = RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr + '?token=' + token.name;
|
|
389
397
|
let res = await fetch(url);
|
|
390
398
|
let resJson = await res.json();
|
|
391
399
|
if (resJson.exists) {
|
|
@@ -398,7 +406,7 @@ export async function depositSPL({ lightWasm, storage, keyBasePath, publicKey, c
|
|
|
398
406
|
retryTimes++;
|
|
399
407
|
}
|
|
400
408
|
}
|
|
401
|
-
async function checkDepositLimit(connection, treeAccount) {
|
|
409
|
+
async function checkDepositLimit(connection, treeAccount, token) {
|
|
402
410
|
try {
|
|
403
411
|
// Fetch the account data
|
|
404
412
|
const accountInfo = await connection.getAccountInfo(treeAccount);
|
|
@@ -411,21 +419,21 @@ async function checkDepositLimit(connection, treeAccount) {
|
|
|
411
419
|
const rootIndex = new BN(accountInfo.data.slice(4112, 4120), 'le');
|
|
412
420
|
const maxDepositAmount = new BN(accountInfo.data.slice(4120, 4128), 'le');
|
|
413
421
|
const bump = accountInfo.data[4128];
|
|
414
|
-
// Convert to
|
|
415
|
-
const
|
|
416
|
-
const
|
|
417
|
-
const remainder = maxDepositAmount.mod(
|
|
418
|
-
// Format the
|
|
419
|
-
let
|
|
422
|
+
// Convert to SPL using BN division to handle large numbers
|
|
423
|
+
const unitesPerToken = new BN(token.units_per_token);
|
|
424
|
+
const maxDepositSpl = maxDepositAmount.div(unitesPerToken);
|
|
425
|
+
const remainder = maxDepositAmount.mod(unitesPerToken);
|
|
426
|
+
// Format the SPL amount with decimals
|
|
427
|
+
let amountFormatted = '1';
|
|
420
428
|
if (remainder.eq(new BN(0))) {
|
|
421
|
-
|
|
429
|
+
amountFormatted = maxDepositSpl.toString();
|
|
422
430
|
}
|
|
423
431
|
else {
|
|
424
|
-
// Handle fractional
|
|
425
|
-
const fractional = remainder.toNumber() /
|
|
426
|
-
|
|
432
|
+
// Handle fractional SPL by converting remainder to decimal
|
|
433
|
+
const fractional = remainder.toNumber() / token.units_per_token;
|
|
434
|
+
amountFormatted = `${maxDepositSpl.toString()}${fractional.toFixed(Math.log10(token.units_per_token)).substring(1)}`;
|
|
427
435
|
}
|
|
428
|
-
return Number(
|
|
436
|
+
return Number(amountFormatted);
|
|
429
437
|
}
|
|
430
438
|
catch (error) {
|
|
431
439
|
console.log('❌ Error reading deposit limit:', error);
|
package/dist/exportUtils.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
|
|
|
7
7
|
export { depositSPL } from './depositSPL.js';
|
|
8
8
|
export { withdrawSPL } from './withdrawSPL.js';
|
|
9
9
|
export { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
|
|
10
|
+
export { type TokenList, type SplList, tokens } from './utils/constants.js';
|
package/dist/exportUtils.js
CHANGED
|
@@ -7,3 +7,4 @@ export { getBalanceFromUtxos, getUtxos, localstorageKey } from './getUtxos.js';
|
|
|
7
7
|
export { depositSPL } from './depositSPL.js';
|
|
8
8
|
export { withdrawSPL } from './withdrawSPL.js';
|
|
9
9
|
export { getBalanceFromUtxosSPL, getUtxosSPL } from './getUtxosSPL.js';
|
|
10
|
+
export { tokens } from './utils/constants.js';
|
package/dist/getUtxos.d.ts
CHANGED
|
@@ -9,12 +9,13 @@ export declare function localstorageKey(key: PublicKey): string;
|
|
|
9
9
|
* @param setStatus A global state updator. Set live status message showing on webpage
|
|
10
10
|
* @returns Array of decrypted UTXOs that belong to the user
|
|
11
11
|
*/
|
|
12
|
-
export declare function getUtxos({ publicKey, connection, encryptionService, storage, abortSignal }: {
|
|
12
|
+
export declare function getUtxos({ publicKey, connection, encryptionService, storage, abortSignal, offset }: {
|
|
13
13
|
publicKey: PublicKey;
|
|
14
14
|
connection: Connection;
|
|
15
15
|
encryptionService: EncryptionService;
|
|
16
16
|
storage: Storage;
|
|
17
17
|
abortSignal?: AbortSignal;
|
|
18
|
+
offset?: number;
|
|
18
19
|
}): Promise<Utxo[]>;
|
|
19
20
|
/**
|
|
20
21
|
* Check if a UTXO has been spent
|
package/dist/getUtxos.js
CHANGED
|
@@ -26,7 +26,7 @@ let decryptionTaskFinished = 0;
|
|
|
26
26
|
* @param setStatus A global state updator. Set live status message showing on webpage
|
|
27
27
|
* @returns Array of decrypted UTXOs that belong to the user
|
|
28
28
|
*/
|
|
29
|
-
export async function getUtxos({ publicKey, connection, encryptionService, storage, abortSignal }) {
|
|
29
|
+
export async function getUtxos({ publicKey, connection, encryptionService, storage, abortSignal, offset }) {
|
|
30
30
|
let valid_utxos = [];
|
|
31
31
|
let valid_strings = [];
|
|
32
32
|
let history_indexes = [];
|
|
@@ -38,15 +38,22 @@ export async function getUtxos({ publicKey, connection, encryptionService, stora
|
|
|
38
38
|
roundStartIndex = 0;
|
|
39
39
|
}
|
|
40
40
|
decryptionTaskFinished = 0;
|
|
41
|
+
if (!offset) {
|
|
42
|
+
offset = 0;
|
|
43
|
+
}
|
|
44
|
+
roundStartIndex = Math.max(offset, roundStartIndex);
|
|
41
45
|
while (true) {
|
|
42
46
|
if (abortSignal?.aborted) {
|
|
43
47
|
throw new Error('aborted');
|
|
44
48
|
}
|
|
45
49
|
let offsetStr = storage.getItem(LSK_FETCH_OFFSET + localstorageKey(publicKey));
|
|
46
50
|
let fetch_utxo_offset = offsetStr ? Number(offsetStr) : 0;
|
|
51
|
+
if (offset) {
|
|
52
|
+
fetch_utxo_offset = Math.max(offset, fetch_utxo_offset);
|
|
53
|
+
}
|
|
47
54
|
let fetch_utxo_end = fetch_utxo_offset + FETCH_UTXOS_GROUP_SIZE;
|
|
48
55
|
let fetch_utxo_url = `${RELAYER_API_URL}/utxos/range?start=${fetch_utxo_offset}&end=${fetch_utxo_end}`;
|
|
49
|
-
let fetched = await fetchUserUtxos({ publicKey, connection, url: fetch_utxo_url, encryptionService, storage });
|
|
56
|
+
let fetched = await fetchUserUtxos({ publicKey, connection, url: fetch_utxo_url, encryptionService, storage, initOffset: offset });
|
|
50
57
|
let am = 0;
|
|
51
58
|
const nonZeroUtxos = [];
|
|
52
59
|
const nonZeroEncrypted = [];
|
|
@@ -96,7 +103,7 @@ export async function getUtxos({ publicKey, connection, encryptionService, stora
|
|
|
96
103
|
storage.setItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(publicKey), JSON.stringify(valid_strings));
|
|
97
104
|
return valid_utxos;
|
|
98
105
|
}
|
|
99
|
-
async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionService }) {
|
|
106
|
+
async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionService, initOffset }) {
|
|
100
107
|
const lightWasm = await WasmFactory.getInstance();
|
|
101
108
|
// Derive the UTXO keypair from the wallet keypair
|
|
102
109
|
const utxoPrivateKey = encryptionService.deriveUtxoPrivateKey();
|
package/dist/getUtxosSPL.d.ts
CHANGED
|
@@ -9,13 +9,14 @@ export declare function localstorageKey(key: PublicKey): string;
|
|
|
9
9
|
* @param setStatus A global state updator. Set live status message showing on webpage
|
|
10
10
|
* @returns Array of decrypted UTXOs that belong to the user
|
|
11
11
|
*/
|
|
12
|
-
export declare function getUtxosSPL({ publicKey, connection, encryptionService, storage,
|
|
12
|
+
export declare function getUtxosSPL({ publicKey, connection, encryptionService, storage, abortSignal, offset, mintAddress }: {
|
|
13
13
|
publicKey: PublicKey;
|
|
14
14
|
connection: Connection;
|
|
15
15
|
encryptionService: EncryptionService;
|
|
16
16
|
storage: Storage;
|
|
17
|
-
mintAddress: PublicKey;
|
|
17
|
+
mintAddress: PublicKey | string;
|
|
18
18
|
abortSignal?: AbortSignal;
|
|
19
|
+
offset?: number;
|
|
19
20
|
}): Promise<Utxo[]>;
|
|
20
21
|
/**
|
|
21
22
|
* Check if a UTXO has been spent
|
|
@@ -26,6 +27,7 @@ export declare function getUtxosSPL({ publicKey, connection, encryptionService,
|
|
|
26
27
|
export declare function isUtxoSpent(connection: Connection, utxo: Utxo): Promise<boolean>;
|
|
27
28
|
export declare function getBalanceFromUtxosSPL(utxos: Utxo[]): {
|
|
28
29
|
base_units: number;
|
|
30
|
+
amount: number;
|
|
29
31
|
/** @deprecated use base_units instead */
|
|
30
32
|
lamports: number;
|
|
31
33
|
};
|
package/dist/getUtxosSPL.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Keypair as UtxoKeypair } from './models/keypair.js';
|
|
|
4
4
|
import { WasmFactory } from '@lightprotocol/hasher.rs';
|
|
5
5
|
//@ts-ignore
|
|
6
6
|
import * as ffjavascript from 'ffjavascript';
|
|
7
|
-
import { FETCH_UTXOS_GROUP_SIZE, RELAYER_API_URL, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, PROGRAM_ID } from './utils/constants.js';
|
|
7
|
+
import { FETCH_UTXOS_GROUP_SIZE, RELAYER_API_URL, LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET, PROGRAM_ID, tokens } from './utils/constants.js';
|
|
8
8
|
import { logger } from './utils/logger.js';
|
|
9
9
|
import { getAssociatedTokenAddress } from '@solana/spl-token';
|
|
10
10
|
// Use type assertion for the utility functions (same pattern as in get_verification_keys.ts)
|
|
@@ -28,13 +28,21 @@ let decryptionTaskFinished = 0;
|
|
|
28
28
|
* @param setStatus A global state updator. Set live status message showing on webpage
|
|
29
29
|
* @returns Array of decrypted UTXOs that belong to the user
|
|
30
30
|
*/
|
|
31
|
-
export async function getUtxosSPL({ publicKey, connection, encryptionService, storage,
|
|
31
|
+
export async function getUtxosSPL({ publicKey, connection, encryptionService, storage, abortSignal, offset, mintAddress }) {
|
|
32
32
|
let valid_utxos = [];
|
|
33
33
|
let valid_strings = [];
|
|
34
34
|
let history_indexes = [];
|
|
35
35
|
let publicKey_ata;
|
|
36
|
+
if (typeof mintAddress == 'string') {
|
|
37
|
+
mintAddress = new PublicKey(mintAddress);
|
|
38
|
+
}
|
|
39
|
+
let token = tokens.find(t => t.pubkey.toString() == mintAddress.toString());
|
|
40
|
+
if (!token) {
|
|
41
|
+
throw new Error('token not found: ' + mintAddress.toString());
|
|
42
|
+
}
|
|
43
|
+
logger.debug('token name: ' + token.name + ', token address' + token.pubkey.toString());
|
|
36
44
|
try {
|
|
37
|
-
publicKey_ata = await getAssociatedTokenAddress(
|
|
45
|
+
publicKey_ata = await getAssociatedTokenAddress(token.pubkey, publicKey);
|
|
38
46
|
let offsetStr = storage.getItem(LSK_FETCH_OFFSET + localstorageKey(publicKey_ata));
|
|
39
47
|
if (offsetStr) {
|
|
40
48
|
roundStartIndex = Number(offsetStr);
|
|
@@ -43,15 +51,23 @@ export async function getUtxosSPL({ publicKey, connection, encryptionService, st
|
|
|
43
51
|
roundStartIndex = 0;
|
|
44
52
|
}
|
|
45
53
|
decryptionTaskFinished = 0;
|
|
54
|
+
if (!offset) {
|
|
55
|
+
offset = 0;
|
|
56
|
+
}
|
|
57
|
+
roundStartIndex = Math.max(offset, roundStartIndex);
|
|
46
58
|
while (true) {
|
|
47
59
|
if (abortSignal?.aborted) {
|
|
48
60
|
throw new Error('aborted');
|
|
49
61
|
}
|
|
50
62
|
let offsetStr = storage.getItem(LSK_FETCH_OFFSET + localstorageKey(publicKey_ata));
|
|
51
63
|
let fetch_utxo_offset = offsetStr ? Number(offsetStr) : 0;
|
|
64
|
+
if (offset) {
|
|
65
|
+
fetch_utxo_offset = Math.max(offset, fetch_utxo_offset);
|
|
66
|
+
}
|
|
67
|
+
console.log(' ####fetch_utxo_offset', fetch_utxo_offset);
|
|
52
68
|
let fetch_utxo_end = fetch_utxo_offset + FETCH_UTXOS_GROUP_SIZE;
|
|
53
|
-
let fetch_utxo_url = `${RELAYER_API_URL}/utxos/range?token
|
|
54
|
-
let fetched = await fetchUserUtxos({
|
|
69
|
+
let fetch_utxo_url = `${RELAYER_API_URL}/utxos/range?token=${token.name}&start=${fetch_utxo_offset}&end=${fetch_utxo_end}`;
|
|
70
|
+
let fetched = await fetchUserUtxos({ url: fetch_utxo_url, encryptionService, storage, publicKey_ata, tokenName: token.name });
|
|
55
71
|
let am = 0;
|
|
56
72
|
const nonZeroUtxos = [];
|
|
57
73
|
const nonZeroEncrypted = [];
|
|
@@ -107,9 +123,14 @@ export async function getUtxosSPL({ publicKey, connection, encryptionService, st
|
|
|
107
123
|
logger.debug(`valid_strings len after set: ${valid_strings.length}`);
|
|
108
124
|
storage.setItem(LSK_ENCRYPTED_OUTPUTS + localstorageKey(publicKey_ata), JSON.stringify(valid_strings));
|
|
109
125
|
// reorgnize
|
|
110
|
-
|
|
126
|
+
if (valid_utxos.length) {
|
|
127
|
+
console.log('filter mint', valid_utxos[0].mintAddress, token.pubkey.toString());
|
|
128
|
+
}
|
|
129
|
+
let filtered_utxos = valid_utxos.filter(u => u.mintAddress == token.pubkey.toString());
|
|
130
|
+
console.log('filtered_utxos.len', filtered_utxos.length);
|
|
131
|
+
return filtered_utxos;
|
|
111
132
|
}
|
|
112
|
-
async function fetchUserUtxos({
|
|
133
|
+
async function fetchUserUtxos({ url, storage, encryptionService, publicKey_ata, tokenName }) {
|
|
113
134
|
const lightWasm = await WasmFactory.getInstance();
|
|
114
135
|
// Derive the UTXO keypair from the wallet keypair
|
|
115
136
|
const utxoPrivateKey = encryptionService.deriveUtxoPrivateKey();
|
|
@@ -152,7 +173,7 @@ async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionS
|
|
|
152
173
|
cachedStringNum = JSON.parse(cachedString).length;
|
|
153
174
|
}
|
|
154
175
|
let decryptionTaskTotal = data.total + cachedStringNum - roundStartIndex;
|
|
155
|
-
let batchRes = await decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm);
|
|
176
|
+
let batchRes = await decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm, tokenName);
|
|
156
177
|
decryptionTaskFinished += encryptedOutputs.length;
|
|
157
178
|
logger.debug('batchReslen', batchRes.length);
|
|
158
179
|
for (let i = 0; i < batchRes.length; i++) {
|
|
@@ -170,7 +191,7 @@ async function fetchUserUtxos({ publicKey, connection, url, storage, encryptionS
|
|
|
170
191
|
if (decryptionTaskFinished % 100 == 0) {
|
|
171
192
|
logger.info(`(decrypting cached utxo: ${decryptionTaskFinished + 1}/${decryptionTaskTotal}...)`);
|
|
172
193
|
}
|
|
173
|
-
let batchRes = await decrypt_outputs(cachedEncryptedOutputs, encryptionService, utxoKeypair, lightWasm);
|
|
194
|
+
let batchRes = await decrypt_outputs(cachedEncryptedOutputs, encryptionService, utxoKeypair, lightWasm, tokenName);
|
|
174
195
|
decryptionTaskFinished += cachedEncryptedOutputs.length;
|
|
175
196
|
logger.debug('cachedbatchReslen', batchRes.length, ' source', cachedEncryptedOutputs.length);
|
|
176
197
|
for (let i = 0; i < batchRes.length; i++) {
|
|
@@ -250,8 +271,19 @@ async function areUtxosSpent(connection, utxos) {
|
|
|
250
271
|
}
|
|
251
272
|
// Calculate total balance
|
|
252
273
|
export function getBalanceFromUtxosSPL(utxos) {
|
|
274
|
+
if (!utxos.length) {
|
|
275
|
+
return { base_units: 0, amount: 0, lamports: 0 };
|
|
276
|
+
}
|
|
277
|
+
let token = tokens.find(t => t.pubkey.toString() == utxos[0].mintAddress.toString());
|
|
278
|
+
if (!token) {
|
|
279
|
+
throw new Error('token not found for ' + utxos[0].mintAddress.toString());
|
|
280
|
+
}
|
|
253
281
|
const totalBalance = utxos.reduce((sum, utxo) => sum.add(utxo.amount), new BN(0));
|
|
254
|
-
return {
|
|
282
|
+
return {
|
|
283
|
+
base_units: totalBalance.toNumber(),
|
|
284
|
+
lamports: totalBalance.toNumber(),
|
|
285
|
+
amount: totalBalance.toNumber() / token.units_per_token
|
|
286
|
+
};
|
|
255
287
|
}
|
|
256
288
|
async function decrypt_output(encryptedOutput, encryptionService, utxoKeypair, lightWasm, connection) {
|
|
257
289
|
let res = { status: 'unDecrypted' };
|
|
@@ -325,7 +357,7 @@ async function decrypt_output(encryptedOutput, encryptionService, utxoKeypair, l
|
|
|
325
357
|
}
|
|
326
358
|
return res;
|
|
327
359
|
}
|
|
328
|
-
async function decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm) {
|
|
360
|
+
async function decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair, lightWasm, tokenName) {
|
|
329
361
|
let results = [];
|
|
330
362
|
// decript all UTXO
|
|
331
363
|
for (const encryptedOutput of encryptedOutputs) {
|
|
@@ -351,7 +383,7 @@ async function decrypt_outputs(encryptedOutputs, encryptionService, utxoKeypair,
|
|
|
351
383
|
let url = RELAYER_API_URL + `/utxos/indices`;
|
|
352
384
|
let res = await fetch(url, {
|
|
353
385
|
method: 'POST', headers: { "Content-Type": "application/json" },
|
|
354
|
-
body: JSON.stringify({ encrypted_outputs, token:
|
|
386
|
+
body: JSON.stringify({ encrypted_outputs, token: tokenName })
|
|
355
387
|
});
|
|
356
388
|
let j = await res.json();
|
|
357
389
|
if (!j.indices || !Array.isArray(j.indices) || j.indices.length != encrypted_outputs.length) {
|
package/dist/index.d.ts
CHANGED
|
@@ -77,10 +77,19 @@ export declare class PrivacyCash {
|
|
|
77
77
|
lamports: number;
|
|
78
78
|
}>;
|
|
79
79
|
/**
|
|
80
|
-
* Returns the amount of
|
|
80
|
+
* Returns the amount of base unites current wallet has in Privacy Cash.
|
|
81
81
|
*/
|
|
82
82
|
getPrivateBalanceUSDC(): Promise<{
|
|
83
83
|
base_units: number;
|
|
84
|
+
amount: number;
|
|
85
|
+
lamports: number;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Returns the amount of base unites current wallet has in Privacy Cash.
|
|
89
|
+
*/
|
|
90
|
+
getPrivateBalanceSpl(mintAddress: PublicKey | string): Promise<{
|
|
91
|
+
base_units: number;
|
|
92
|
+
amount: number;
|
|
84
93
|
lamports: number;
|
|
85
94
|
}>;
|
|
86
95
|
/**
|
|
@@ -88,4 +97,29 @@ export declare class PrivacyCash {
|
|
|
88
97
|
*/
|
|
89
98
|
isBrowser(): boolean;
|
|
90
99
|
startStatusRender(): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Deposit SPL to the Privacy Cash.
|
|
102
|
+
*/
|
|
103
|
+
depositSPL({ base_units, mintAddress, amount }: {
|
|
104
|
+
base_units?: number;
|
|
105
|
+
amount?: number;
|
|
106
|
+
mintAddress: PublicKey | string;
|
|
107
|
+
}): Promise<{
|
|
108
|
+
tx: string;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Withdraw SPL from the Privacy Cash.
|
|
112
|
+
*/
|
|
113
|
+
withdrawSPL({ base_units, mintAddress, recipientAddress, amount }: {
|
|
114
|
+
base_units?: number;
|
|
115
|
+
amount?: number;
|
|
116
|
+
mintAddress: PublicKey | string;
|
|
117
|
+
recipientAddress?: string;
|
|
118
|
+
}): Promise<{
|
|
119
|
+
isPartial: boolean;
|
|
120
|
+
tx: string;
|
|
121
|
+
recipient: string;
|
|
122
|
+
base_units: number;
|
|
123
|
+
fee_base_units: number;
|
|
124
|
+
}>;
|
|
91
125
|
}
|