Unshield NFTs

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

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

Imports

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

Gas Estimate

export const erc721UnshieldGasEstimate = async (
  network: NetworkName,
  railgunWalletID: string,
  encryptionKey: string,
  erc721AmountRecipients: RailgunNFTAmountRecipient[]
) => {
  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
    erc721AmountRecipients,
    originalGasDetails,
    feeTokenDetails,
    sendWithPublicWallet
  );

  return gasEstimate;
};

Generate Proof

export const erc721UnshieldGenerateProof = async (
  encryptionKey: string,
  network: NetworkName,
  railgunWalletID: string,
  erc721AmountRecipients: RailgunNFTAmountRecipient[],
  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 ERC721 Proof progress: ", progress);
  };

  await generateUnshieldProof(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    railgunWalletID,
    encryptionKey,
    [],
    erc721AmountRecipients, // nft amount recipients
    broadcasterFeeERC20AmountRecipient,
    sendWithPublicWallet,
    overallBatchMinGasPrice,
    progressCallback
  );
};

Populate Transaction

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

  return populateResponse;
};

Example Usage

export const TEST_ERC721Unshield = async (
  encryptionKey: string,
  railgunWalletInfo: RailgunWalletInfo
) => {
  console.log("TEST_ERC721Unshield");
  const { wallet } = getProviderWallet();
  const erc721AmountRecipients: RailgunNFTAmountRecipient[] = [
    serializeERC721Transfer(TEST_NFT_ADDRESS, TEST_NFT_SUBID, wallet.address),
  ];

  const gasEstimate = await erc721UnshieldGasEstimate(
    TEST_NETWORK,
    railgunWalletInfo.id,
    encryptionKey,
    erc721AmountRecipients
  );

  console.log("ERC721 UNSHIELD gasEstimate");

  // generate erc721 unshield proof
  await erc721UnshieldGenerateProof(
    encryptionKey,
    TEST_NETWORK,
    railgunWalletInfo.id,
    erc721AmountRecipients,
    1n
  );

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

  const overallBatchMinGasPrice = await calculateGasPrice(
    transactionGasDetails
  );

  const transaction = await erc721UnshieldPopulateTransaction(
    TEST_NETWORK,
    railgunWalletInfo.id,
    erc721AmountRecipients,
    overallBatchMinGasPrice,
    transactionGasDetails
  );

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

Last updated