Getting transactions from wallet RPC endpoint

Hello, I’m having trouble understanding the response from the get_transactions RPC endpoint. I assumed that I’d just get all transactions and sum up the “amount” field, but that doesn’t work. What is the proper way to sum up transactions to come to the same balance as the wallet shows? Does it have to do with the “additions” and “removals” arrays? Thanks!

Here is an example response:

        {
            "additions": [
                {
                    "amount": 10000000000,
                    "parent_coin_info": "0xff6872f31c5a872...b2ddf815ed8bcc50afe1d26d8de8ae0c3",
                    "puzzle_hash": "0xffea83e29f3267....bddca39b7a8fbbbd2db8e55e22a"
                }
            ],
            "amount": 10000000000,
            "confirmed": true,
            "confirmed_at_height": 1599937,
            "created_at_time": 164999951,
            "fee_amount": 0,
            "memos": {},
            "name": "0x975a667b7f53e5e89b....9e639a18703e27517",
            "removals": [],
            "sent": 0,
            "sent_to": [],
            "spend_bundle": null,
            "to_address": "xch1ll4g8c5lxfn4mmd9hw....028mh0fdhrj4ug4qh0eda5bb898ee3763d32ffcbddca39b7a8fbbbd2db8e55e22a",
            "trade_id": null,
            "type": 0,
            "wallet_id": 1
        },
        {
            "additions": [
                {
                    "amount": 50000000000,
                    "parent_coin_info": "0xcb791c2f5b80c28fec....9ce7acb0ebe5a066f26ffdba5a8ba",
                    "puzzle_hash": "0xffea83e29f32675deda5b....ddca39b7a8fbbbd2db8e55e22a"
                }
            ],
            "amount": 50000000000,
            "confirmed": true,
            "confirmed_at_height": 1569993,
            "created_at_time": 1649999999,
            "fee_amount": 0,
            "memos": {},
            "name": "0x96602e5e06ed1624674ada31f697....25dd8fcaf215e457a4d5",
            "removals": [],
            "sent": 0,
            "sent_to": [],
            "spend_bundle": null,
            "to_address": "xch1ll4g8c5lxfn4mmd9hwyc....h0fdhrj4ug4qh0fq37",
            "to_puzzle_hash": "0xffea83e29f32675ded....39b7a8fbbbd2db8e55e22a",
            "trade_id": null,
            "type": 0,
            "wallet_id": 1
        }

Did you take care of the different wallet and transaction types?

Thank you for that, I was looking for those the other day! It still doesn’t seem to help me though. I’ve created a very specific scenario so hopefully it is clear what I’m asking.

TL;DR: I expected to be able to export transactions, sum them up and come up with a balance that matches the wallet UI. How do I do this?

I created a brand new wallet and made 3 transactions:

  1. Received 0.1234 XCH from another wallet. No fee.
  2. Sent 0.01 XCH to myself (this new wallet). Included fee of 0.000053709309.
  3. Sent 0.01 XCH back to the original sending wallet. Included fee of 0.000053709309.

The problem I’m having is that second transaction - I see the “debit” transaction but not the incoming “credit” transaction (since it is just making change). I would actually expect there to be 4 transactions total for this:

  1. Received 0.1234.
  2. Sent 0.1 to myself.
  3. Received 0.1 from myself.
  4. Sent 0.1 to another wallet.

So is my thinking wrong about using transactions for this and maybe I should be looking at “additions/removals” arrays? I tried various calculations with those too and couldn’t make it work.

I’ve noticed the wallet UI itself kind of has this same problem (note if you added these numbers up, it wouldn’t match UI balance either):

And finally here is the full JSON for these transactions:

