Unshield ERC-20 tokens

Unshielding requires you to "Generate Proof" and, optionally, make use of "Relayers": See UX for Private Transactions UX for Private Transactions

Unshield multiple ERC-20 tokens into a public wallet in a single transaction.

Imports

import {
  calculateGasPrice,
  NetworkName,
  TXIDVersion,
  type RailgunERC20AmountRecipient,
  type RailgunWalletInfo,
  type TransactionGasDetails,
} from "@railgun-community/shared-models";
import {
  gasEstimateForUnprovenUnshield,
  generateUnshieldProof,
  populateProvedUnshield,
} from "@railgun-community/wallet";
import {
  getGasDetailsForTransaction,
  getOriginalGasDetailsForTransaction,
  serializeERC20Transfer,
} from "../util";
import { TEST_NETWORK, TEST_TOKEN } from "../../utils/constants";
import { getProviderWallet } from "../../utils/provider";

Gas Estimate

export const erc20UnshieldGasEstimate = async (
  network: NetworkName,
  railgunWalletID: string,
  encryptionKey: string,
  erc20AmountRecipients: RailgunERC20AmountRecipient[]
) => {
  const sendWithPublicWallet = true;
  const originalGasDetails = await getOriginalGasDetailsForTransaction(
    network,
    sendWithPublicWallet
  );
  // dont setup broadcaster connection for simplicity.
  const feeTokenDetails = undefined;
  console.log("unshield originalGasDetails: ", originalGasDetails);

  const { gasEstimate } = await gasEstimateForUnprovenUnshield(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    railgunWalletID,
    encryptionKey,
    erc20AmountRecipients,
    [], // nft amount recipients
    originalGasDetails,
    feeTokenDetails,
    sendWithPublicWallet
  );

  return gasEstimate;
};

Generate Proof

export const erc20UnshieldGenerateProof = async (
  encryptionKey: string,
  network: NetworkName,
  railgunWalletID: string,
  tokenAmountRecipients: RailgunERC20AmountRecipient[],
  overallBatchMinGasPrice: bigint,
  sendWithPublicWallet: boolean = true,
  broadcasterFeeERC20AmountRecipient:
    | RailgunERC20AmountRecipient
    | undefined = undefined
) => {
  const progressCallback = (progress: number) => {
    // Handle proof progress (show in UI).
    // Proofs can take 20-30 seconds on slower devices.
    console.log("Unshield ERC20 Proof progress: ", progress);
  };
  await generateUnshieldProof(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    railgunWalletID,
    encryptionKey,
    tokenAmountRecipients,
    [], // nft amount recipients
    broadcasterFeeERC20AmountRecipient,
    sendWithPublicWallet,
    overallBatchMinGasPrice,
    progressCallback
  );
};

Populate Transaction


export const erc20UnshieldPopulateTransaction = async (
  network: NetworkName,
  railgunWalletID: string,
  tokenAmountRecipients: RailgunERC20AmountRecipient[],
  overallBatchMinGasPrice: bigint,
  transactionGasDetails: TransactionGasDetails,
  sendWithPublicWallet: boolean = true,
  broadcasterFeeERC20AmountRecipient:
    | RailgunERC20AmountRecipient
    | undefined = undefined
) => {
  const populateResponse = await populateProvedUnshield(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    railgunWalletID,
    tokenAmountRecipients,
    [], // nftAmountRecipients
    broadcasterFeeERC20AmountRecipient,
    sendWithPublicWallet,
    overallBatchMinGasPrice,
    transactionGasDetails
  );

  return populateResponse;
};

Example Usage

export const TEST_ERC20Unshield = async (
  encryptionKey: string,
  railgunWalletInfo: RailgunWalletInfo
) => {
  console.log("TEST_ERC20Unshield");
  const { wallet } = getProviderWallet();
  const erc20AmountRecipients: RailgunERC20AmountRecipient[] = [
    serializeERC20Transfer(
      TEST_TOKEN, // WETH
      1n,
      wallet.address
    ),
  ];

  const gasEstimate = await erc20UnshieldGasEstimate(
    TEST_NETWORK,
    railgunWalletInfo.id,
    encryptionKey,
    erc20AmountRecipients
  );

  console.log("ERC20 UNSHIELD gasEstimate: ", gasEstimate);

  // generate unshield proof
  await erc20UnshieldGenerateProof(
    encryptionKey,
    TEST_NETWORK,
    railgunWalletInfo.id,
    erc20AmountRecipients,
    1n
  );

  const transactionGasDetails = await getGasDetailsForTransaction(
    TEST_NETWORK,
    gasEstimate,
    true,
    wallet
  );

  const overallBatchMinGasPrice = await calculateGasPrice(
    transactionGasDetails
  );

  // populate tx

  const transaction = await erc20UnshieldPopulateTransaction(
    TEST_NETWORK,
    railgunWalletInfo.id,
    erc20AmountRecipients,
    overallBatchMinGasPrice,
    transactionGasDetails
  );

  console.log("ERC20 UNSHIELD transaction", transaction);
  // send unshield tx
  // submission via self-signed tx or public-broadcaster
};

Last updated