Enable Bulk ERC20 Withdrawals
Approve the batcher smart contract to enable bulk ERC20 token withdrawals. Includes flows for Custody MPC, Custody Multisig, Self-Custody MPC (Hot and Cold), and Self-Custody Multisig (Hot and Cold) wallets. See the Guide.
-
Before approving tokens, you can check if your wallet has already approved the batcher contract. The large number shown in the response (
2^256-1) is the maximum approval amount (unlimited).Approving the batcher smart contract is a one-time operation, but each token requires a separate approval in each wallet.
Prerequisites: Complete Get Started, Create Wallets, and Deposit Assets (you must have the ERC20 token in the wallet).
-
For Custody MPC wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
sendManywithisTss: trueandtype: 'tokenApproval'.Since no assets are withdrawing in this transaction, BitGo automatically bypasses any policies to require additional admin approval. Once approved, you can Bulk Withdraw ERC20 Tokens.
-
For Custody Multisig wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
sendManywithtype: 'tokenApproval'(noisTssflag needed).Since no assets are withdrawing in this transaction, BitGo automatically bypasses any policies to require additional admin approval. Once approved, you can Bulk Withdraw ERC20 Tokens.
-
For self-custody MPC wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
sendManywithisTss: true,type: 'tokenApproval',walletPassphrase, andfeeOptions.Transactions for approving the batcher smart contract follow the transaction flow of the wallet type, and must receive all required signatures and approvals before broadcasting to the blockchain. Once you sign and broadcast your approval transaction, you can Bulk Withdraw ERC20 Tokens.
-
For BitGo Offline Vault MPC wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
sendManywithisTss: true,type: 'tokenApproval', andfeeOptions. You will need to sign the transaction offline.Transactions for approving the batcher smart contract follow the transaction flow of the wallet type, and must receive all required signatures and approvals before broadcasting to the blockchain. Once you sign and broadcast your approval transaction, you can Bulk Withdraw ERC20 Tokens.
-
For self-custody multisignature wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
buildErc20TokenApprovalwith thetokenNameandwalletPassphraseto build, sign, and send in one operation.Transactions for approving the batcher smart contract follow the transaction flow of the wallet type, and must receive all required signatures and approvals before broadcasting to the blockchain. Once you sign and broadcast your approval transaction, you can Bulk Withdraw ERC20 Tokens.
-
For BitGo Offline Vault multisignature wallets, build an approval transaction for the ERC20 token to authorize the batcher smart contract to transfer tokens on your behalf. Use
buildErc20TokenApprovalto get the unsigned transaction, sign offline using the OVC, then send the half-signed transaction withsendTransaction.Transactions for approving the batcher smart contract follow the transaction flow of the wallet type, and must receive all required signatures and approvals before broadcasting to the blockchain. Once you sign and broadcast your approval transaction, you can Bulk Withdraw ERC20 Tokens.
// 1. (Optional) Check Token Allowance
export COIN="<ASSET_ID_OF_NATIVE_COIN>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
curl -X GET \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/allowance \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN"
// 2. Custody MPC: Approve Batcher Smart Contract
export COIN="<ASSET_ID_OF_NATIVE_COIN>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TOKEN_NAME="<ASSET_ID_OF_TOKEN>"
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"intent": {
"intentType": "tokenApproval",
"tokenName": "'"$TOKEN_NAME"'"
}
}'
// 3. Custody Multisig: Approve Batcher Smart Contract
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"type": "tokenApproval"
"tokenName": "'"$TOKEN_NAME"'"
}'
// 4. Self-Custody MPC: Approve Batcher Smart Contract
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"intent": {
"intentType": "tokenApproval",
"tokenName": "'"$TOKEN_NAME"'",
"feeOptions": {
"maxFeePerGas": "30000000001",
"maxPriorityFeePerGas": "30000000000"
},
"type": "tokenApproval"
}
}'
// 5. BitGo Offline Vault MPC: Approve Batcher Smart Contract
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"intent": {
"intentType": "tokenApproval",
"tokenName": "'"$TOKEN_NAME"'",
"feeOptions": {
"maxFeePerGas": "30000000001",
"maxPriorityFeePerGas": "30000000000"
}
}
}'
// 6. Self-Custody Multisig: Approve Batcher Smart Contract
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"tokenName": "'"$TOKEN_NAME"'"
}'
// 7. BitGo Offline Vault Multisig: Approve Batcher Smart Contract
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/token/approval/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"tokenName": "'"$TOKEN_NAME"'"
}'
// 1. (Optional) Check Token Allowance
// Use the REST API for this step (see cURL tab)
// 2. Custody MPC: Approve Batcher Smart Contract
async function approveTokenCustodyMpc() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// For custodial MPC wallets, use sendMany with type: 'tokenApproval'
const result = await walletInstance.sendMany({
isTss: true,
type: 'tokenApproval',
tokenName: 'opeth:usdc'
});
return result;
}
// 3. Custody Multisig: Approve Batcher Smart Contract
async function approveTokenCustodyMultisig() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// For custodial multisig wallets, use sendMany with type: 'tokenApproval'
const result = await walletInstance.sendMany({
type: 'tokenApproval',
tokenName: 'opeth:usdc'
});
return result;
}
// 4. Self-Custody MPC: Approve Batcher Smart Contract
async function approveTokenSelfCustodyMpcHot() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// For self-custody MPC wallets, use sendMany with isTss flag
const result = await walletInstance.sendMany({
isTss: true,
type: 'tokenApproval',
tokenName: 'opeth:usdc',
walletPassphrase: 'VerySecurePassword1234',
feeOptions: {
maxFeePerGas: '30000000001',
maxPriorityFeePerGas: '30000000000'
}
});
return result;
}
// 5. BitGo Offline Vault MPC: Approve Batcher Smart Contract
async function approveTokenSelfCustodyMpcCold() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// For BitGo Offline Vault MPC wallets, similar to Self-Custody MPC but without passphrase
// User will need to sign the transaction offline
const result = await walletInstance.sendMany({
isTss: true,
type: 'tokenApproval',
tokenName: 'opeth:usdc',
feeOptions: {
maxFeePerGas: '30000000001',
maxPriorityFeePerGas: '30000000000'
}
});
return result;
}
// 6. Self-Custody Multisig: Approve Batcher Smart Contract
async function approveTokenSelfCustodyMultisigHot() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// self-custody multisignature wallets can use buildErc20TokenApproval with walletPassphrase
// to build, sign, and send in one operation
const result = await walletInstance.buildErc20TokenApproval(
'opeth:opeth:usdc', // tokenName
'VerySecurePassword1234' // walletPassphrase
);
return result;
}
// 7. BitGo Offline Vault Multisig: Approve Batcher Smart Contract
async function approveTokenSelfCustodyMultisigCold() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// For BitGo Offline Vault Multisig wallets, get the unsigned transaction
const tokenApprovalBuild = await walletInstance.buildErc20TokenApproval('opeth:usdc');
// Sign offline using the OVC
// ...
// Send the half-signed transaction
const sendResult = await walletInstance.sendTransaction({
txHex: halfSignedTxHex,
});
return sendResult;
}
// 1. (Optional) Check Token Allowance Response
{
"allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
}
// Approve Batcher Smart Contract Response (applies to all wallet types)
{
"pendingApproval": {
"id": "63727a81cdbc820007b27caa7b76016d",
"coin": "eth",
"wallet": "63726fde0a3c94000758f2790536041d",
"state": "pendingFinalApproval",
"scope": "wallet",
"info": {
"type": "transactionRequest",
"transactionRequest": {
"coinSpecific": {
"eth": {
"eip1559": {
"maxPriorityFeePerGas": 1500000000,
"maxFeePerGas": 133302263906
},
"recipients": [
{
"amount": "0",
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"data": "0x095ea7b3000000000000000000000000..."
}
]
}
}
}
}
}
}