Duplicate account history entries on STEEM: How to detect and fix them

in #bug4 years ago (edited)


source

I was trying to count all my STEEM/SBD balances for my tax report as I found out that the STEEM account history api is not reliable:

#!/usr/bin/python
from beem import Steem
from beem.account import Account
from beem.amount import Amount
from beem.nodelist import NodeList


if __name__ == "__main__":
    nodelist = NodeList()
    nodelist.update_nodes()
    stm = Steem(node=nodelist.get_steem_nodes())
    print(stm)
        
    account_name = "holger80"
    account = Account(account_name, steem_instance=stm)
    ops_dict = {}
    for ops in account.history():
        ops_dict[ops["index"]] = ops
    STEEM = 0
    SBD = 0
    index = 0
    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if ops["type"] == "fill_convert_request":
            amount_out = Amount(ops["amount_out"], blockchain_instance=stm)
            amount_in = Amount(ops["amount_in"], blockchain_instance=stm)
            STEEM += float(amount_out)
            SBD -= float(amount_in)
        elif ops["type"] == "fill_transfer_from_savings":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["to"] == account_name:
                if amount.symbol == "STEEM":
                    STEEM += float(amount)
                else:
                    SBD += float(amount)         
        elif ops["type"] == "transfer_to_savings":
            amount = Amount(ops["amount"], steem_instance=stm)
            if amount.symbol == "STEEM":
                STEEM -= float(amount)
            else:
                SBD -= float(amount)  
        elif ops["type"] == "transfer_to_vesting":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                STEEM -= float(amount)         
            elif ops["from"] == account_name:
                STEEM -= float(amount)
            index += 1           
        elif ops["type"] == "fill_vesting_withdraw":
            amount = Amount(ops["deposited"], steem_instance=stm)
            if ops["to_account"] == account_name:
                STEEM += float(amount)
        elif ops["type"] == "proposal_pay":
            amount = Amount(ops["payment"], steem_instance=stm)
            SBD += float(amount)
            index += 1
        elif ops["type"] == "create_proposal":
            SBD -= 10
            index += 1
        elif ops["type"] == "transfer":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                continue
            if ops["to"] == account_name:
                if amount.symbol == "STEEM":
                    STEEM += float(amount)
                else:
                    SBD += float(amount)
            else:
                if amount.symbol == "STEEM":
                    STEEM -= float(amount)
                else:
                    SBD -= float(amount)                
            index += 1   
        elif ops["type"] == "account_create_with_delegation":
            if ops["new_account_name"] == account_name:
                continue            
            fee = Amount(ops["fee"], blockchain_instance=stm)
            STEEM -= float(fee)
        elif ops["type"] == "account_create":
            if ops["new_account_name"] == account_name:
                continue
            fee = Amount(ops["fee"], blockchain_instance=stm)
            STEEM -= float(fee) 
        elif ops["type"] == "claim_reward_balance":
        
            reward_steem = Amount(ops["reward_steem"], steem_instance=stm)
            reward_vests = Amount(ops["reward_vests"], steem_instance=stm)
            reward_sbd = Amount(ops["reward_sbd"], steem_instance=stm)
            if float(reward_steem) > 0:
                STEEM += float(reward_steem)
            if float(reward_sbd) > 0:
                SBD += float(reward_sbd)

            index += 1          
        elif ops["type"] == "fill_order":
            open_pays = Amount(ops["open_pays"], steem_instance=stm)
            current_pays = Amount(ops["current_pays"], steem_instance=stm)
            open_owner = ops["open_owner"]
            current_owner = ops["current_owner"]           
            if current_owner == account_name:
                if open_pays.symbol == "STEEM":
                    STEEM += float(open_pays)
                    SBD -= float(current_pays)
                else:
                    SBD += float(open_pays)
                    STEEM -= float(current_pays)
            else:
                if current_pays.symbol == "STEEM":
                    STEEM += float(current_pays)
                    SBD -= float(open_pays)
                else:
                    SBD += float(current_pays)
                    STEEM -= float(open_pays)
         
            index += 1
           
    print("%.3f STEEM, %.3f SBD" % (STEEM, SBD))

