Withdraw from Wallet - Self-Custody MPC Hot (Simple)

Overview

The simple withdrawal flow for self-custody MPC hot wallets enables you to build, sign, and send transactions, all in 1 call, using the BitGo JavaScript SDK. The simple flow suffices for most use cases. If you require more granular control, see the integration guide for the advanced flow.

The simple flow also supports sending to many recipients in 1 transaction, lowering the aggregate amount of blockchain fees when compared to creating multiple transactions. Sending to many aligns with the simple transaction flow, where in 1 call you build, sign, and send a half-signed transaction to BitGo. BitGo then uses the BitGo key to create a fully signed send-to-many transaction.

Just like with the advanced flow, you can configure wallet policies to require approvals on withdrawals. Once the transaction is half signed and approved, you send it to BitGo for final signing and broadcasting to the blockchain.

Prerequisites

1. Build, Sign, and Send Transaction

Build and sign the transaction and send it to BitGo, all in 1 call.

Additionally, you can create a send-to-many transaction that automatically invokes a batcher contract to send assets to multiple recipients. Currently, send-to-many transaction are available for ETH and MATIC and are limited to 200 recipients.

Endpoints:

  • cURL
  • JavaScript
  • JavaScript (send to many)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>" export COIN="<ASSET_ID>" export WALLET_ID="<YOUR_WALLET_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>" export ADDRESS="<DESTINATION_ADDRESS>" export AMOUNT="<AMOUNT_IN_BASE_UNITS>" curl -X POST \ http://$BITGO_EXPRESS_HOST:3080/api/v2/$COIN/wallet/$WALLET_ID/sendmany \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "walletPassphrase": "'"$WALLET_PASSPHRASE"'", "recipients": [ { "address": "'"$ADDRESS"'", "amount": "'"$AMOUNT"'" } ], "type": "transfer" }'

Step Result

