Unstake Assets - Self-Custody Wallet
Unstake assets from a self-custody wallet with full signing control. See the Guide.
-
You create an unstaking request by specifying the unstaking details and sending them to BitGo. This generates an unstaking transaction for you to approve and sign.
For ether, currently only wallet administrators can create an unstaking request. For ETH, you must wait for the unstaking transaction to complete before initiating a new unstaking request for the same wallet.
-
Validators must process your unstaking request before the request is ready for approval and signing. To get notified when unstaking requests are pending approval, you can Create Webhooks.
-
If you have a policy that requires approval, you must approve the unstaking request before signing and broadcasting. You cannot approve your own transactions — another admin must approve them.
-
After an admin approves the unstaking request (or if no approval is required), sign the transactions and send them to BitGo for final signing and broadcasting to the blockchain.
BitGo may automatically generate a second claim transaction after the unstaking cooldown period, which requires the same approval and signing process.
// 1. Create Unstaking Request
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export CLIENT_ID="<YOUR_CLIENT_ID>"
export DELEGATION_ID="<YOUR_DELEGATION_ID>"
curl -X POST \
https://app.bitgo-test.com/api/staking/v1/$COIN/wallets/$WALLET_ID/requests \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"clientId": "'"$CLIENT_ID"'",
"delegationId": "'"$DELEGATION_ID"'",
"type": "UNSTAKE"
}'
// 2. Get Request Status (Optional)
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export WALLET_TYPE="<YOUR_WALLET_TYPE>"
export WALLET_ID="<YOUR_WALLET_ID>"
curl -X GET \
https://app.bitgo-test.com/api/staking/v1/enterprises/$ENTERPRISE_ID/requests/transactions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"walletType": "'"$WALLET_TYPE"'",
"walletId": "'"$WALLET_ID"'",
"requestType": "UNSTAKE",
"requestStatus": "PENDING_APPROVAL"
}'
// 3. Approve Request (Optional)
export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export OTP="<YOUR_OTP>"
curl -X PUT \
https://app.bitgo-test.com/api/v2/pendingApprovals/$APPROVAL_ID \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"state": "approved",
"otp": "'"$OTP"'"
}'
// 4. Sign and Send Request
// Use the JavaScript SDK for signing (see JavaScript tab)
// 1. Create Unstaking Request
const stakingWallet = wallet.toStakingWallet();
const stakingRequest = await stakingWallet.unstake({
// For assets other than ETH, pass delegationId
delegationId: 'e0225adbc-66a3-4ccd-9a9d-726a05bca0cf',
// For ETH, pass delegationIds
// Excluding delegationIds unstakes from all validators
delegationIds: ['e0225adbc-66a3-4ccd-9a9d-726a05bca0cf'],
clientId: 'e055adbc-66a3-4ccd-9a9d-726a05bca0cf',
});
// 2. Get Request Status (Optional)
// Use webhooks or call the List staking requests endpoint via REST API
// 3. Approve Request (Optional)
const baseCoin = this.bitgoSDK.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
// 4. Sign and Send Request
const transactions = await stakingWallet.getTransactionsReadyToSign(stakingRequest.id);
if (!transactions.allSigningComplete && transactions.transactions.length > 0) {
transactions.transactions.forEach((transaction) => {
await stakingWallet.buildSignAndSend({ walletPassphrase: 'walletPassphrase' }, transaction);
});
}
// 1. Create Unstaking Request Response
{
"id": "e055adbc-66a3-4ccd-9a9d-726a05bca0cf",
"requestingUserId": "6092e75c451052000636831deb797bd1",
"type": "UNSTAKE",
"enterpriseId": "1032e75c451052000436831deb797af1",
"walletId": "2032e75g451052000636831abd797bd3",
"walletType": "hot",
"withdrawalAddress": "0xeea83a40a0fd35096b84395c1ae14900e460c7a3",
"coin": "hteth",
"status": "NEW",
"statusModifiedDate": "2023-04-19T23:15:12.7244Z",
"createdDate": "2023-04-19T23:15:12.724395Z",
"delegations": [
{
"id": "e0225adbc-66a3-4ccd-9a9d-726a05bca0cf",
"delegationAddress": "8dcf640ca21a6e411ce8a2645febdb45cc247272e9fe71246006a54222bcdf0c4881ed30b787d5383f622514483bb427",
"withdrawalAddress": "0xeea83a40a0fd35096b84395c1ae14900e460c7a3",
"delegated": "32003969181000000000",
"coin": "eth",
"walletId": "2032e75g451052000636831abd797bd3",
"status": "ACTIVE",
"rewards": "807047532000000000",
"lockedRewards": "0",
"pendingUnstake": "32003969181000000000",
"pendingStake": "0",
"reserved": "0",
"pendingReserved": "0",
"apy": "4.7200"
}
]
}
// 2. Get Request Status Response
{
"page": 1,
"totalPages": 1,
"totalElements": 1,
"requests": [
{
"id": "e055adbc-66a3-4ccd-9a9d-726a05bca0cf",
"status": "NEW",
"transactions": [
{
"id": "d0355adbc-55b43-5tta-9a9d-726a05bca0ai",
"status": "PENDING_APPROVAL",
"amount": "3200000000000000000",
"transactionType": "undelegate"
}
]
}
]
}
// 3. Approve Request Response
{
"id": "e055adbc-66a3-4ccd-9a9d-726a05bca0cf",
"coin": "hteth",
"wallet": "2032e75g451052000636831abd797bd3",
"enterprise": "1032e75c451052000436831deb797af1",
"state": "approved",
"approvalsRequired": 1
}
// 4. Sign and Send Request Response
{
"id": "e055adbc-66a3-4ccd-9a9d-726a05bca0cf",
"walletType": "hot",
"type": "UNSTAKE",
"coin": "hteth",
"status": "NEW",
"delegations": [
{
"id": "e0225adbc-66a3-4ccd-9a9d-726a05bca0cf",
"delegationAddress": "0x5a6406c9710f588ca733360bfa8033d0ef9ecdy5",
"delegated": 3200000000000000000,
"status": "PENDING"
}
],
"transactions": [
{
"stakingRequestId": "e055adbc-66a3-4ccd-9a9d-726a05bca0cf",
"status": "PENDING",
"amount": 3200000000000000000,
"transactionType": "undelegate"
}
],
"amount": 6400000000000000000
}