{
    "success": true,
    "transactions": [
        {
            "additions": [
                {
                    "amount": 123400000000,
                    "parent_coin_info": "0x2c41432886...2d25d1649",
                    "puzzle_hash": "0xc1a864cc...d3dd6facc"
                }
            ],
            "amount": 123400000000,
            "confirmed": true,
            "confirmed_at_height": 1599990,
            "created_at_time": 1649999152,
            "fee_amount": 0,
            "memos": {},
            "name": "0xe077751de9f0c25741412...b320ece25",
            "removals": [],
            "sent": 0,
            "sent_to": [],
            "spend_bundle": null,
            "to_address": "xch1cx5xfnrh7pmze...wkltxqhzhzfc",
            "to_puzzle_hash": "0xc1a864cc77f0762c8d6...ec749d477d3dd6facc",
            "trade_id": null,
            "type": 0,
            "wallet_id": 1
        },
        {
            "additions": [
                {
                    "amount": 10000000000,
                    "parent_coin_info": "0x3542ab5c5e5efedb27...28ec5e91eca0",
                    "puzzle_hash": "0xc1a864cc77f0762c8d6b8a9d...77d3dd6facc"
                },
                {
                    "amount": 113346290691,
                    "parent_coin_info": "0x3542ab5c5e5efedb2...5e91eca0",
                    "puzzle_hash": "0x56de5dda6e7552d5215...08f6ea04df"
                }
            ],
            "amount": 10000000000,
            "confirmed": true,
            "confirmed_at_height": 1599995,
            "created_at_time": 1649999238,
            "fee_amount": 53709309,
            "memos": {},
            "name": "0x4a9cfd15f2e6c6e5593....7669d3ce40384b0",
            "removals": [
                {
                    "amount": 123400000000,
                    "parent_coin_info": "0x2c414328861355035489be...c219b8572d25d1649",
                    "puzzle_hash": "0xc1a864cc77f0762c8d6b8a9d...49d477d3dd6facc"
                }
            ],
            "sent": 1,
            "sent_to": [
                [
                    "5f439d406a12f5aa0eb42d...0a1f074a3bc8fe8",
                    3,
                    "DOUBLE_SPEND"
                ]
            ],
            "spend_bundle": {
                "aggregated_signature": "0xb1019cc5a0036e1bfe9f35a06ea81e...5256c",
                "coin_spends": [
                    {
                        "coin": {
                            "amount": 123400000000,
                            "parent_coin_info": "0x2c414328861355...25d1649",
                            "puzzle_hash": "0xc1a864cc77f0762c8d6b...7d3dd6facc"
                        },
                        "puzzle_reveal": "0xff02ffff01ff02ffff01ff...dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0aded237f7d2ea020f11c89050f709315edef69661a566e9156f165e62c3f500ea05461c4ae309cc6827c18b9c61aeed3ff018080",
                        "solution": "0xff80ffff01ffff...b6ec27fbc29003a2758080ff8080"
                    }
                ]
            },
            "to_address": "xch1cx5xfnrh7p...ltxqhzhzfc",
            "to_puzzle_hash": "0xc1a864cc77f0762c8d6b8...477d3dd6facc",
            "trade_id": null,
            "type": 1,
            "wallet_id": 1
        },
        {
            "additions": [
                {
                    "amount": 10000000000,
                    "parent_coin_info": "0x009ceff6f68154f2...58b14c2f187e",
                    "puzzle_hash": "0x6795cebe1e5ad7ce...fc8f2cf73c8bf"
                },
                {
                    "amount": 103292581382,
                    "parent_coin_info": "0x009ceff6f68154f2110...4c2f187e",
                    "puzzle_hash": "0x01468af43ceefc8b92...85306ca406a7"
                }
            ],
            "amount": 10000000000,
            "confirmed": true,
            "confirmed_at_height": 1599995,
            "created_at_time": 1649999620,
            "fee_amount": 53709309,
            "memos": {},
            "name": "0xa9aa12f11230bb...17d21",
            "removals": [
                {
                    "amount": 113346290691,
                    "parent_coin_info": "0x3542ab5c5e5efed...ec5e91eca0",
                    "puzzle_hash": "0x56de5dda6e7552d52...2c0b08f6ea04df"
                }
            ],
            "sent": 1,
            "sent_to": [
                [
                    "5f439d406a12f5aa0eb4...74a3bc8fe8",
                    1,
                    null
                ]
            ],
            "spend_bundle": {
                "aggregated_signature": "0x824a8566128c13e...ed7ca4a935",
                "coin_spends": [
                    {
                        "coin": {
                            "amount": 113346290691,
                            "parent_coin_info": "0x3542ab5c5e...8ec5e91eca0",
                            "puzzle_hash": "0x56de5dda6e7552d52...8f6ea04df"
                        },
                        "puzzle_reveal": "0xff02ffff01ff02ffff01ff02ffff03ff...7f4b787d805bac0ff151665d30f85a478dbc6e46e10ec19634fb6afd801ff018080",
                        "solution": "0xff80ffff01ffff33ffa06795cebe1e5...add0edeb7bb478080ff8080"
                    }
                ]
            },
            "to_address": "xch1v72ua0s7tttuu...vvhmq",
            "to_puzzle_hash": "0x6795cebe1e5ad7c...f2cf73c8bf",
            "trade_id": null,
            "type": 1,
            "wallet_id": 1
        }
    ],
    "wallet_id": 1
}
1 Like

