privacycash 1.0.17 → 1.0.18

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.
Files changed (42) hide show
  1. package/__tests__/e2e.test.ts +5 -1
  2. package/__tests__/e2espl.test.ts +73 -0
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.js +6 -10
  5. package/dist/deposit.js +4 -11
  6. package/dist/depositSPL.d.ts +19 -0
  7. package/dist/depositSPL.js +433 -0
  8. package/dist/exportUtils.d.ts +3 -0
  9. package/dist/exportUtils.js +3 -0
  10. package/dist/getUtxos.d.ts +2 -1
  11. package/dist/getUtxos.js +68 -79
  12. package/dist/getUtxosSPL.d.ts +31 -0
  13. package/dist/getUtxosSPL.js +369 -0
  14. package/dist/index.d.ts +31 -1
  15. package/dist/index.js +73 -3
  16. package/dist/models/utxo.js +10 -1
  17. package/dist/utils/address_lookup_table.d.ts +1 -0
  18. package/dist/utils/address_lookup_table.js +23 -0
  19. package/dist/utils/constants.d.ts +3 -1
  20. package/dist/utils/constants.js +6 -3
  21. package/dist/utils/encryption.d.ts +1 -1
  22. package/dist/utils/encryption.js +5 -3
  23. package/dist/utils/utils.d.ts +3 -2
  24. package/dist/utils/utils.js +26 -6
  25. package/dist/withdraw.js +3 -3
  26. package/dist/withdrawSPL.d.ts +22 -0
  27. package/dist/withdrawSPL.js +290 -0
  28. package/package.json +5 -3
  29. package/src/config.ts +7 -14
  30. package/src/deposit.ts +4 -11
  31. package/src/depositSPL.ts +555 -0
  32. package/src/exportUtils.ts +5 -1
  33. package/src/getUtxos.ts +73 -78
  34. package/src/getUtxosSPL.ts +495 -0
  35. package/src/index.ts +84 -3
  36. package/src/models/utxo.ts +10 -1
  37. package/src/utils/address_lookup_table.ts +54 -6
  38. package/src/utils/constants.ts +8 -3
  39. package/src/utils/encryption.ts +6 -3
  40. package/src/utils/utils.ts +29 -6
  41. package/src/withdraw.ts +4 -4
  42. package/src/withdrawSPL.ts +379 -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 { LSK_ENCRYPTED_OUTPUTS, LSK_FETCH_OFFSET } from './utils/constants.js';
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
  */
@@ -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
+ }
@@ -6,9 +6,11 @@ export declare const DEPLOYER_ID: PublicKey;
6
6
  export declare const FEE_RECIPIENT: PublicKey;
7
7
  export declare const FETCH_UTXOS_GROUP_SIZE = 10000;
8
8
  export declare const TRANSACT_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
9
+ export declare const TRANSACT_SPL_IX_DISCRIMINATOR: Buffer<ArrayBuffer>;
9
10
  export declare const MERKLE_TREE_DEPTH = 26;
10
11
  export declare const ALT_ADDRESS: PublicKey;
11
- export declare const INDEXER_API_URL: string;
12
+ export declare const RELAYER_API_URL: string;
12
13
  export declare const SIGN_MESSAGE = "Privacy Money account sign in";
13
14
  export declare const LSK_FETCH_OFFSET = "fetch_offset";
14
15
  export declare const LSK_ENCRYPTED_OUTPUTS = "encrypted_outputs";
16
+ export declare const USDC_MINT: PublicKey;
@@ -2,14 +2,17 @@ import { PublicKey } from '@solana/web3.js';
2
2
  import BN from 'bn.js';
3
3
  export const FIELD_SIZE = new BN('21888242871839275222246405745257275088548364400416034343698204186575808495617');
4
4
  export const PROGRAM_ID = new PublicKey('9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD');
5
- export const DEPLOYER_ID = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
5
+ export const DEPLOYER_ID = new PublicKey('97rSMQUukMDjA7PYErccyx7ZxbHvSDaeXp2ig5BwSrTf');
6
+ //BxuZn19npE43qkrQycBSb12vgruyD3vLygxwZss7eXLU
6
7
  export const FEE_RECIPIENT = new PublicKey('AWexibGxNFKTa1b5R5MN4PJr9HWnWRwf8EW9g8cLx3dM');
7
8
  export const FETCH_UTXOS_GROUP_SIZE = 10_000;
8
9
  export const TRANSACT_IX_DISCRIMINATOR = Buffer.from([217, 149, 130, 143, 221, 52, 252, 119]);
10
+ export const TRANSACT_SPL_IX_DISCRIMINATOR = Buffer.from([154, 66, 244, 204, 78, 225, 163, 151]);
9
11
  export const MERKLE_TREE_DEPTH = 26;
10
- export const ALT_ADDRESS = new PublicKey('72bpRay17JKp4k8H87p7ieU9C6aRDy5yCqwvtpTN2wuU');
11
- export const INDEXER_API_URL = process.env.NEXT_PUBLIC_INDEXER_API_URL ?? 'https://api3.privacycash.org';
12
+ export const ALT_ADDRESS = new PublicKey('HEN49U2ySJ85Vc78qprSW9y6mFDhs1NczRxyppNHjofe');
13
+ export const RELAYER_API_URL = process.env.NEXT_PUBLIC_RELAYER_API_URL ?? 'https://api3.privacycash.org';
12
14
  export const SIGN_MESSAGE = `Privacy Money account sign in`;
13
15
  // localStorage cache keys
14
16
  export const LSK_FETCH_OFFSET = 'fetch_offset';
15
17
  export const LSK_ENCRYPTED_OUTPUTS = 'encrypted_outputs';
18
+ export const 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>;
@@ -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
- TRANSACT_IX_DISCRIMINATOR,
354
+ discriminator,
353
355
  // Serialize proof
354
356
  Buffer.from(proof.proofA),
355
357
  Buffer.from(proof.proofB),
@@ -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;
@@ -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 { INDEXER_API_URL, PROGRAM_ID } from './constants.js';
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
- const response = await fetch(`${INDEXER_API_URL}/merkle/proof/${commitment}`);
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: ${response.status} ${response.statusText}`);
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
- const response = await fetch(`${INDEXER_API_URL}/merkle/root`);
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, DEPLOYER_ID, FEE_RECIPIENT, FIELD_SIZE, INDEXER_API_URL, MERKLE_TREE_DEPTH } from './utils/constants.js';
7
+ import { ALT_ADDRESS, DEPLOYER_ID, 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(`${INDEXER_API_URL}/withdraw`, {
17
+ const response = await fetch(`${RELAYER_API_URL}/withdraw`, {
18
18
  method: 'POST',
19
19
  headers: {
20
20
  'Content-Type': 'application/json',
@@ -257,7 +257,7 @@ export async function withdraw({ recipient, lightWasm, storage, publicKey, conne
257
257
  console.log(`retryTimes: ${retryTimes}`);
258
258
  await new Promise(resolve => setTimeout(resolve, itv * 1000));
259
259
  console.log('Fetching updated tree state...');
260
- let res = await fetch(INDEXER_API_URL + '/utxos/check/' + encryptedOutputStr);
260
+ let res = await fetch(RELAYER_API_URL + '/utxos/check/' + encryptedOutputStr);
261
261
  let resJson = await res.json();
262
262
  console.log('resJson:', resJson);
263
263
  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 {};