BitGo uses the data you pass to build a half-signed transaction. The transaction remains in a pending-approval status until a wallet admin approves it.

  • JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 { "transfer": { "entries": [ { "address": "0x1a52b70e708f4aec9d92260aa035b3c71e51df84", "wallet": "665e33f768f9b4b1cc2ca87a6b87cdfb", "value": -1, "valueString": "-1" }, { "address": "0xe2c5b494162bd9033283af31e35be27c6ee4bbf7", "value": 1, "valueString": "1" } ], "id": "665e352e29c225381225e8f5f74f429d", "coin": "hteth", "wallet": "665e33f768f9b4b1cc2ca87a6b87cdfb", "walletType": "hot", "enterprise": "66325011d4b1ff58feae3b311d669aae", "organization": "66325011d4b1ff58feae3b76c2d30987", "txid": "0x43f7bef95dd02eea33d447afc625908a429902fbd35a35f0da6b7befddc69d9b", "txidType": "transactionHash", "txRequestId": "2c7e52a6-a422-49d3-876c-c050fb4cbf36", "height": 999999999, "heightId": "999999999-665e352e29c225381225e8f5f74f429d", "date": "2024-06-03T21:27:10.071Z", "type": "send", "value": -1, "valueString": "-1", "intendedValueString": "-1", "baseValue": -1, "baseValueString": "-1", "baseValueWithoutFees": -1, "baseValueWithoutFeesString": "-1", "feeString": "0", "payGoFee": 0, "payGoFeeString": "0", "usd": 0, "usdRate": 3775.4311802956, "state": "signed", "instant": false, "isReward": false, "isUnlock": false, "isFee": false, "tags": [ "665e33f768f9b4b1cc2ca87a6b87cdfb", "66325011d4b1ff58feae3b311d669aae" ], "history": [ { "date": "2024-06-03T21:27:10.071Z", "action": "signed" }, { "date": "2024-06-03T21:27:10.020Z", "user": "660d7c9fa6fbf0d00b415146cf70405a", "action": "created" } ], "signedDate": "2024-06-03T21:27:10.071Z", "coinSpecific": { "isMev": false }, "metadata": [], "signedTime": "2024-06-03T21:27:10.071Z", "createdTime": "2024-06-03T21:27:10.020Z" }, "txRequest": { "apiVersion": "full", "txRequestId": "2c7e52a6-a422-49d3-876c-c050fb4cbf36", "walletId": "665e33f768f9b4b1cc2ca87a6b87cdfb", "walletType": "hot", "version": 10, "enterpriseId": "66325011d4b1ff58feae3b311d669aae", "organizationId": "66325011d4b1ff58feae3b76c2d30987", "userId": "660d7c9fa6fbf0d00b415146cf70405a", "initiatedBy": "660d7c9fa6fbf0d00b415146cf70405a", "updatedBy": "660d7c9fa6fbf0d00b415146cf70405a", "policiesChecked": true, "date": "2024-06-03T21:27:10.203Z", "createdDate": "2024-06-03T21:27:01.066Z", "intent": { "intentType": "payment", "recipients": [ { "address": { "address": "0xE2C5b494162bd9033283Af31e35Be27C6Ee4Bbf7" }, "amount": { "value": "1", "symbol": "hteth" } } ], "feeOptions": { "baseFee": "1005178132", "gasUsedRatio": "0.2743939", "safeLowMinerTip": "10896128", "normalMinerTip": "22751361", "standardMinerTip": "498266940", "fastestMinerTip": "437486468", "ludicrousMinerTip": "1500000000", "maxPriorityFeePerGas": "498266940", "maxFeePerGas": "2508623204" }, "senderAddressIndex": 0 }, "intents": [ { "intentType": "payment", "recipients": [ { "address": { "address": "0xE2C5b494162bd9033283Af31e35Be27C6Ee4Bbf7" }, "amount": { "value": "1", "symbol": "hteth" } } ], "feeOptions": { "baseFee": "1005178132", "gasUsedRatio": "0.2743939", "safeLowMinerTip": "10896128", "normalMinerTip": "22751361", "standardMinerTip": "498266940", "fastestMinerTip": "437486468", "ludicrousMinerTip": "1500000000", "maxPriorityFeePerGas": "498266940", "maxFeePerGas": "2508623204" }, "senderAddressIndex": 0 } ], "state": "delivered", "latest": true, "transactions": [ { "state": "delivered", "signatureShares": [], "commitmentShares": [], "unsignedTx": { "parsedTx": { "minerFee": "0", "spendAmount": "1", "spendAmounts": [ { "coinName": "hteth", "amountString": "1" } ], "outputs": [ { "address": "0xe2c5b494162bd9033283af31e35be27c6ee4bbf7", "wallets": [], "enterprises": [], "valueString": "1", "coinName": "hteth" } ], "inputs": [ { "value": 1, "address": "0x1a52b70e708f4aec9d92260aa035b3c71e51df84", "valueString": "1" } ], "hasUnvalidatedData": false }, "serializedTxHex": "02ed82426880841db2f33c8495868d648301637894e2c5b494162bd9033283af31e35be27c6ee4bbf70180c0808080", "signableHex": "02ea82426880841db2f33c8495868d648301637894e2c5b494162bd9033283af31e35be27c6ee4bbf70180c0", "feeInfo": { "fee": 136813501552000, "feeString": "136813501552000" }, "derivationPath": "m" }, "txHash": "0x43f7bef95dd02eea33d447afc625908a429902fbd35a35f0da6b7befddc69d9b", "signedTx": { "id": "0x43f7bef95dd02eea33d447afc625908a429902fbd35a35f0da6b7befddc69d9b", "tx": "0x02f86d82426880841db2f33c8495868d648301637894e2c5b494162bd9033283af31e35be27c6ee4bbf70180c080a0631c4464bcb29519ac7e3998955c1bda374d058868557661c3711d531cb37e62a04836e3cf75969a2ddd9c38981d1b6fade02733059544c74784f9a85e62da8719" }, "updatedDate": "2024-06-03T21:27:10.215Z", "createdDate": "2024-06-03T21:27:01.072Z" } ], "messages": [], "isCanceled": false }, "txid": "0x43f7bef95dd02eea33d447afc625908a429902fbd35a35f0da6b7befddc69d9b", "tx": "0x02f86d82426880841db2f33c8495868d648301637894e2c5b494162bd9033283af31e35be27c6ee4bbf70180c080a0631c4464bcb29519ac7e3998955c1bda374d058868557661c3711d531cb37e62a04836e3cf75969a2ddd9c38981d1b6fade02733059544c74784f9a85e62da8719", "status": "signed" }

