RAILGUN only supports shielding ERC-20 tokens. Base tokens cannot be shielded directly, as they are not ERC-20 tokens. They must be shielded as a wrapped token, eg. wETH for the Ethereum network.
Base token shields are executed as a multi-call through the RAILGUN Relay Adapt contract, which wraps the ETH into wETH at 1:1 ratio, and shields the result into your balance. This must be performed in isolation and cannot support shielding other ERC-20 tokens as part of the same transaction.
Gas Estimate
import { NetworkName} from'@railgun-community/shared-models';import { gasEstimateForShieldBaseToken, getShieldPrivateKeySignatureMessage,} from'@railgun-community/wallet';import { keccak256, Wallet } from'ethers';// Receiver of the shield.constrailgunAddress='0zk123...456';// The shieldPrivateKey enables the sender to decrypt // the receiver's address in the future.constwallet=newWallet(pKey);constshieldSignatureMessage=getShieldPrivateKeySignatureMessage();constshieldPrivateKey=keccak256(awaitwallet.signMessage(shieldSignatureMessage),);// Formatted wrapped token amount.// Tokens will shield as ETH and auto-wrap into wETH.constwrappedERC20Amount:RailgunERC20Amount= { tokenAddress:'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',// wETH amount:BigInt('0x10'),// hexadecimal amount};// Public wallet to shield from.constfromWalletAddress='0xab5...c9b';const { gasEstimate } =awaitgasEstimateForShieldBaseToken(NetworkName.Ethereum, railgunAddress, shieldPrivateKey, wrappedERC20Amount, fromWalletAddress,);
Populate Transaction
import { ... EVMGasType, TransactionGasDetails, getEVMGasTypeForTransaction,} from'@railgun-community/shared-models';import { ... populateShield,} from'@railgun-community/wallet';...constsendWithPublicWallet=true; // Always true for Shield transactionsconstevmGasType:EVMGasType=getEVMGasTypeForTransaction(NetworkName.Ethereum, sendWithPublicWallet);constgasEstimate=...; // Output from gasEstimateForShield in above examplelet gasDetails:TransactionGasDetails;switch (evmGasType) {caseEVMGasType.Type0:caseEVMGasType.Type1: gasDetails = { evmGasType, gasEstimate, gasPrice:BigInt('0x100000'),// Proper calculation of network gasPrice is not covered in this guide }break;caseEVMGasType.Type2:// Proper calculation of gas Max Fee and gas Max Priority Fee is not covered in this guide. See: https://docs.alchemy.com/docs/how-to-build-a-gas-fee-estimator-using-eip-1559constmaxFeePerGas:BigInt('0x100000');constmaxPriorityFeePerGas:BigInt('0x010000'); gasDetails = { evmGasType, gasEstimate, maxFeePerGas, maxPriorityFeePerGas, }break;}const { transaction } =awaitpopulateShieldBaseToken(NetworkName.Ethereum, railgunAddress, shieldPrivateKey, wrappedERC20Amount, gasDetails,);// Public wallet to shield from.transaction.from ='0xab58...c9b';