]> pere.pagekite.me Git - homepage.git/blobdiff - blog/archive/2024/03/index.html
Generated.
[homepage.git] / blog / archive / 2024 / 03 / index.html
index 59960fd2c890e60dd37786c753e34ca0b3be6b73..3be995def74221795b14332a7edf3af7cf1c264b 100644 (file)
 
     <h3>Entries from March 2024.</h3>
     
 
     <h3>Entries from March 2024.</h3>
     
+    <div class="entry">
+      <div class="title">
+        <a href="https://people.skolelinux.org/pere/blog/Plain_text_accounting_file_from_your_bitcoin_transactions.html">Plain text accounting file from your bitcoin transactions</a>
+      </div>
+      <div class="date">
+         7th March 2024
+      </div>
+      <div class="body">
+        <p>A while back I wrote a small script to extract the Bitcoin
+transactions in a wallet in the
+<ahref="https://plaintextaccounting.org/">ledger plain text accounting
+format</a>.  The last few days I spent some time to get it working
+better with more special cases.  In case it can be useful for others,
+here is a copy:</p>
+
+<p><blockquote><pre>
+#!/usr/bin/python3
+#  -*- coding: utf-8 -*-
+#  Copyright (c) 2023-2024 Petter Reinholdtsen
+
+from decimal import Decimal
+import json
+import subprocess
+import time
+
+import numpy
+
+def format_float(num):
+    return numpy.format_float_positional(num, trim='-')
+
+accounts = {
+    u'amount' : 'Assets:BTC:main',
+}
+
+addresses = {
+    '<some address>' : 'Assets:bankkonto',
+    '<some address>' : 'Assets:bankkonto',
+}
+
+def exec_json(cmd):
+    proc = subprocess.Popen(cmd,stdout=subprocess.PIPE)
+    j = json.loads(proc.communicate()[0], parse_float=Decimal)
+    return j
+
+def list_txs():
+    # get all transactions for all accounts / addresses
+    c = 0
+    txs = []
+    txidfee = {}
+    limit=100000
+    cmd = ['bitcoin-cli', 'listtransactions', '*', str(limit)]
+    if True:
+        txs.extend(exec_json(cmd))
+    else:
+        # Useful for debugging
+        with open('transactions.json') as f:
+            txs.extend(json.load(f, parse_float=Decimal))
+    #print txs
+    for tx in sorted(txs, key=lambda a: a['time']):
+#        print tx['category']
+        if 'abandoned' in tx and tx['abandoned']:
+            continue
+        if 'confirmations' in tx and 0 >= tx['confirmations']:
+            continue
+        when = time.strftime('%Y-%m-%d %H:%M', time.localtime(tx['time']))
+        if 'message' in tx:
+            desc = tx['message']
+        elif 'comment' in tx:
+            desc = tx['comment']
+        elif 'label' in tx:
+            desc = tx['label']
+        else:
+            desc = 'n/a'
+        print("%s %s" % (when, desc))
+        if 'address' in tx:
+            print("  ; to bitcoin address %s" % tx['address'])
+        else:
+            print("  ; missing address in transaction, txid=%s" % tx['txid'])
+        print(f"  ; amount={tx['amount']}")
+        if 'fee'in tx:
+            print(f"  ; fee={tx['fee']}")
+        for f in accounts.keys():
+            if f in tx and Decimal(0) != tx[f]:
+                amount = tx[f]
+                print("  %-20s   %s BTC" % (accounts[f], format_float(amount)))
+        if 'fee' in tx and Decimal(0) != tx['fee']:
+            # Make sure to list fee used in several transactions only once.
+            if 'fee' in tx and tx['txid'] in txidfee \
+               and tx['fee'] == txidfee[tx['txid']]:
+                True
+            else:
+                fee = tx['fee']
+                print("  %-20s   %s BTC" % (accounts['amount'], format_float(fee)))
+                print("  %-20s   %s BTC" % ('Expences:BTC-fee', format_float(-fee)))
+                txidfee[tx['txid']] = tx['fee']
+
+        if 'address' in tx and tx['address'] in addresses:
+            print("  %s" % addresses[tx['address']])
+        else:
+            if 'generate' == tx['category']:
+                print("  Income:BTC-mining")
+            else:
+                if amount < Decimal(0):
+                    print(f"  Assets:unknown:sent:update-script-addr-{tx['address']}")
+                else:
+                    print(f"  Assets:unknown:received:update-script-addr-{tx['address']}")
+
+        print()
+        c = c + 1
+    print("# Found %d transactions" % c)
+    if limit == c:
+        print(f"# Warning: Limit {limit} reached, consider increasing limit.")
+
+def main():
+    list_txs()
+
+main()
+</pre></blockquote></p>
+
+<p>It is more of a proof of concept, and I do not expect it to handle
+all edge cases, but it worked for me, and perhaps you can find it
+useful too.</p>
+
+<p>To get a more interesting result, it is useful to map accounts sent
+to or received from to accounting accounts, using the
+<tt>addresses</tt> hash.  As these will be very context dependent, I
+leave out my list to allow each user to fill out their own list of
+accounts.  Out of the box, 'ledger reg BTC:main' should be able to
+show the amount of BTCs present in the wallet at any given time in the
+past.  For other and more valuable analysis, a account plan need to be
+set up in the <tt>addresses</tt> hash.  Here is an example
+transaction:</p>
+
+<p><blockquote><pre>
+2024-03-07 17:00 Donated to good cause
+    Assets:BTC:main                           -0.1 BTC
+    Assets:BTC:main                       -0.00001 BTC
+    Expences:BTC-fee                       0.00001 BTC
+    Expences:donations                         0.1 BTC
+</pre></blockquote></p>
+
+<p>It need a running Bitcoin Core daemon running, as it connect to it
+using <tt>bitcoin-cli listtransactions * 100000</tt> to extract the
+transactions listed in the Wallet.</p>
+
+<p>As usual, if you use Bitcoin and want to show your support of my
+activities, please send Bitcoin donations to my address
+<b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>
+
+      </div>
+      <div class="tags">
+        
+        
+        Tags: <a href="https://people.skolelinux.org/pere/blog/tags/bitcoin">bitcoin</a>, <a href="https://people.skolelinux.org/pere/blog/tags/english">english</a>.
+        
+        
+      </div>
+    </div>
+    <div class="padding"></div>
+    
     <div class="entry">
       <div class="title">
         <a href="https://people.skolelinux.org/pere/blog/RAID_status_from_LSI_Megaraid_controllers_using_free_software.html">RAID status from LSI Megaraid controllers using free software</a>
     <div class="entry">
       <div class="title">
         <a href="https://people.skolelinux.org/pere/blog/RAID_status_from_LSI_Megaraid_controllers_using_free_software.html">RAID status from LSI Megaraid controllers using free software</a>
