> For the complete documentation index, see [llms.txt](https://docs.railgun.org/developer-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.railgun.org/developer-guide/wallet/transactions/unshielding/unshield-base-token.md).

# Unshield base token

*Unshielding requires you to "Generate Proof" and, optionally, make use of "Relayers": See UX for Private Transactions* [*UX for Private Transactions* ](/developer-guide/wallet/transactions/ux-private-transactions.md)

Unshield only the base token for a network (eg. ETH) from shielded wETH in a single transaction.&#x20;

Base tokens cannot be shielded by themselves, as they are not ERC-20 tokens. They must be shielded as a wrapped token, eg. [wETH](https://weth.io/) for the Ethereum network. You can choose to unshield a wrapped base token (like wETH) from a user's private balance to the equivalent base token.

Base token unshields are executed as a multi call through RAILGUN Relay Adapt, which unwraps the wETH into ETH at a 1:1 ratio and unshields the result into a public balance. This transaction is performed in isolation and cannot be paired with ERC-20 unshields.

### Imports

```typescript
import {
  calculateGasPrice,
  TXIDVersion,
  type NetworkName,
  type RailgunERC20Amount,
  type RailgunERC20AmountRecipient,
  type RailgunWalletInfo,
  type TransactionGasDetails,
} from "@railgun-community/shared-models";
import { TEST_NETWORK, TEST_TOKEN } from "../../utils/constants";
import {
  getGasDetailsForTransaction,
  getOriginalGasDetailsForTransaction,
} from "../util";
import {
  gasEstimateForUnprovenUnshieldBaseToken,
  generateUnshieldBaseTokenProof,
  populateProvedUnshieldBaseToken,
} from "@railgun-community/wallet";
import { getProviderWallet } from "../../utils/provider";
```

### Gas Estimate

```typescript
export const ethUnshieldGasEstimate = async (
  network: NetworkName,
  railgunWalletID: string,
  encryptionKey: string,
  erc20AmountRecipients: RailgunERC20Amount,
  destinationAddress: string
) => {
  const sendWithPublicWallet = true;
  const originalGasDetails = await getOriginalGasDetailsForTransaction(
    network,
    sendWithPublicWallet
  );

  // dont setup broadcaster connection for simplicity.
  const feeTokenDetails = undefined;
  console.log("unshield ETH originalGasDetails: ", originalGasDetails);

  const { gasEstimate } = await gasEstimateForUnprovenUnshieldBaseToken(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    destinationAddress,
    railgunWalletID,
    encryptionKey,
    erc20AmountRecipients,
    originalGasDetails,
    feeTokenDetails,
    sendWithPublicWallet
  );

  return gasEstimate;
};

```

### Generate Proof

```typescript
export const ethUnshieldGenerateProof = async (
  encryptionKey: string,
  network: NetworkName,
  railgunWalletID: string,
  destinationAddress: string,
  tokenAmountRecipients: RailgunERC20Amount,
  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 ETH Proof progress: ", progress);
  };

  await generateUnshieldBaseTokenProof(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    destinationAddress,
    railgunWalletID,
    encryptionKey,
    tokenAmountRecipients,
    broadcasterFeeERC20AmountRecipient,
    sendWithPublicWallet,
    overallBatchMinGasPrice,
    progressCallback
  );
};

```

### Populate Transaction

```typescript
export const ethUnshieldPopulateTransaction = async (
  network: NetworkName,
  railgunWalletID: string,
  destinationAddress: string,
  tokenAmountRecipients: RailgunERC20Amount,
  overallBatchMinGasPrice: bigint,
  transactionGasDetails: TransactionGasDetails,
  sendWithPublicWallet: boolean = true,
  broadcasterFeeERC20AmountRecipient:
    | RailgunERC20AmountRecipient
    | undefined = undefined
) => {
  const populateResponse = await populateProvedUnshieldBaseToken(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    destinationAddress,
    railgunWalletID,
    tokenAmountRecipients,
    broadcasterFeeERC20AmountRecipient,
    sendWithPublicWallet,
    overallBatchMinGasPrice,
    transactionGasDetails
  );
  return populateResponse;
};
```

### Example Usage

```typescript
export const TEST_ETHUnshield = async (
  encryptionKey: string,
  railgunWalletInfo: RailgunWalletInfo
) => {
  const { wallet } = getProviderWallet();

  //
  const wrappedERC20Amount: RailgunERC20Amount = {
    tokenAddress: TEST_TOKEN, // wETH
    amount: 1n, //
  };

  // gas estimate
  const gasEstimate = await ethUnshieldGasEstimate(
    TEST_NETWORK,
    railgunWalletInfo.id,
    encryptionKey,
    wrappedERC20Amount,
    wallet.address
  );

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

  // generate eth unshield proof
  await ethUnshieldGenerateProof(
    encryptionKey,
    TEST_NETWORK,
    railgunWalletInfo.id,
    wallet.address,
    wrappedERC20Amount,
    1n // originalBatchMinGasPrice
  );
  const transactionGasDetails = await getGasDetailsForTransaction(
    TEST_NETWORK,
    gasEstimate,
    true,
    wallet
  );

  const overallBatchMinGasPrice = await calculateGasPrice(
    transactionGasDetails
  );

  // populate tx
  const transaction = await ethUnshieldPopulateTransaction(
    TEST_NETWORK,
    railgunWalletInfo.id,
    wallet.address,
    wrappedERC20Amount,
    overallBatchMinGasPrice,
    transactionGasDetails
  );
  console.log("ETH UNSHIELD transaction", transaction);
};
```
