Proof of Reserves

Overview

You can take steps to provide assurances and transparency to your clients and end users by verifying proof of reserves (PoR). Providing PoR is especially important for cryptocurrency exchanges and trading platforms, as it enables you to prove liquidity and solvency.

BitGo offers multiple REST APIs that you can use to return your balances and other wallet details. In its most basic form, PoR entails sharing your balances and public addresses. Clients and end users can then confirm your balances on their respective blockchains. If you require more in depth PoR, you can partner with third-party auditors. Using a Merkle tree, auditors can anonymize data and confirm ownership of individuals' assets within your wallets.

You can verify PoR for custody and self-custody wallets. However, you can't verify PoR for Go Accounts, due to the off-chain ledger they use.

Prerequisites

Steps

1. List Wallets

Get a list of your wallets, and determine which among these constitute your reserves. BitGo recommends that you use custody wallets for your reserves, as these provide maximum security.

GET /api/v2/wallets

Step Result

Save the id for the wallets that make up your reserves.

{
    "wallets": [
        {
            "id": "62f0418088859b0007ad2c1337e402f0",
            "users": [
                {
                    "user": "62ab90e06dfda30007974f0a52a12995",
                    "permissions": [
                        "admin",
                        "view",
                        "spend"
                    ]
                }
            ],
            "coin": "btc",
            "label": "Cold BTC Wallet",
            "m": 2,
            "n": 3,
            "keys": [
                "62f04084d540700007a1da45e6a4d28e",
                "62f040cce56ef50007af49c09cafaf90",
                "62f040e05eec400007bd55f532d86fac"
            ],
            "keySignatures": {},
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "tags": [
                "62f0418088859b0007ad2c1337e402f0",
                "62c5ae8174ac860007aff138a2d74df7"
            ],
            "disableTransactionNotifications": false,
            "freeze": {},
            "deleted": false,
            "approvalsRequired": 1,
            "isCold": true,
            "coinSpecific": {},
            "admin": {},
            "clientFlags": [],
            "walletFlags": [],
            "allowBackupKeySigning": false,
            "startDate": "2022-08-07T22:49:36.000Z",
            "type": "cold",
            "buildDefaults": {},
            "customChangeKeySignatures": {},
            "hasLargeNumberOfAddresses": false,
            "multisigType": "onchain",
            "config": {},
            "balance": 1256709,
            "confirmedBalance": 1256709,
            "spendableBalance": 1256709,
            "balanceString": "1256709",
            "confirmedBalanceString": "1256709",
            "spendableBalanceString": "1256709"
        },
        {
            "id": "62f03dee8d13be0007894b3dbc21be17",
            "users": [
                {
                    "user": "62ab90e06dfda30007974f0a52a12995",
                    "permissions": [
                        "admin",
                        "view",
                        "spend"
                    ]
                }
            ],
            "coin": "dot",
            "label": "MPC DOT Wallet",
            "m": 2,
            "n": 3,
            "keys": [
                "62f03dee8d13be0007894b41f63bc504",
                "62f03dee8d13be0007894b43cb0f65d0",
                "62f03dee8d13be0007894b3f8024e0e8"
            ],
            "keySignatures": {},
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "tags": [
                "62f03dee8d13be0007894b3dbc21be17",
                "62c5ae8174ac860007aff138a2d74df7"
            ],
            "disableTransactionNotifications": false,
            "freeze": {},
            "deleted": false,
            "approvalsRequired": 1,
            "isCold": true,
            "coinSpecific": {
                "pendingChainInitialization": false,
                "rootAddress": "5G4oQ1xMu5V4y9Cdp9zPnVR57Nh8vsbYRRTei7MmQU6e1DHv",
                "lastNonce": 0,
                "lastChainIndex": {
                    "0": 1,
                    "1": -1
                }
            },
            "admin": {},
            "clientFlags": [],
            "walletFlags": [],
            "allowBackupKeySigning": false,
            "startDate": "2022-08-07T22:34:22.000Z",
            "type": "custodial",
            "buildDefaults": {},
            "customChangeKeySignatures": {},
            "hasLargeNumberOfAddresses": false,
            "multisigType": "MPC",
            "config": {},
            "balanceString": "2000000000000",
            "confirmedBalanceString": "2000000000000",
            "spendableBalanceString": "0"
        },
        {
            "id": "62c75ed042852800082440d8d63a4319",
            "users": [
                {
                    "user": "62ab90e06dfda30007974f0a52a12995",
                    "permissions": [
                        "admin",
                        "view",
                        "spend"
                    ]
                }
            ],
            "coin": "btc",
            "label": "Hot BTC Wallet",
            "m": 2,
            "n": 3,
            "keys": [
                "62c75ecf871f420008f23497a2ea1174",
                "62c75ecfd2d04f000858d79f4ee278ae",
                "62c75ecf3f7ede0007f9b398aafdf07b"
            ],
            "keySignatures": {
                "backupPub": "209faade005392cf930a2325db3dfba92cfa90fb27971c2b842768059f9caf653a1b76d893c3442b83549c82b8c97580948d3208d4b6e81e49c02dbb7648db1d99",
                "bitgoPub": "2089747b9eee580371691db42a85a7f3b93fd1b8be30dacdcfe537e5b48291b1462ea34afbbbc26ba11dbb5f2077843915ea812c1a6268b89d9977511563be241e"
            },
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "tags": [
                "62c75ed042852800082440d8d63a4319",
                "62c5ae8174ac860007aff138a2d74df7"
            ],
            "disableTransactionNotifications": false,
            "freeze": {},
            "deleted": false,
            "approvalsRequired": 1,
            "isCold": false,
            "coinSpecific": {},
            "admin": {},
            "clientFlags": [],
            "walletFlags": [],
            "allowBackupKeySigning": false,
            "startDate": "2022-07-07T22:31:44.000Z",
            "type": "hot",
            "buildDefaults": {},
            "customChangeKeySignatures": {},
            "hasLargeNumberOfAddresses": false,
            "multisigType": "onchain",
            "config": {},
            "balance": 232687,
            "confirmedBalance": 232687,
            "spendableBalance": 232687,
            "balanceString": "232687",
            "confirmedBalanceString": "232687",
            "spendableBalanceString": "232687"
        },
        {
            "id": "62c60db8b19ca800088f8ed53eb2e628",
            "users": [
                {
                    "user": "62ab90e06dfda30007974f0a52a12995",
                    "permissions": [
                        "admin",
                        "view",
                        "spend"
                    ]
                }
            ],
            "coin": "xrp",
            "label": "Cold XRP Wallet",
            "m": 2,
            "n": 3,
            "keys": [
                "62c60db8b19ca800088f8edd5ae4d4e7",
                "62c60db8b19ca800088f8ee378424d5f",
                "62c60db9b19ca800088f8f5f7ec220db"
            ],
            "keySignatures": {},
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "tags": [
                "62c60db8b19ca800088f8ed53eb2e628",
                "62c5ae8174ac860007aff138a2d74df7"
            ],
            "disableTransactionNotifications": false,
            "freeze": {},
            "deleted": false,
            "approvalsRequired": 1,
            "isCold": true,
            "coinSpecific": {
                "rootAddress": "rM2ESyPZwycfRwQvNo8MHKi5hAXZgjpj1X",
                "pendingChainInitialization": false,
                "creationFailure": []
            },
            "admin": {},
            "clientFlags": [],
            "walletFlags": [],
            "allowBackupKeySigning": false,
            "startDate": "2022-07-06T22:33:28.000Z",
            "type": "custodial",
            "buildDefaults": {},
            "customChangeKeySignatures": {},
            "hasLargeNumberOfAddresses": false,
            "multisigType": "onchain",
            "config": {},
            "balanceString": "12000000",
            "confirmedBalanceString": "12000000",
            "spendableBalanceString": "0"
        },
        {
            "id": "62c5b5c9d0ece30007cec9616ff29edc",
            "users": [
                {
                    "user": "62ab90e06dfda30007974f0a52a12995",
                    "permissions": [
                        "admin",
                        "view",
                        "spend"
                    ]
                }
            ],
            "coin": "btc",
            "label": "My Demo BTC Wallet",
            "m": 2,
            "n": 3,
            "keys": [
                "62c5b54a8ec0290007324c0fab5337f6",
                "62c5b54a8a0c5200071e49a857e50b0e",
                "62c5b54bd0ece30007ce8377f23f264f"
            ],
            "keySignatures": {},
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "tags": [
                "62c5b5c9d0ece30007cec9616ff29edc",
                "62c5ae8174ac860007aff138a2d74df7"
            ],
            "disableTransactionNotifications": false,
            "freeze": {},
            "deleted": false,
            "approvalsRequired": 1,
            "isCold": false,
            "coinSpecific": {},
            "admin": {},
            "clientFlags": [],
            "walletFlags": [],
            "allowBackupKeySigning": false,
            "startDate": "2022-07-06T16:18:17.000Z",
            "type": "hot",
            "buildDefaults": {},
            "customChangeKeySignatures": {},
            "hasLargeNumberOfAddresses": false,
            "multisigType": "onchain",
            "config": {},
            "balance": 1089773,
            "confirmedBalance": 1089773,
            "spendableBalance": 1089773,
            "balanceString": "1089773",
            "confirmedBalanceString": "1089773",
            "spendableBalanceString": "1089773"
        },
    ]
}