@@ -36,7 +196,7 @@ got my hands on one of these.  I had forgotten how to handle this RAID
 controller in Debian, so I had to take a peek in the
 <a href="https://wiki.debian.org/LinuxRaidForAdmins">Debian wiki page
 "Linux and Hardware RAID: an administrator's summary"</a> to remember
 controller in Debian, so I had to take a peek in the
 <a href="https://wiki.debian.org/LinuxRaidForAdmins">Debian wiki page
 "Linux and Hardware RAID: an administrator's summary"</a> to remember
-that kind of software is available to configure and monitor the disks
+what kind of software is available to configure and monitor the disks
 and controller.  I prefer Free Software alternatives to proprietary
 tools, as the later tend to fall into disarray once the manufacturer
 loose interest, and often do not work with newer Linux Distributions.
 and controller.  I prefer Free Software alternatives to proprietary
 tools, as the later tend to fall into disarray once the manufacturer
 loose interest, and often do not work with newer Linux Distributions.
@@ -149,7 +309,7 @@ activities, please send Bitcoin donations to my address
 
 <li><a href="https://people.skolelinux.org/pere/blog/archive/2024/02/">February (1)</a></li>
 
 
 <li><a href="https://people.skolelinux.org/pere/blog/archive/2024/02/">February (1)</a></li>
 
-<li><a href="https://people.skolelinux.org/pere/blog/archive/2024/03/">March (1)</a></li>
+<li><a href="https://people.skolelinux.org/pere/blog/archive/2024/03/">March (2)</a></li>
 
 </ul></li>
 
 
 </ul></li>
 
@@ -582,7 +742,7 @@ activities, please send Bitcoin donations to my address
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/betalkontant">betalkontant (9)</a></li>
 
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/betalkontant">betalkontant (9)</a></li>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/bitcoin">bitcoin (12)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/bitcoin">bitcoin (13)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/bootsystem">bootsystem (17)</a></li>
 
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/bootsystem">bootsystem (17)</a></li>
 
@@ -604,7 +764,7 @@ activities, please send Bitcoin donations to my address
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/drivstoffpriser">drivstoffpriser (4)</a></li>
 
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/drivstoffpriser">drivstoffpriser (4)</a></li>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/english">english (457)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/english">english (458)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/fiksgatami">fiksgatami (23)</a></li>
 
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/fiksgatami">fiksgatami (23)</a></li>