2. Approve Transaction (Optional)

Note: You can't approve your own transactions - another admin must approve them.

Endpoint: Update Pending Approval

  • cURL
  • JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>" export COIN="<ASSET_ID>" export APPROVAL_ID="<APPROVAL_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>" curl -X PUT \ https://$BITGO_EXPRESS_HOST:3080/api/v2/$COIN/pendingApprovals/$APPROVAL_ID \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "state": "approved", "walletPassphrase": "'"$WALLET_PASSPHRASE"'" }'

Step Result

Once approved, BitGo rebuilds the half-signed transaction, applying the most up-to-date fees. BitGo then applies the final signature using the BitGo key and broadcasts the transaction to the blockchain.

  • JSON
  • JSON (send to many)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 { "id": "66b66201c45ab3125fc2d8a77b541d12", "coin": "tsol", "wallet": "669569464cec3c82c9b524faf0d42087", "wallets": [], "enterprise": "6672220dd9e61ce3d62e9e2d710cbd6f", "organization": "66722210d9e61ce3d62e9e997100b40a", "bitgoOrg": "BitGo Trust", "creator": "6672175d79369c8ad556deaca06abeea", "createDate": "2024-08-09T18:37:53.078Z", "approvedDate": "2024-08-09T18:38:47.371Z", "info": { "type": "transactionRequestFull", "transactionRequestFull": { "txRequestId": "0b259f23-d5a8-47d0-8666-47a3df07e244", "videoApprovers": [], "intent": { "intentType": "payment", "recipients": [ { "address": { "address": "ESda41265eU4typ7Q7MFnBuaYUvV3rYsJyrGQzqo6YZn" }, "amount": { "value": "500000", "symbol": "tsol" } } ] } } }, "approvers": [], "state": "approved", "scope": "wallet", "userIds": [ "6672175d79369c8ad556deaca06abeea", "6672292d89bd038e41cfb93b6ee482f1" ], "approvalsRequired": 1, "singleRunResults": [], "txRequestId": "0b259f23-d5a8-47d0-8666-47a3df07e244", "resolvers": [ { "user": "6672292d89bd038e41cfb93b6ee482f1", "date": "2024-08-09T18:38:45.245Z", "resolutionType": "pending", "resolutionAction": "approve" } ], "policyEvaluationId": "8dc3ffdd-50ea-4ab6-9742-963a12eb4f6c", "actions": [ { "id": "d0bcc3af-b341-4b1c-9c7e-723ff4bc7259", "status": "COMPLETE", "name": "approvals.customer.walletAdmin", "parameters": { "minRequired": "1", "userIds": [] }, "resolvers": [ { "user": "6672292d89bd038e41cfb93b6ee482f1", "date": "2024-08-09T18:38:45.245Z", "resolutionType": "pending", "resolutionAction": "approve" } ], "approvers": [] } ], "resolutionOrder": [ { "actions": [ "d0bcc3af-b341-4b1c-9c7e-723ff4bc7259" ] } ] }

Next

You can view your completed withdrawal in BitGo or on a blockchain explorer.

See Also