There are couple key points about coins and transactions:

Coins are first class objects and transactions are ephemeral justifications of destroying some of them and creating others…

One major difference between Chia and other UTXO-based blockchain systems is that spend bundles are not a first-class object in the block database. Each block in chia contains a list of removals and additions, where removals are the coins spent in that block, and additions are the coins added in that block.

Your total balance are the total of the amount of unspent coins:

So to calculate it, you have to find all unspent coins on blockchain and add their amount together.

Your wallet should see only three transactions (2. sent to yourself & 3. received from your self happened in the same transaction).

Let’s try to follow your balance after each transactions:

1. Received 0.1234 XCH from another wallet. No fee.

"additions": [
    {
        "amount": 123400000000,
        "parent_coin_info": "0x2c41432886...2d25d1649",
        "puzzle_hash": "0xc1a864cc...d3dd6facc"
    }
 ],

After this txn is confirmed, your wallet sees one unspent coin with 123400000000 mojos. So that’s your total balance.

2. Sent 0.01 XCH to myself (this new wallet). Included fee of 0.000053709309.

"additions": [
    {
        "amount": 10000000000,
        "parent_coin_info": "0x3542ab5c5e5efedb27...28ec5e91eca0",
        "puzzle_hash": "0xc1a864cc77f0762c8d6b8a9d...77d3dd6facc"
    },
    {
        "amount": 113346290691,
        "parent_coin_info": "0x3542ab5c5e5efedb2...5e91eca0",
        "puzzle_hash": "0x56de5dda6e7552d5215...08f6ea04df"
    }
]
"fee_amount": 53709309,
"removals": [
    {
        "amount": 123400000000,
        "parent_coin_info": "0x2c414328861355035489be...c219b8572d25d1649",
        "puzzle_hash": "0xc1a864cc77f0762c8d6b8a9d...49d477d3dd6facc"
    }
],

The coin with 123400000000 mojos that you got from the last txn is now spent (removals).

And two new coins are created. The first coin is the 0.01 xch that you send to yourself. The second coin is the change to yourself after fees deduction. Basically, this breaks the coin with 123400000000 mojos to two new coins.

1st unspent coin + 2nd unspent coin = spent coin - fees

10000000000 + 113346290691 = 123400000000 - 53709309

So your balance now should be 10000000000 + 113346290691 = 123346290691

3. Sent 0.01 XCH back to the original sending wallet. Included fee of 0.000053709309.

"additions": [
    {
        "amount": 10000000000,
        "parent_coin_info": "0x009ceff6f68154f2...58b14c2f187e",
        "puzzle_hash": "0x6795cebe1e5ad7ce...fc8f2cf73c8bf"
    },
    {
        "amount": 103292581382,
        "parent_coin_info": "0x009ceff6f68154f2110...4c2f187e",
        "puzzle_hash": "0x01468af43ceefc8b92...85306ca406a7"
    }
],
"fee_amount": 53709309,
"removals": [
    {
        "amount": 113346290691,
        "parent_coin_info": "0x3542ab5c5e5efed...ec5e91eca0",
        "puzzle_hash": "0x56de5dda6e7552d52...2c0b08f6ea04df"
    }
],

After this txn is confirmed, one of the coin (113346290691 mojos) you got from the last txn is spent.

And two new coins are created. The first one is created for the original sending wallet (not yours). The second coin is the change to yourself as well after fees deduction.

unspent coin (for original wallet) + your new coin = spent coin - fees
10000000000 + 103292581382 = 113346290691 - 53709309

So you now have two unspent coins:

// From 2nd txn
{
        "amount": 10000000000,
        "parent_coin_info": "0x3542ab5c5e5efedb27...28ec5e91eca0",
        "puzzle_hash": "0xc1a864cc77f0762c8d6b8a9d...77d3dd6facc"
 },
// From 3rd txn
{
        "amount": 103292581382,
        "parent_coin_info": "0x009ceff6f68154f2110...4c2f187e",
        "puzzle_hash": "0x01468af43ceefc8b92...85306ca406a7"
}

