# Shield ERC-20 tokens

Shield one or more ERC-20 tokens into RAILGUN private balances in a single transaction

### Imports

```typescript
import {
  NETWORK_CONFIG,
  NetworkName,
  TXIDVersion,
  type RailgunERC20AmountRecipient,
} from "@railgun-community/shared-models";
import {
  getGasDetailsForTransaction,
  getShieldSignature,
  serializeERC20Transfer,
} from "../util";
import {
  gasEstimateForShield,
  populateShield,
} from "@railgun-community/wallet";
import { Contract, type HDNodeWallet, type Wallet } from "ethers";
import { TEST_NETWORK, TEST_TOKEN } from "../../utils/constants";
import { getProviderWallet } from "../../utils/provider";


```

## Gas Estimate

An asynchronous function `erc20ShieldGasEstimate` that calculates the estimated gas required to execute a shielding transaction for ERC-20 tokens in the RAILGUN system. It takes as parameters the network name, a wallet instance, and a list of ERC-20 amount recipients. The function first obtains a unique shield signature for the transaction using the provided wallet. It then derives the address from which the tokens are being shielded and calls `gasEstimateForShield` to perform the gas estimation based on transaction details like the recipient information and other transaction parameters. The estimated gas is then returned, providing insights into transaction costs before execution.

```typescript
export const erc20ShieldGasEstimate = async (
  network: NetworkName,
  wallet: Wallet | HDNodeWallet,
  erc20AmountRecipients: RailgunERC20AmountRecipient[]
) => {
  const shieldPrivateKey = await getShieldSignature(wallet);

  // Address of public wallet we are shielding from
  const fromWalletAddress = wallet.address;

  const { gasEstimate } = await gasEstimateForShield(
    TXIDVersion.V2_PoseidonMerkle,
    network,
    shieldPrivateKey,
    erc20AmountRecipients,
    [], // nftAmountRecipients
    fromWalletAddress
  );

  return gasEstimate;
};
```

### Populate Transaction

The code block defines an asynchronous function `erc20PopulateShieldTransaction` that facilitates the preparation of a transaction for shielding ERC20 tokens using the Railgun protocol. Initially, it approves the necessary token allowances for the specified `erc20AmountRecipients` by interacting with their token contracts. It checks the current allowance and approves additional tokens if needed. The function then estimates the gas required for the shielding transaction by calling `erc20ShieldGasEstimate`. With this estimate, it retrieves gas details tailored to whether the transaction is sent using a public or private wallet. Finally, the transaction is populated using `populateShield`, which returns the transaction details including gas estimation, nullifiers, and transaction object, suitable for execution on the Ethereum network.

```typescript

export const erc20PopulateShieldTransaction = async (
  network: NetworkName,
  wallet: Wallet | HDNodeWallet,
  erc20AmountRecipients: RailgunERC20AmountRecipient[],
  sendWithPublicWallet: boolean
) => {
  // get gas estimate for tx,
  // populate tx with gas estimate
  // approve token to spender.

  // approve token to spender
  const spender = NETWORK_CONFIG[network].proxyContract;
  const tokens = erc20AmountRecipients.map((erc20AmountRecipient) => {
    return erc20AmountRecipient.tokenAddress;
  });

  for (const amountRecipient of erc20AmountRecipients) {
    const contract = new Contract(
      amountRecipient.tokenAddress,
      [
        "function allowance(address owner, address spender) view returns (uint256)",
        "function approve(address spender, uint256 amount) external returns (bool)",
      ],
      wallet
    );
    const allowance = await contract.allowance(wallet.address, spender);
    if (allowance >= amountRecipient.amount) {
      console.log("already have enough allowance");
      continue;
    }
    const tx = await contract.approve(spender, amountRecipient.amount);
    await tx.wait();
  }

  const gasEstimate = await erc20ShieldGasEstimate(
    network,
    wallet,
    erc20AmountRecipients
  );

  const shieldPrivateKey = await getShieldSignature(wallet);

  const gasDetails = await getGasDetailsForTransaction(
    network,
    gasEstimate,
    sendWithPublicWallet,
    wallet
  );

  const { transaction, nullifiers } = await populateShield(
    TXIDVersion.V2_PoseidonMerkle, // this is for V2 of the railgun protocol
    network,
    shieldPrivateKey,
    erc20AmountRecipients,
    [],
    gasDetails
  );

  return {
    gasEstimate,
    gasDetails,
    transaction,
    nullifiers,
  };
};
```

## Example Usage

```typescript
export const TEST_shieldERC20 = async (railgunWalletAddress: string) => {
  const { wallet } = getProviderWallet();

  const erc20AmountRecipients = [
    serializeERC20Transfer(
      TEST_TOKEN, // WETH
      1n,
      railgunWalletAddress
    ),
  ];

  const { gasEstimate, gasDetails, transaction, nullifiers } =
    await erc20PopulateShieldTransaction(
      TEST_NETWORK,
      wallet,
      erc20AmountRecipients,
      true
    );

  //   console.log("gasEstimate: ", gasEstimate);
  //   console.log("gasDetails: ", gasDetails);
  //   console.log("transaction: ", transaction);
  //   console.log("nullifiers: ", nullifiers);

  const tx = await wallet.sendTransaction(transaction);
  console.log("tx: ", tx);
  await tx.wait();
};
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.railgun.org/developer-guide/wallet/transactions/shielding/shield-erc-20-tokens.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
