Withdraw from Wallet - Self-Custody Multisig Cold

Overview

You initiate withdrawals self-custody multisignature cold wallets by submitting transaction details to BitGo. BitGo uses the data you pass to construct an unsigned transaction that you take to the the Offline Vault Console (OVC), where wallet co-signers can apply their signature. After signing in the OVC, you upload the half-signed transaction to BitGo to enable wallet admins approvals. Once the transaction is half signed and approved, BitGo receives it for final signing and broadcasting to the blockchain.

Prerequisites

1. Build Transaction

Build the transaction by specifying the transaction details and sending them to BitGo. The following example is shows the minimum required parameters for sending bitcoin.

Endpoint: Build a Transaction

  • cURL
  • JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 export COIN="<ASSET_ID>" export WALLET_ID="<YOUR_WALLET_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" export ADDRESS="<DESTINATION_ADDRESS>" export AMOUNT="<AMOUNT_IN_BASE_UNITS>" curl -X POST \ https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/build \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "recipients": [ { "amount": "'"$AMOUNT"'", "address": "'"$ADDRESS"'" } ] }'

Step Result

BitGo uses the data you pass to build an unsigned transaction. Save this JSON file to an SD card for transfer to the OVC. The following example builds a withdrawal of 10,000 sats of TBTC4.

  • 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 { "txHex": "01000000010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000000ffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e6269839900000000", "txInfo": { "nP2SHInputs": 0, "nSegwitInputs": 1, "nOutputs": 2, "unspents": [ { "chain": 10, "index": 5, "redeemScript": "0020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467daf", "witnessScript": "522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae", "id": "d5621704d7dd06d55c6016709e75a1787fb661d565290611e3eff914f03a4d0e:0", "address": "2N5bzKehiq63uqT9hKDVaPWm1LmrPbHDz2S", "value": 100000, "valueString": "100000" } ], "changeAddresses": [ "tb1ps5xs4drx69wtz4ja655dfktsnulydaqag8lxm992qymcucnfswvspwdwxq" ], "walletAddressDetails": { "tb1ps5xs4drx69wtz4ja655dfktsnulydaqag8lxm992qymcucnfswvspwdwxq": { "chain": 41, "index": 3, "coinSpecific": {} } }, "txHexes": {} }, "feeInfo": { "size": 226, "fee": 20451, "feeRate": 90491, "feeString": "20451", "payGoFee": 0, "payGoFeeString": "0" }, "debug": { "dimensions": { "nP2shInputs": 0, "nP2shP2wshInputs": 1, "nP2wshInputs": 0, "nP2trKeypathInputs": 0, "nP2trScriptPathLevel1Inputs": 0, "nP2trScriptPathLevel2Inputs": 0, "nP2shP2pkInputs": 0, "outputs": { "count": 2, "size": 75 } } }, "coin": "tbtc4" }

2. Sign Transaction

Upload the unsigned transaction returned in the prior step to the OVC and sign it there with your private key.

3. Send Transaction

Using the txHex obtained in the prior step, send the half-signed transaction to BitGo.

