Crypto-as-a-Service: Transfer Between Go Accounts

Build, authenticate, and send an off-chain book transfer between two Go Accounts. See the Guide.

  1. Build a transaction from the source Go Account to the destination Go Account. Pass the destination Go Account wallet ID as the value of the address field in the recipient object — the recipient object uses address, not walletId. The response payload contains shortCircuitBlockchainTransfer: true and isIntraJXTransfer: true, confirming that BitGo recognized this as an off-chain book transfer.

    API Reference

  2. Use your Go Account passphrase to authenticate the transaction. To ensure your passphrase isn't passed over the Internet, you must use BitGo Express in external-signing mode or the JavaScript SDK. If you're using Express in external signing-mode, configure your Go Account passphrase as the WALLET_<walletId>_PASSPHRASE environment variable.

  3. Send the signed payload to BitGo. The halfSigned object takes only the two values returned by Step 2: payload (the transaction payload string from Step 1, returned verbatim by Step 2) and signature (the hex-encoded signature from Step 2). All transaction details are already encoded inside the payload string. The transactionType field in the response confirms that BitGo processed this as a BOOK_TRANSFER.

    API Reference

  4. If you configure an approval requirement for transfers, the transaction remains pending until another admin approves it — you can't approve your own transactions. Once approved, BitGo processes the book transfer and updates the ledger balances for both Go Accounts.

    API Reference

// 1. Build Transaction
export COIN="<CRYPTO_ASSET_ID>" # Crypto asset IDs in Go Accounts always start with "ofc" (such as ofctbtc)
export WALLET_ID="<SOURCE_GO_ACCOUNT_WALLET_ID>"
export SERVICE_USER_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>"
export DESTINATION_WALLET_ID="<DESTINATION_GO_ACCOUNT_WALLET_ID>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/build \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $SERVICE_USER_TOKEN" \
  -d '{
    "recipients": [
      {
        "amount": "'"$AMOUNT"'",
        "address": "'"$DESTINATION_WALLET_ID"'"
      }
    ]
}'
// 2. Authenticate Transaction
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export WALLET_PASSPHRASE="<YOUR_GO_ACCOUNT_PASSPHRASE>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/ofc/signPayload \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $SERVICE_USER_TOKEN" \
  -d '{
   "walletId": "'"$WALLET_ID"'",
   "walletPassphrase": "'"$WALLET_PASSPHRASE"'",
   "payload": "<PAYLOAD_FROM_BUILD_STEP>"
}'
// 3. Send Transaction
export PAYLOAD="<PAYLOAD_FROM_STEP_2>"
export SIGNATURE="<SIGNATURE_FROM_STEP_2>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/send \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $SERVICE_USER_TOKEN" \
  -d '{
    "halfSigned": {
      "payload": "'"$PAYLOAD"'",
      "signature": "'"$SIGNATURE"'"
    }
  }'
// 4. Approve Transaction (Optional)
export APPROVAL_ID="<APPROVAL_ID>"
export OTP="<OTP>"

curl -X PUT \
  https://app.bitgo-test.com/api/v2/pendingApprovals/$APPROVAL_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $SERVICE_USER_TOKEN" \
  -d '{
    "state": "approved",
    "otp": "'"$OTP"'"
}'
Response
// 1. Build Transaction Response
{
  "payload": "{\"coin\":\"ofctbtc\",\"recipients\":[{\"address\":\"2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY\",\"amount\":\"10000\"}],\"fromAccount\":\"63ff43c474598902272894f328452ad7\",\"nonce\":\"80bc93b5-eeec-4c11-afca-f6dae4bba2f2\",\"timestamp\":\"2023-09-28T10:55:39.135Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":true,\"isIntraJXTransfer\":true}",
  "feeInfo": { "feeString": "0" },
  "coin": "ofc",
  "token": "ofctbtc"
}

// 2. Authenticate Transaction Response
{
  "payload": "{\"coin\":\"ofctbtc\",\"recipients\":[{\"address\":\"2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY\",\"amount\":\"10000\"}],\"fromAccount\":\"63ff43c474598902272894f328452ad7\",\"nonce\":\"80bc93b5-eeec-4c11-afca-f6dae4bba2f2\",\"timestamp\":\"2023-09-28T10:55:39.135Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":true,\"isIntraJXTransfer\":true}",
  "signature": "1f989926e3fc8ed0138bd0e188e90e2c5321ef86734896886c004005740a005dfd2008142dbc48aee68d1f576c4a9ac558e5b7b4acbd5aa765710ea636aca9d032"
}

// 3. Send Transaction Response
{
  "transfer": {
    "id": "65155c4a72fddb000774edbee5fa75fd",
    "coin": "ofctbtc",
    "wallet": "63ff43c474598902272894f328452ad7",
    "walletType": "trading",
    "enterprise": "63f31592e277e50837712300495902c7",
    "txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
    "height": 999999999,
    "heightId": "999999999-65155c4a72fddb000774edbe",
    "date": "2023-09-28T10:58:18.272Z",
    "type": "send",
    "value": -10000,
    "valueString": "-10000",
    "baseValue": -10000,
    "baseValueString": "-10000",
    "feeString": "0",
    "payGoFee": 0,
    "payGoFeeString": "0",
    "state": "signed",
    "instant": false,
    "isReward": false,
    "isFee": false,
    "tags": [
      "63ff43c474598902272894f328452ad7",
      "63f31592e277e50837712300495902c7"
    ],
    "entries": [
      {
        "address": "63ff43c474598902272894f328452ad7",
        "wallet": "63ff43c474598902272894f328452ad7",
        "value": -10000,
        "valueString": "-10000"
      },
      {
        "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
        "value": 10000,
        "valueString": "10000"
      }
    ]
  },
  "txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
  "tx": {
    "transaction": {
      "coin": "ofctbtc",
      "recipients": [
        {
          "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
          "amount": "10000"
        }
      ],
      "fromAccount": "63ff43c474598902272894f328452ad7",
      "nonce": "80bc93b5-eeec-4c11-afca-f6dae4bba2f2",
      "timestamp": "2023-09-28T10:55:39.135Z",
      "feeString": "0",
      "shortCircuitBlockchainTransfer": true,
      "isIntraJXTransfer": true
    },
    "signature": "1f989926e3fc8ed0138bd0e188e90e2c5321ef86734896886c004005740a005dfd2008142dbc48aee68d1f576c4a9ac558e5b7b4acbd5aa765710ea636aca9d032",
    "transactionType": "BOOK_TRANSFER"
  },
  "status": "signed"
}

// 4. Approve Transaction (Optional) Response
{
  "id": "65155c4a72fddb000774edbee5fa75fd",
  "coin": "ofctbtc",
  "wallet": "63ff43c474598902272894f328452ad7",
  "enterprise": "63f31592e277e50837712300495902c7",
  "state": "approved"
}