2. List Addresses

Using the wallet ids, get all the addresses for your reserve wallets.

GET /api/v2/{coin}/wallet/{walletId}/addresses?includeBalances=true

Step Result

Save each address that contains a balance. These are public addresses that can anyone can search for on their respective block chains.

{
    "coin": "btc",
    "totalAddressCount": 3,
    "addresses": [
        {
            "id": "62f0418088859b0007ad2c23dd2a316e",
            "address": "2MxNxcyy4Jt4NQGkwR8bVD6pYPDSMhQqkmr",
            "chain": 10,
            "index": 1,
            "coin": "btc",
            "wallet": "62f0418088859b0007ad2c1337e402f0",
            "coinSpecific": {
                "redeemScript": "00201ca0444be0e22067cf8ed6cbc81268ade365e0559844d00eedf3b0af22e9bfc0",
                "witnessScript": "5221020292b2ee9c27e3d1425b8516ebd43351b2d163b7dfb839a36b9c73e40afe043021029b387b9a41acbcf0f6c8c0fd72247a0670dcc7bcf0e0c19d466253b6e8b6cbb821023f3e4bec6ff7d805f168e7ce80a813c3f0df26f4b29e1dea3bbeda90291d1e8f53ae"
            },
            "balance": {
                "updated": "2022-08-31T16:07:28.000Z",
                "balance": 1256709,
                "balanceString": "1256709",
                "totalReceived": 1256709,
                "totalSent": 0,
                "confirmedBalanceString": "1256709",
                "spendableBalanceString": "1256709",
                "tokens": {}
            }
        },
        {
            "id": "630f8734f2d4160007837e4c34a1a9b2",
            "address": "2N3oMXAzeU6XBBBFmWJiFDbwtVxRiUprsv6",
            "chain": 10,
            "index": 2,
            "coin": "btc",
            "wallet": "62f0418088859b0007ad2c1337e402f0",
            "coinSpecific": {
                "redeemScript": "0020a9f3c4d917a9094193fe8baaf88844ff42ea96de1a1fee92fdc9e84093794395",
                "witnessScript": "5221022c9f415e4c7491fb6f87dad25294f6e083bd9511bf50f94e031e0d387740f7c121035da85278e3d4dc17100b4fb1f591d552d64e74501a7b9927f69e9385f82946fe2103b569f313c45d577f56f38efb163d4d86d32b2281f4d605a2eb4e6102cc118fbc53ae"
            },
            "balance": {
                "balance": 0,
                "balanceString": "0",
                "totalReceived": 0,
                "totalSent": 0,
                "confirmedBalanceString": "0",
                "spendableBalanceString": "0",
                "tokens": {}
            }
        },
        {
            "id": "630fc9fe7db3fd0007157e7b0867d82b",
            "address": "tb1qkzkvluehktkcrx6y85yjlqyal558j9nk4garzghyfjtkwyw73prsvvzcwf",
            "chain": 21,
            "index": 1,
            "coin": "btc",
            "wallet": "62f0418088859b0007ad2c1337e402f0",
            "coinSpecific": {
                "witnessScript": "52210319a0ad3dda87215d90a195e074f0f053d393cc55dd43c742e2d59bca9c8f495921033ebb11af652e887e17be2b8e029b792318426e136439d0cbb0a86d3645617620210319128393716221430d05a29930e75cabaf9fae741f0c0882030fb26b2e42c2b953ae"
            },
            "balance": {
                "balance": 0,
                "balanceString": "0",
                "totalReceived": 0,
                "totalSent": 0,
                "confirmedBalanceString": "0",
                "spendableBalanceString": "0",
                "tokens": {}
            }
        }
    ],
    "count": 3
}

Repeat this step for each wallet in your reserve.

3. Aggregate Balances

Write a script that aggregates the balances for your coin or tokens. Ensure that you're adding the balances of every address in your reserve wallets.

4. Share Balances

Once you aggregate your balances, you can share your reserves, along with the public addresses. Your clients and end users can search for the public addresses on their respective block chains and confirm their balances.

If you need to confirm individuals' assets within your reserves, you can share you PoR with a third-party auditor.

See Also