Endpoint: Send a Half-Signed Transaction

  • cURL
  • JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 export COIN="<ASSET_ID>" export WALLET_ID="<YOUR_WALLET_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" curl -X POST \ https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/send \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "halfSigned": { "txHex": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990500483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201000069522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000" } }'

Step Result

If your withdrawal doesn't require approval, then BitGo receives the transaction for final signing with the BitGo key and broadcasting to the blockchain. If you Create Policy Rules to require approvals on withdrawals, the transaction remains in a pending-approval status until a wallet admin approves it.

  • JSON (approval not required)
  • JSON (pending approval)
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 { "transfer": { "entries": [ { "address": "2NAVwU9KtPyE4h3RyHkhbLgQQvrc4EuSXD3", // Sender address "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0", "value": -100000, "valueString": "-100000" }, { "address": "2Mw241n14gJx2PcK2kijidZ2BPGeJBdwp1A", // Receiver address "value": 10000, "valueString": "10000", "isChange": false, "isPayGo": false }, { "address": "tb1pq9m0lqjg4lfa0rj9wzjjjumk3l6vecndt8wla5756ktre6h6fexqg7z0vq", // Change address that collects the UTXO "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0", "value": 70013, "valueString": "70013", "isChange": true, "isPayGo": false } ], "id": "65528cde229f765c57a8f4d1eb762908", "coin": "tbtc4", "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0", "walletType": "hot", "enterprise": "62c5ae8174ac860007aff138a2d74df7", "txid": "c68916ddc1672ec62c474ef0839ec479ad9b2dabc2249177ce6be6247f81dfe7", "txidType": "transactionHash", "height": 999999999, "heightId": "999999999-65528cde229f765c57a8f4d1eb762908", "date": "2023-11-13T20:53:51.445Z", "type": "send", "value": -29987, "valueString": "-29987", "intendedValueString": "-29987", "baseValue": -10000, "baseValueString": "-10000", "baseValueWithoutFees": -10000, "baseValueWithoutFeesString": "-10000", "feeString": "19987", "payGoFee": 0, "payGoFeeString": "0", "usd": -11.0275843085, "usdRate": 36774.55, "state": "signed", "instant": false, "isReward": false, "isFee": false, "tags": [ "654ec786c07fe8dc0dcfe03916ec5bb0", "62c5ae8174ac860007aff138a2d74df7" ], "history": [ { "date": "2023-11-13T20:53:51.444Z", "action": "signed" }, { "date": "2023-11-13T20:53:50.646Z", "user": "62ab90e06dfda30007974f0a52a12995", "action": "created" } ], "signedDate": "2023-11-13T20:53:51.444Z", "vSize": 225, "metadata": [], "signedTime": "2023-11-13T20:53:51.444Z", "createdTime": "2023-11-13T20:53:50.646Z" }, "txid": "c68916ddc1672ec62c474ef0839ec479ad9b2dabc2249177ce6be6247f81dfe7", "tx": "01000000000101c76ddd01e185e12e995c6f4f36bd440867296d3f224751d73432d465be93478100000000232200204fe0358ee98bef039832fa3a4dc96cb4b265448f3d89c4a05a997a3481f3da6effffffff02102700000000000017a9142962c500562c9db56434702a629ff08fcbd5add0877d110100000000002251200176ff8248afd3d78e4570a52973768ff4cce26d59ddfed3d4d5963ceafa4e4c0400483045022100c4db3db14398d5cc4c9a2a3e4a8fa4fa3b8960ad80eb840e51e182f7561cf6c102207a6410e68aaf7327a1daed83838a39b96e37e22783d879a838640035b6059bcc0147304402205888b2863bb8fc296ed51374db2d03c7fdc746fd0d6c5ceebbe2246bb76b67840220730c8b8395285767ef1049c40cd6cbdecfb5ecfefd795ac2053b28b7a6b0790f0169522103a4c6a0aa167ef75fcf4a96c53b2dd20aee3afa19d1bc2ec4354328ae87c0976621022e4d77a9d0fecafc7ad4f9cfd9144082cf146b27de945ba26d22f26438c5784b2103ee2fef2c21d48bbd0d3813c71269fca6e1bff51e676b1f0131aa29afceb08f8853ae00000000", "status": "signed" }

4. Approve Transaction (Optional)

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

Endpoint: Update Pending Approval

  • cURL
  • JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 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"'" }'

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.

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 { "id": "65529448bd87efe59c3b0156ddfce867", "coin": "tbtc4", "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0", "enterprise": "62c5ae8174ac860007aff138a2d74df7", "creator": "62ab90e06dfda30007974f0a52a12995", "createDate": "2023-11-13T21:25:28.022Z", "info": { "type": "transactionRequest", "transactionRequest": { "requestedAmount": "10000", "fee": 20451, "sourceWallet": "654ec786c07fe8dc0dcfe03916ec5bb0", "policyUniqueId": "654ec786c07fe8dc0dcfe03f", "recipients": [ { "address": "2N1UvKhtSHLUa9YomSH7n9YMFCkMG2pbmsQ", "amount": "10000", "_id": "65529448bd87efe59c3b0158" } ], "coinSpecific": { "tbtc4": { "txHex": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990500483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201000069522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000" } }, "validTransaction": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990400483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201473044022049e20c0073f42c9636408efc6c833ebf0e1a8ef13e8cb818dde2f4e2af7f7b7f022000cb3a321d65605b9d51d7f87e34306169607646c8d54a44011b021eff3dbe500169522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000", "validTransactionHash": "5ea8d2b93997ed9fa3597a2f3113817c8216f573a0278c2533bb5db50fdb0dff" } }, "state": "approved", "scope": "wallet", "userIds": [ "62ab90e06dfda30007974f0a52a12995", "621d08a634ad8a0007fcddffd7c429cc" ], "approvalsRequired": 1, "singleRunResults": [ { "ruleId": "Custody Enterprise Transaction ID Verification", "triggered": false, "_id": "65529448bd87efe59c3b0157" } ], "resolvers": [ { "user": "621d08a634ad8a0007fcddffd7c429cc", "date": "2023-11-13T21:44:27.794Z", "resolutionType": "pending" } ] }

Next

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

See Also