And your final balance should be 10000000000 + 103292581382 = 113292581382

Let’s summarize:

coin received from original wallet - (fees * 2) - coin sent to original wallet = final balance
123400000000 - ((53709309 * 2) + 10000000000) = 113292581382

Hope this helps!

3 Likes

Wow thank you so much for the details! This all makes a lot more sense now - I’m on another project at the moment but I will come back to this and see if I can make it work soon. I’ll follow up then, thanks again!

1 Like

Thank you! This was a great question and follow up! I had the exact same question but instead of focusing on the wallet balance, I am focus on creating a one-line “transaction” summary from the standpoint of documentation for taxes.

Though there is a lot of detail here, I’m not sure I fully understand the correct approach to boil down the JSON returned in the get_transactions RPC endpoint. Currently, for all transaction types other than OUTGOING_TX, I simply use the amount field itself. But for OUTGOING_TX, I have been totaling the removal amounts and using as the ‘net amount’ of that transaction. I do this because it seems like the ‘change’ back from spending a coin with a higher value, comes back to you in a separate transaction.

My wallet only has one OUTGOING_TX transaction when I created my PlotNFT. But I can tell there were really two transactions (at least that are stored in my wallet db) at that exact moment.


 {
      "additions": [
        {
          "amount": 1749999999999,
          "parent_coin_info": "0x70131393896f1b68...c69e92a5a789c65",
          "puzzle_hash": "0x25ba42b53eac370...47d29e235a25b2c4f7228d"
        }
      ],
      "amount": 1749999999999,
      "confirmed": true,
      "confirmed_at_height": 542916,
      "created_at_time": 1625752171,
      "fee_amount": 0,
      "memos": {},
      "name": "0x22b67775da...ccd64a40c76c7f8fa22219",
      "removals": [],
      "sent": 0,
      "sent_to": [],
      "spend_bundle": null,
      "to_address": "xch1ykay9df7...a983rtgjm938hy2xs6lgat4",
      "to_puzzle_hash": "0x25ba42b53ea...7d29e235a25b2c4f7228d",
      "trade_id": null,
      "type": 0,
      "wallet_id": 1
    },
 {
      "additions": [
        {
          "amount": 1749999999999,
          "parent_coin_info": "0x70131393896f1b6...fe89c69e92a5a789c65",
          "puzzle_hash": "0x25ba42b53...29e235a25b2c4f7228d"
        },
        {
          "amount": 1,
          "parent_coin_info": "0x70131393896f1...fe89c69e92a5a789c65",
          "puzzle_hash": "0xeff0752249506...4d1a64ea4cdc13da9"
        }
      ],
      "amount": 1,
      "confirmed": true,
      "confirmed_at_height": 542916,
      "created_at_time": 1625752171,
      "fee_amount": 0,
      "memos": {},
      "name": "0x5c3b34a20878a2...abf2a091c4df1ac8fbf",
      "removals": [
        {
          "amount": 1750000000000,
          "parent_coin_info": "0xccd5bb7118353...0000000000000046764",
          "puzzle_hash": "0x414b238fa40bc5...2df68f98b4b23e17d89"
        }
      ],
      "sent": 0,
      "sent_to": [],
      "spend_bundle": null,
      "to_address": "xch1alc82gjf2ps...5e82fnwp8k5s6vrrej",
      "to_puzzle_hash": "0xeff07522495060...a64ea4cdc13da9",
      "trade_id": null,
      "type": 1,
      "wallet_id": 1
    },

I made a Bash script to try to build a CSV file for transactions, and I’m just worried that my logic is wrong. Here is the output for my OUTGOING_TX and the INCOMING_TX that hit at the exact same time.

"0x22b67775da4d8dcbc...cd64a40c76c7f8fa22219",1625752171,"2021-07-08 08:49:31","INCOMING_TX",1.749999999999,0
"0x5c3b34a2...ec848dcabf2a091c4df1ac8fbf",1625752171,"2021-07-08 08:49:31",OUTGOING_TX,1.750000000000,0

So I guess my question is, am I really using the correct logic here? Could there be times when to really get the ‘net’ amount for tax documentation, I would need to get wallet db transactions from multiple wallet ids? For instance, if someone spent a coin to purchase a CAT?

XCH Transaction Exporter : getxchtx