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

Source: https://developers.bitgo.com/docs/withdraw-wallet-type-self-custody-mpc-simple

## Overview

The simple withdrawal flow for self-custody MPC wallets enables you to build, sign, and send transactions, all in one 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 [manual](/docs/withdraw-wallet-type-self-custody-mpc-manual) 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 one 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 manual flow, you can configure wallet policies to require approvals on withdrawals. Once a wallet admin half signs and approves the transaction, you send it to BitGo for final signing and broadcasting to the blockchain.

## Prerequisites

* [Get Started](/docs/get-started-intro)
* [Create Wallets](/docs/wallets-create-wallets)
* [Create Whitelists](/docs/wallets-whitelists-create)
* [Deposit Assets](/docs/deposit-assets)

## Cookbook

Need just the steps? Expand the cookbook below to get started:

<Cookbook slug="withdraw-self-custody-mpc-simple" title="Withdraw - Self-Custody MPC (Simple)" />

## 1. Build, Sign, and Send Transaction

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

Additionally, you can create a send-to-many transaction that automatically invokes a [batcher contract](https://github.com/BitGo/eth-multisig-v4/blob/master/contracts/Batcher.sol) to send assets to multiple recipients. Currently, send-to-many transactions are available for ETH and MATIC and support up to 200 recipients.

>Endpoints:
> * [Create a signature share for the transaction request](/reference/v2wallettxrequestsignaturesharecreate)
> * [Get transaction requests by wallet](/reference/v2wallettxrequestget)

```js JavaScript
import * as dotenv from "dotenv";
import {EnvironmentName} from "bitgo";
import {BitGoAPI} from "@bitgo/sdk-api";
import {Hteth} from "@bitgo/sdk-coin-eth";

dotenv.config();

const config = {
    USERNAME: process.env.USERNAME as string,
    PASSWORD: process.env.PASSWORD as string,
    ENV: process.env.ENV as EnvironmentName,
    OTP: process.env.OTP as string,
    ENTERPRISE_ID: process.env.ENTERPRISE_ID as string,
    WALLET_ID: process.env.WALLET_ID as string,
    WALLET_PASS_PHRASE: process.env.WALLET_PASS_PHRASE as string
};

const bitgo = new BitGoAPI({env: config.ENV});
bitgo.register("hteth", Hteth.createInstance);
const coin = bitgo.coin("hteth");

async function auth() {
    await bitgo.authenticate({
        username: config.USERNAME,
        password: config.PASSWORD,
        otp: config.OTP,
    });
    await bitgo.lock();
    await bitgo.unlock({otp: "000000", duration: 3600});
}

async function main() {
    await auth();
    const destinatonAddress = "0x1037c88b10fbd0754b9fbd3ba7be41fe7cb61f59";
    const wallet = await coin.wallets().get({id: config.WALLET_ID});
    const sendAmount = wallet.balanceString() ?? 0;
    const res = await wallet.sendMany({
        walletPassphrase: config.WALLET_PASS_PHRASE,
        recipients: [{address: destinatonAddress, amount: sendAmount}],
        type: "transfer",
    });
    console.log(res);
}

main().catch((err) => console.error(err));
```
```js JavaScript (send to many)
import * as dotenv from "dotenv";
import {EnvironmentName} from "bitgo";
import {BitGoAPI} from "@bitgo/sdk-api";
import {Hteth} from "@bitgo/sdk-coin-eth";

dotenv.config();

const config = {
    USERNAME: process.env.USERNAME as string,
    PASSWORD: process.env.PASSWORD as string,
    ENV: process.env.ENV as EnvironmentName,
    OTP: process.env.OTP as string,
    ENTERPRISE_ID: process.env.ENTERPRISE_ID as string,
    WALLET_ID: process.env.WALLET_ID as string,
    WALLET_PASS_PHRASE: process.env.WALLET_PASS_PHRASE as string
};

const bitgo = new BitGoAPI({env: config.ENV});
bitgo.register("hteth", Hteth.createInstance);
const coin = bitgo.coin("hteth");

async function auth() {
    await bitgo.authenticate({
        username: config.USERNAME,
        password: config.PASSWORD,
        otp: config.OTP,
    });
    await bitgo.lock();
    await bitgo.unlock({otp: "000000", duration: 3600});
}

async function main() {
    await auth();
    const destinatonAddress = "0x1037c88b10fbd0754b9fbd3ba7be41fe7cb61f59";
    const wallet = await coin.wallets().get({id: config.WALLET_ID});
    const totalAmount = wallet.balanceString();
    let totalAmountAsNumber = +totalAmount;
    const sendAmount = (totalAmountAsNumber / 200) - 10000; //desired amount to send
    const recipients = Array(10).fill( //Construct the required recipients array
        {
            amount: String(sendAmount),
            address: destinatonAddress
        }, 0, 10);
    console.log(JSON.stringify(recipients))
    const res = await wallet.sendMany({
        walletPassphrase: config.WALLET_PASS_PHRASE,
        recipients: recipients,
        type: "transfer",
        isTss: true,
    });
    console.log(`Batch Transfer for coin: ${coin} completed. TxId: ${res.txid}`)
    console.log(JSON.stringify(res));
    console.log("Batch transfers completed.");
}

main().catch((err) => console.error(err));
```

#### 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 JSON
{
  "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](/reference/v2approvalupdate)

```shell cURL
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 \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/pendingApprovals/$APPROVAL_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "state": "approved",
    "walletPassphrase": "'"$WALLET_PASSPHRASE"'"
  }'
```
```js JavaScript
const baseCoin = this.bitgoSDK.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
```

#### Step Result

After a wallet admin approves the transaction, 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
{
  "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"
      ]
    }
  ]
}
```
```json JSON (send to many)
{
  "id": "66b662a6229e503a24b4f1eca9787cb7",
  "coin": "tsol",
  "wallet": "669569464cec3c82c9b524faf0d42087",
  "wallets": [],
  "enterprise": "6672220dd9e61ce3d62e9e2d710cbd6f",
  "organization": "66722210d9e61ce3d62e9e997100b40a",
  "bitgoOrg": "BitGo Trust",
  "creator": "6672175d79369c8ad556deaca06abeea",
  "createDate": "2024-08-09T18:40:38.927Z",
  "approvedDate": "2024-08-09T18:41:06.681Z",
  "info": {
    "type": "transactionRequestFull",
    "transactionRequestFull": {
      "txRequestId": "ae8d598e-f084-4ecb-a3b3-b81ff68e67e4",
      "videoApprovers": [],
      "intent": {
        "intentType": "payment",
        "recipients": [
          {
            "address": {
              "address": "ESda41265eU4typ7Q7MFnBuaYUvV3rYsJyrGQzqo6YZn"
            },
            "amount": {
              "value": "500000",
              "symbol": "tsol"
            }
          },
          {
            "address": {
              "address": "BaKnSGoQCrTU6NJhVT8tdaMceSFmb7RGv74AEebfqJcg"
            },
            "amount": {
              "value": "500000",
              "symbol": "tsol"
            }
          }
        ]
      }
    }
  },
  "approvers": [],
  "state": "approved",
  "scope": "wallet",
  "userIds": [
    "6672175d79369c8ad556deaca06abeea",
    "6672292d89bd038e41cfb93b6ee482f1"
  ],
  "approvalsRequired": 1,
  "singleRunResults": [],
  "txRequestId": "ae8d598e-f084-4ecb-a3b3-b81ff68e67e4",
  "resolvers": [
    {
      "user": "6672292d89bd038e41cfb93b6ee482f1",
      "date": "2024-08-09T18:41:04.386Z",
      "resolutionType": "pending",
      "resolutionAction": "approve"
    }
  ],
  "policyEvaluationId": "cc99d8a1-dd13-479b-b300-77f6a1cefb64",
  "actions": [
    {
      "id": "a41f81a2-bc8e-49fa-b28a-e6215746161e",
      "status": "COMPLETE",
      "name": "approvals.customer.walletAdmin",
      "parameters": {
        "minRequired": "1",
        "userIds": []
      },
      "resolvers": [
        {
          "user": "6672292d89bd038e41cfb93b6ee482f1",
          "date": "2024-08-09T18:41:04.386Z",
          "resolutionType": "pending",
          "resolutionAction": "approve"
        }
      ],
      "approvers": []
    }
  ],
  "resolutionOrder": [
    {
      "actions": [
        "a41f81a2-bc8e-49fa-b28a-e6215746161e"
      ]
    }
  ]
}
```

## Next

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

## See Also

* [MPC Error Recovery](/docs/withdraw-mpc-error-recovery)
* [API Reference: Send to Many](/reference/expresswalletsendmany)
* [API Reference: Send Transaction](/reference/expresswalletsendcoins)
* [API Reference: Update Pending Approval](/reference/v2approvalupdate)