returns

6115.776 STEEM, -3.775 SBD

which is completely wrong. First it cannot be negative and second steemd.com shows
my steem balance

After investigating, I found out that some account history elements are shown twice.

1. check: Works beem as it should?

E.g. beem returns:

print(ops_dict[150050])
print(ops_dict[150053])
{'current_owner': 'holger80', 'current_orderid': 1584865440, 'current_pays': {'amount': '3775', 'precision': 3, 'nai': '@@000000013'}, 'open_owner': 'cst90', 'open_orderid': 1584865425, 'open_pays': {'amount': '20000', 'precision': 3, 'nai': '@@000000021'}, 'trx_id': '0a3200e502bd6b1c06b81c2a2337e0436fc13704', 'block': 41868606, 'trx_in_block': 24, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-03-22T08:24:00', 'account': 'holger80', 'type': 'fill_order', '_id': '60ccd83432667fccb51946202811a6d65f68a6ea', 'index': 150050}
{'current_owner': 'holger80', 'current_orderid': 1584865440, 'current_pays': {'amount': '3775', 'precision': 3, 'nai': '@@000000013'}, 'open_owner': 'cst90', 'open_orderid': 1584865425, 'open_pays': {'amount': '20000', 'precision': 3, 'nai': '@@000000021'}, 'trx_id': '0a3200e502bd6b1c06b81c2a2337e0436fc13704', 'block': 41868606, 'trx_in_block': 24, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-03-22T08:24:00', 'account': 'holger80', 'type': 'fill_order', '_id': '60ccd83432667fccb51946202811a6d65f68a6ea', 'index': 150053}

Which is also shown on steemd.com:
doublicate entry

The error is not caused by beem.

2. check: What is stored in the trx id?

https://steemd.com/tx/0a3200e502bd6b1c06b81c2a2337e0436fc13704 retuns only one operation:

3. check: What shows the block?

https://steemd.com/b/41868606#0a3200e502bd6b1c06b81c2a2337e0436fc13704
shows that there is only one operation:
block

How to fix?

I'm using the internal _id parameter from beem for this. For every operation, a unique identifier is calculated. Whenever when two operations are identically, their _id values are identically. I use this _id to find all duplicate entries and count then all operations with the same transaction id in the block. When there are more entries than counted operations, I mark the surplus entries as duplicate.

#!/usr/bin/python
from beem import Steem
from beem.block import Block
from beem.account import Account
from beem.amount import Amount
from beem.nodelist import NodeList


if __name__ == "__main__":
    nodelist = NodeList()
    nodelist.update_nodes()
    stm = Steem(node=nodelist.get_steem_nodes())
    print(stm)
        
    account_name = "holger80"
    
    account = Account(account_name, steem_instance=stm)
    ops_dict = {}
    _ids = {}
    for ops in account.history():
        ops_dict[ops["index"]] = ops
        if ops["_id"] in _ids:
            _ids[ops["_id"]] += 1
        else:
            _ids[ops["_id"]] = 1
    duplicate_indices = []
    _id_list = []
    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if _ids[ops["_id"]] == 1:
            continue
        if ops["_id"] not in _id_list:
            _id_list.append(ops["_id"])
        else:
            trx_id = ops["trx_id"]
            if trx_id == "0000000000000000000000000000000000000000":
                duplicate_indices.append(ops["index"])
            else:
                block = Block(ops["block"], blockchain_instance=stm)
                count_ops = 0
                for t in block.transactions:
                    if t["transaction_id"] != trx_id:
                        continue
                    for o in t["operations"]:
                        count_ops += 1
                if count_ops < _ids[ops["_id"]]:
                    duplicate_indices.append(ops["index"])
    
    STEEM = 0
    SBD = 0    
    index = 0
    print("duplicate indices %d" % len(duplicate_indices))

    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if _id in duplicate_indices:
            continue

        if ops["type"] == "fill_convert_request":
            amount_out = Amount(ops["amount_out"], blockchain_instance=stm)
            amount_in = Amount(ops["amount_in"], blockchain_instance=stm)
            STEEM += float(amount_out)
            SBD -= float(amount_in)
            index += 1
        elif ops["type"] == "fill_transfer_from_savings":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["to"] == account_name:
                if amount.symbol == "STEEM":
                    STEEM += float(amount)
                else:
                    SBD += float(amount)  
                index += 1         
        elif ops["type"] == "transfer_to_savings":
            amount = Amount(ops["amount"], steem_instance=stm)
            if amount.symbol == "STEEM":
                STEEM -= float(amount)
            else:
                SBD -= float(amount)
            index += 1 
        elif ops["type"] == "transfer_to_vesting":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                STEEM -= float(amount)             
            elif ops["from"] == account_name:
                STEEM -= float(amount)
            index += 1           
        elif ops["type"] == "fill_vesting_withdraw":
            amount = Amount(ops["deposited"], steem_instance=stm)
            if ops["to_account"] == account_name:
                STEEM += float(amount)
                index += 1
        elif ops["type"] == "proposal_pay":
            amount = Amount(ops["payment"], steem_instance=stm)
            SBD += float(amount)
            index += 1
        elif ops["type"] == "create_proposal":
            SBD -= 10
            index += 1
        elif ops["type"] == "transfer":
            amount = Amount(ops["amount"], steem_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                continue
            if ops["to"] == account_name:
                if amount.symbol == "STEEM":
                    STEEM += float(amount)
                else:
                    SBD += float(amount)
            else:
                if amount.symbol == "STEEM":
                    STEEM -= float(amount)
                else:
                    SBD -= float(amount)                
            index += 1
        elif ops["type"] == "account_create_with_delegation":
            if ops["new_account_name"] == account_name:
                continue            
            fee = Amount(ops["fee"], blockchain_instance=stm)
            STEEM -= float(fee)
            index += 1  
        elif ops["type"] == "account_create":
            if ops["new_account_name"] == account_name:
                continue
            fee = Amount(ops["fee"], blockchain_instance=stm)
            STEEM -= float(fee)
            index += 1
        elif ops["type"] == "claim_reward_balance":
        
            reward_steem = Amount(ops["reward_steem"], steem_instance=stm)
            reward_vests = Amount(ops["reward_vests"], steem_instance=stm)
            reward_sbd = Amount(ops["reward_sbd"], steem_instance=stm)
            if float(reward_steem) > 0:
                STEEM += float(reward_steem)
            if float(reward_sbd) > 0:
                SBD += float(reward_sbd)

            index += 1        
        elif ops["type"] == "fill_order":
            open_pays = Amount(ops["open_pays"], steem_instance=stm)
            current_pays = Amount(ops["current_pays"], steem_instance=stm)
            open_owner = ops["open_owner"]
            current_owner = ops["current_owner"]
    
            if current_owner == account_name:
                if open_pays.symbol == "STEEM":
                    STEEM += float(open_pays)
                    SBD -= float(current_pays)
                else:
                    SBD += float(open_pays)
                    STEEM -= float(current_pays)
            else:
                if current_pays.symbol == "STEEM":
                    STEEM += float(current_pays)
                    SBD -= float(open_pays)
                else:
                    SBD += float(current_pays)
                    STEEM -= float(open_pays)
         
            index += 1
            
    print("%d entries" % index)
    print("%.3f STEEM, %.3f SBD" % (STEEM, SBD))

This time, the script returns:

duplicate indices 26
0.001 STEEM, 0.000 SBD

which is now correct. After removing 26 duplicate entries, my balance is correct.

Is there also a problem with duplicate entries on Hive?

#!/usr/bin/python
from beem import Hive
from beem.account import Account
from beem.amount import Amount
from beem.block import Block
from beem.nodelist import NodeList


if __name__ == "__main__":
    nodelist = NodeList()
    nodelist.update_nodes()
    stm = Hive(node=nodelist.get_hive_nodes())
    print(stm)
        
    account_name = "holger80"

    account = Account(account_name, blockchain_instance=stm)
    ops_dict = {}
    _ids = {}
    for ops in account.history():
        ops_dict[ops["index"]] = ops
        if ops["_id"] in _ids:
            _ids[ops["_id"]] += 1
        else:
            _ids[ops["_id"]] = 1
    duplicate_indices = []
    _id_list = []
    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if _ids[ops["_id"]] == 1:
            continue
        if ops["_id"] not in _id_list:
            _id_list.append(ops["_id"])
        else:
            trx_id = ops["trx_id"]
            if trx_id == "0000000000000000000000000000000000000000":
                duplicate_indices.append(ops["index"])
            else:
                block = Block(ops["block"], blockchain_instance=stm)
                count_ops = 0
                for t in block.transactions:
                    if t["transaction_id"] != trx_id:
                        continue
                    for o in t["operations"]:
                        count_ops += 1
                if count_ops < _ids[ops["_id"]]:
                    duplicate_indices.append(ops["index"])

    type_count = {}
    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if ops["type"] in type_count:
            type_count[ops["type"]] += 1
        else:
            type_count[ops["type"]] = 1
    
    HIVE = 0
    HBD = 0    
    index = 0

    print("duplicate indices %d" % len(duplicate_indices))

    for _id in sorted(list(ops_dict.keys())):
        ops = ops_dict[_id]
        if _id in duplicate_indices:
            continue
        
        if ops["type"] == "fill_convert_request":
            amount_out = Amount(ops["amount_out"], blockchain_instance=stm)
            amount_in = Amount(ops["amount_in"], blockchain_instance=stm)
            HIVE += float(amount_out)
            HBD -= float(amount_in)
            index += 1
        elif ops["type"] == "fill_transfer_from_savings":
            amount = Amount(ops["amount"], blockchain_instance=stm)
            if ops["to"] == account_name:
                if amount.symbol == "HIVE":
                    HIVE += float(amount)
                else:
                    HBD += float(amount)
                index += 1     
        elif ops["type"] == "transfer_to_savings":
            amount = Amount(ops["amount"], blockchain_instance=stm)
            if amount.symbol == "HIVE":
                HIVE -= float(amount)
            else:
                HBD -= float(amount)
            index += 1
        elif ops["type"] == "transfer_to_vesting":
            amount = Amount(ops["amount"], blockchain_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                HIVE -= float(amount)            
            elif ops["from"] == account_name:
                HIVE -= float(amount)
            index += 1          
        elif ops["type"] == "fill_vesting_withdraw":
            amount = Amount(ops["deposited"], blockchain_instance=stm)
            if ops["to_account"] == account_name:
                HIVE += float(amount)
            index += 1
        elif ops["type"] == "proposal_pay":
            amount = Amount(ops["payment"], blockchain_instance=stm)
            HBD += float(amount)
            index += 1
        elif ops["type"] == "create_proposal":
            HBD -= 10
            index += 1
        elif ops["type"] == "transfer":
            amount = Amount(ops["amount"], blockchain_instance=stm)
            if ops["from"] == account_name and ops["to"] == account_name:
                continue
            if ops["to"] == account_name:
                if amount.symbol == "HIVE":
                    HIVE += float(amount)
                else:
                    HBD += float(amount)
            else:
                if amount.symbol == "HIVE":
                    HIVE -= float(amount)
                else:
                    HBD -= float(amount)                
            index += 1
        elif ops["type"] == "account_create_with_delegation":
            if ops["new_account_name"] == account_name:
                continue            
            fee = Amount(ops["fee"], blockchain_instance=stm)
            HIVE -= float(fee)
            index += 1
        elif ops["type"] == "account_create":
            if ops["new_account_name"] == account_name:
                continue
            fee = Amount(ops["fee"], blockchain_instance=stm)
            HIVE -= float(fee)
            index += 1
        elif ops["type"] == "claim_reward_balance":
         
            reward_steem = Amount(ops["reward_steem"], blockchain_instance=stm)
            reward_vests = Amount(ops["reward_vests"], blockchain_instance=stm)
            reward_sbd = Amount(ops["reward_sbd"], blockchain_instance=stm)
            if float(reward_steem) > 0:
                HIVE += float(reward_steem)
            if float(reward_sbd) > 0:
                HBD += float(reward_sbd)

            index += 1
         
        elif ops["type"] == "fill_order":
            open_pays = Amount(ops["open_pays"], blockchain_instance=stm)
            current_pays = Amount(ops["current_pays"], blockchain_instance=stm)
            open_owner = ops["open_owner"]
            current_owner = ops["current_owner"]
         
            if current_owner == account_name:
                if open_pays.symbol == "HIVE":
                    HIVE += float(open_pays)
                    HBD -= float(current_pays)
                else:
                    HBD += float(open_pays)
                    HIVE -= float(current_pays)
            else:
                if current_pays.symbol == "HIVE":
                    HIVE += float(current_pays)
                    HBD -= float(open_pays)
                else:
                    HBD += float(current_pays)
                    HIVE -= float(open_pays)
         
            index += 1

    print("%d entries" % index)
    print("%.3f HIVE, %.3f HBD" % (HIVE, HBD))

returns

duplicate indices 0
6279 entries
65.316 HIVE, 0.063 HBD

which is correct according to hiveblocks:
hive balance
Balance is correct and no duplicate entries were found!

Entries that look like duplicate account history entries

First, I thought there is the same problem on Hive as I was tricked by the following two entries:

print(ops_dict[175655])
print(ops_dict[175656])
{'from': 'holger80', 'to': 'beembot', 'amount': {'amount': '1', 'precision': 3, 'nai': '@@000000021'}, 'memo': 'test', 'trx_id': '9b0c144b02d046a18f23639769a8c013bb3fb10a', 'block': 44657346, 'trx_in_block': 9, 'op_in_trx': 0, 'virtual_op': 0, 'timestamp': '2020-06-27T11:50:30', 'account': 'holger80', 'type': 'transfer', '_id': '09fb4d1710c4091f346bcb0fa4e11bfa4128f59c', 'index': 175655}
{'from': 'holger80', 'to': 'beembot', 'amount': {'amount': '1', 'precision': 3, 'nai': '@@000000021'}, 'memo': 'test', 'trx_id': '9b0c144b02d046a18f23639769a8c013bb3fb10a', 'block': 44657346, 'trx_in_block': 9, 'op_in_trx': 0, 'virtual_op': 0, 'timestamp': '2020-06-27T11:50:30', 'account': 'holger80', 'type': 'transfer', '_id': '09fb4d1710c4091f346bcb0fa4e11bfa4128f59c', 'index': 175656}

which are two tranfers in one transaction:
transfers
and not a duplicate entry.

print(ops_dict[134132])
print(ops_dict[134133])

returns two times the same custom json:

{'required_auths': [], 'required_posting_auths': ['holger80'], 'id': 'sm_submit_team', 'json': '{"trx_id":"20b319ed22c3fd0986b3c68d4743f86548db631c","team_hash":"66b00a954a974829cc4965255fbdefb6"}', 'trx_id': 'ca950109641db603ee8ebf6f0a4345180643888b', 'block': 36147842, 'trx_in_block': 23, 'op_in_trx': 0, 'virtual_op': 0, 'timestamp': '2019-09-05T05:41:39', 'account': 'holger80', 'type': 'custom_json', '_id': 'e56596adbea0dd4abe434270ba6f6633e30796d9', 'index': 134132}
{'required_auths': [], 'required_posting_auths': ['holger80'], 'id': 'sm_submit_team', 'json': '{"trx_id":"20b319ed22c3fd0986b3c68d4743f86548db631c","team_hash":"66b00a954a974829cc4965255fbdefb6"}', 'trx_id': 'ca950109641db603ee8ebf6f0a4345180643888b', 'block': 36147842, 'trx_in_block': 23, 'op_in_trx': 0, 'virtual_op': 0, 'timestamp': '2019-09-05T05:41:39', 'account': 'holger80', 'type': 'custom_json', '_id': 'e56596adbea0dd4abe434270ba6f6633e30796d9', 'index': 134133}

As there are really two identically operations
not a duplicate
(hiveblocks), this is also correct.

Conclusion

There is currently a problem on Steem that the account history API returns sometimes duplicate entries. It is possible to identify them and to remove them.

The account history API on Hive is working correctly.

You can use my scripts to check if your balance can be correctly retraced by the account history api. I will use the scripts and develop them further, so that important account operations can be stored into an excel file.

As the Hive source code is still quite similar to the Steem source code, this may also happen on Hive. In order to prevent this, I created an issue: https://gitlab.syncad.com/hive/hive/-/issues/62
so that that this topic can be explored further.


If you like what I do, consider casting a vote for me as witness on Hivesigner or on PeakD

Sort:  

Can you explain in layman terms how to use this script, and what is the result it returns?
I mean, 6279 entries, 65.316 HIVE, 0.063 HBD does not seem to be the hive you made last year :D

The script counts all ingoing and outgoing HIVE and HBD. Only when the balance is correct after checking the last history item, It can be used further.
65.316 HIVE, 0.063 HBD is my current HIVE/HBD liquid balance.
6279 entries are history items that have modified my balance.

I'm working on a second script that writes an excel file, I will post this as well.

Does this include staking rewards?

Interesting discovery, does each node server return the same replication pairs?

At first glance, the core seems to be correct since the error only appears at the API level and and does not seem to be present on the Hive API? A problem occurred since they changed some things to control the data displayed on third party's frontend?


Witness FR - Gen X - Geek 🤓 Gamer 🎮 Traveler ⛩️

I checked the results on several nodes and the results for my account were the same. I think the error can also appear on Hive. It just did not happen currently for my account.

The error is on the API level, the balances that are returned for an account are correct.

Thanks for the information, I just made the test via Postman with the function get_ops_in_block and all the transactions of the block 41868606 are duplicated in the answer

{
    "jsonrpc":"2.0", 
    "method":"account_history_api.get_ops_in_block", 
    "params":{"block_num":41868606,"only_virtual":false}, 
    "id":1
}

So after some cross-checking I went back up to block 41868590 to finally have a block where the transactions inside are not duplicated. In the other direction, I had to get to block 41868612 for it to finally stop.


Witness FR - Gen X - Geek 🤓 Gamer 🎮 Traveler ⛩️

What do you mean by duplicate?
https://hiveblocks.com/b/41868606
shows no duplicate entries.

I don't mean inside the blockchain but in response to an API call account_history_api.get_ops_in_block.

Problem in the range of 20 blocks 41868591 -> 41868611 (1 blocks/3 seconds mean 1 minute)


Witness FR - Gen X - Geek 🤓 Gamer 🎮 Traveler ⛩️

I spoke to you and roadscape about this a long time ago, it was a change in how RocksDB handles things and there can be duplicate entries and you have to check if the IDs are the same. I am surprised it does not happen on Hive as I didn't hear of a fix.

I had missing Json entries issue as well.

I run the script on your account and found 3 duplicate entries:


{'producer': 'themarkymark', 'vesting_shares': {'amount': '487047858', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 42304342, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-04-06T13:01:27', 'account': 'themarkymark', 'type': 'producer_reward', '_id': '5efd96c86758e62daab6251b4fd40e286ab6f3c2', 'index': 2411563}
{'producer': 'themarkymark', 'vesting_shares': {'amount': '487047842', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 42304354, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-04-06T13:02:03', 'account': 'themarkymark', 'type': 'producer_reward', '_id': 'fa4ff605eaec77ec4949b475fba30f5372c70d69', 'index': 2411564}
{'producer': 'themarkymark', 'vesting_shares': {'amount': '487047858', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 42304342, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-04-06T13:01:27', 'account': 'themarkymark', 'type': 'producer_reward', '_id': '5efd96c86758e62daab6251b4fd40e286ab6f3c2', 'index': 2411565}
{'producer': 'themarkymark', 'vesting_shares': {'amount': '487047842', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 42304354, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-04-06T13:02:03', 'account': 'themarkymark', 'type': 'producer_reward', '_id': 'fa4ff605eaec77ec4949b475fba30f5372c70d69', 'index': 2411566}
{'producer': 'themarkymark', 'vesting_shares': {'amount': '476907066', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 45322425, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-07-20T15:27:15', 'account': 'themarkymark', 'type': 'producer_reward', '_id': 'a4409a3b8798fef22a0b3831e0be451433976298', 'index': 2637227}
{'producer': 'themarkymark', 'vesting_shares': {'amount': '476907066', 'precision': 6, 'nai': '@@000000037'}, 'trx_id': '0000000000000000000000000000000000000000', 'block': 45322425, 'trx_in_block': 4294967295, 'op_in_trx': 0, 'virtual_op': 1, 'timestamp': '2020-07-20T15:27:15', 'account': 'themarkymark', 'type': 'producer_reward', '_id': 'a4409a3b8798fef22a0b3831e0be451433976298', 'index': 2637228}

There are not in order. As only one producer_reward is possible per block, these 6 entries are only 3 valid ones.
The duplicate entries can also check directly on the API:

curl -s --data '{"jsonrpc":"2.0", "method":"account_history_api.get_account_history", "params":{"account":"themarkymark", "start":2411566, "limit":3}, "id":1}' https://api.hive.blog

Does using or not using MIRA change anything about this problem?


Witness FR - Gen X - Geek 🤓 Gamer 🎮 Traveler ⛩️

Any chance an App can be made to calculate Hive taxes? I'd be willing to pay in Hive, HBD, or fiat for reports every year. I imagine there are others for whom this would be useful. I have not found any crypto tax service that can import Hive transactions.

We literally just launched our Beta for this exact dApp - https://HiveBit.io (@HiveBit).

https://peakd.com/hive-183630/@nulledgh0st/hivebit-io-beta-export-your-hive-transaction-history-in-seconds-and-import-sync-to-tax-and-portfolio-svcs-koinly-cointracker-and

We are currently connecting with various tax/accounting apps and companies out there to directly integrate HiveBit into their sites, so that if you join our premium service, you can API / sync you data instantly with ease.

Currently, we offer a FREE data export via CSV file (which can be imported into various services). So far, ours works perfectly with Koinly.io, and we are close to being near perfect with CoinTracker.io.

Visit our website and submit a request (we ask for your username and an email to send your CSV to) and we'll send you a CSV that you can try out for yourself.

Our final version should be launching in a few days. :) It'll be free for CSV exports, and a paid version for the API/sync version with various companies.

Also, join our community (@HiveHustlers) and Discord (https://discord.gg/yA7BYHQ) to stay up to date with everything that goes on in our ecosystem - which HiveBit is a part of.

This is great news. Thanks.

I use Taxbit.com for my crypto taxes. They are able to work with CSV files. However, it would be awesome to have automated import.

I see this is 2 years old and hivebit . io is now defunct. have you found anything else that works? also trying to sync with taxbit

@geekgirl created a tool for reporting your claimed rewards at https://hivelibrarian.herokuapp.com/

You'll have to copy paste to a spreadsheet and massage the formatting a bit.

Thank you so much!

Hi @holger80, you have received a small bonus upvote from MAXUV.
This is to inform you that you now have new MPATH tokens in your Hive-Engine wallet.
Please read this post for more information.
Thanks for being a member of both MAXUV and MPATH!

Great jobs 👌

Source
Spamming comments is frowned upon by the community. Continued comment spamming may result in the account being Blacklisted.

innovation by taxation ;)

The adjective for the adverb 'identically' is 'identical'. Use the phrase 'they are' rather than 'there are' when we are talking about things as in "...they are not in order...". Only use 'there are' when we are talking about existence as in "...there are more entries..."

Thanks for sharing interesting information. Regards.

I have picked your post for my daily hive voting initiative, Keep it up and Hive On!!

.

Loading...