Skip to main content

Deposits

This guide covers depositing tokens from your wallet into your private balance.

Basic Deposit

const result = await sdk.vault.deposit({
  tokenAddress: '0x...token-address',
  amount: 1000000000000000000n, // 1 token (18 decimals)
});

console.log('Transaction hash:', result.txHash);
console.log('Commitment:', result.commitment);

Deposit Parameters

interface DepositParams {
  tokenAddress: Hex;         // ERC-20 token address
  amount: bigint;            // Amount in wei
  recipientMpk?: bigint;     // Optional: deposit to another user
  onProgress?: OnProgress;   // Optional: progress callback
}
ParameterTypeRequiredDescription
tokenAddressHexYesERC-20 token contract address
amountbigintYesAmount in smallest unit (wei)
recipientMpkbigintNoDeposit to another user’s MPK
onProgressfunctionNoProgress callback function

Progress Tracking

Track deposit progress with a callback:
await sdk.vault.deposit({
  tokenAddress: '0x...',
  amount: 1000000000000000000n,
  onProgress: ({ step, message, txHash }) => {
    console.log(`Step: ${step}`);
    console.log(`Message: ${message}`);
    if (txHash) {
      console.log(`Transaction: ${txHash}`);
    }
  },
});

Deposit Steps

StepDescription
wrappingWrapping ETH to WETH (if depositing ETH)
approvingApproving token spending
shieldingExecuting the deposit transaction
complianceWaiting for compliance verification
enum DepositStep {
  wrapping = 'wrapping',
  approving = 'approving',
  shielding = 'shielding',
  compliance = 'compliance',
}

Deposit Result

interface DepositResult {
  txHash: Hex;        // Main deposit transaction hash
  commitment: Hex;    // Note commitment
  fee: bigint;        // Fee paid
  wrapTxHash?: Hex;   // WETH wrap transaction (if applicable)
}

Depositing ETH

To deposit native ETH, use the zero address:
const ETH_ADDRESS = '0x0000000000000000000000000000000000000000';

const result = await sdk.vault.deposit({
  tokenAddress: ETH_ADDRESS,
  amount: 1000000000000000000n, // 1 ETH
  onProgress: ({ step, message, txHash }) => {
    if (step === 'wrapping') {
      console.log('Wrapping ETH to WETH...');
    }
  },
});

// Result includes wrap transaction
console.log('Wrap tx:', result.wrapTxHash);
console.log('Deposit tx:', result.txHash);
The SDK automatically:
  1. Wraps ETH to WETH
  2. Approves WETH spending
  3. Deposits WETH to shield

Deposit to Another User

You can deposit directly to another user’s private balance:
// Get recipient's MPK from their privacy address
import { extractMpkFromPrivacyAddress } from '@testinprod-io/privacy-boost';

const recipientPrivacyAddress = '0x04...';
const recipientMpk = extractMpkFromPrivacyAddress(recipientPrivacyAddress);

const result = await sdk.vault.deposit({
  tokenAddress: '0x...',
  amount: 1000000000000000000n,
  recipientMpk,
});

Token Approval

The SDK handles token approval automatically. For large amounts, you may want to approve unlimited spending:
// The SDK checks current allowance and only approves if needed
// If allowance is sufficient, the approve step is skipped

Parsing Amounts

Use helper functions to convert between formats:
// Parse human-readable amount to bigint
const amount = await sdk.vault.parseAmount('0x...token', '1.5');
// Returns: 1500000000000000000n (for 18 decimal token)

// Format bigint to human-readable
const formatted = sdk.vault.formatAmount(1500000000000000000n, 18);
// Returns: "1.5"

Error Handling

try {
  await sdk.vault.deposit({ tokenAddress, amount });
} catch (error) {
  switch (error.code) {
    case 'INSUFFICIENT_BALANCE':
      console.log('Not enough tokens in wallet');
      break;
    case 'USER_REJECTED':
      console.log('User rejected transaction');
      break;
    case 'APPROVAL_FAILED':
      console.log('Token approval failed');
      break;
    case 'DEPOSIT_FAILED':
      console.log('Deposit transaction failed');
      break;
    case 'COMPLIANCE_REJECTED':
      console.log('Compliance check failed');
      break;
    default:
      console.log('Deposit error:', error.message);
  }
}

UI Example

import { useState } from 'react';

function DepositForm() {
  const [amount, setAmount] = useState('');
  const [step, setStep] = useState('');
  const [loading, setLoading] = useState(false);

  const handleDeposit = async () => {
    setLoading(true);
    try {
      const parsedAmount = await sdk.vault.parseAmount(tokenAddress, amount);

      await sdk.vault.deposit({
        tokenAddress,
        amount: parsedAmount,
        onProgress: ({ step, message }) => {
          setStep(message);
        },
      });

      alert('Deposit successful!');
    } catch (error) {
      alert(`Deposit failed: ${error.message}`);
    } finally {
      setLoading(false);
      setStep('');
    }
  };

  return (
    <div>
      <input
        type="text"
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Amount"
        disabled={loading}
      />
      <button onClick={handleDeposit} disabled={loading}>
        {loading ? step || 'Processing...' : 'Deposit'}
      </button>
    </div>
  );
}

Best Practices

1. Always Validate Amounts

function validateDepositAmount(amount: bigint, walletBalance: bigint) {
  if (amount <= 0n) {
    throw new Error('Amount must be positive');
  }
  if (amount > walletBalance) {
    throw new Error('Insufficient wallet balance');
  }
}

2. Check Token Support

const supportedTokens = await sdk.vault.getSupportedTokens();
const isSupported = supportedTokens.some(
  (t) => t.address.toLowerCase() === tokenAddress.toLowerCase()
);

if (!isSupported) {
  throw new Error('Token not supported');
}

3. Handle Large Deposits

For large deposits, consider splitting into multiple transactions:
async function depositInChunks(tokenAddress: Hex, totalAmount: bigint) {
  const CHUNK_SIZE = 10000000000000000000n; // 10 tokens
  let remaining = totalAmount;

  while (remaining > 0n) {
    const chunk = remaining > CHUNK_SIZE ? CHUNK_SIZE : remaining;
    await sdk.vault.deposit({ tokenAddress, amount: chunk });
    remaining -= chunk;
  }
}

Next Steps