LoginSignup
1
2

More than 5 years have passed since last update.

ZCash プールマイニングで得られた報酬履歴を zchain でスキャンし課税計算に使う(進捗 95%)

Last updated at Posted at 2018-01-28

漢なら ZCash プールマイニングで得られた報酬の統計処理し, 確定申告用の税計算に活用したいですね!

やりましょう!

前提条件

  • なんからのプールマイニングをしており, 自動払い出しを有効にしていて, ブロックチェーンに記録が残っているとする. (払い出し可能であるのに払い出していないプール内の残高は考慮しない)
  • 使っている zcash アドレスはひとつとする
  • マイニングで得られたコインはガチホし, 売っていないとする

各払い出しトランザクションの取得額と取得時間を得る

ZChain API を使います.

一度に取得できるトランザクション数は 20 個までになります(limit パラメータ)

したがって, 全部欲しい場合は offset を変えて GET で叩いて全体を取得することになります.

総トランザクション数(受け取り回数)は https://api.zcha.in/v2/mainnet/accounts/YOUR_ADDRESSrecvCounts でわかります.

offset を変えて取得するスクリプトを作りました. 20 個ごとに連番で JSON でファイルに保存します. python requests を pip あたりでインストールしてください.

#!/usr/bin/env python
# 
import json
import os
import sys
import datetime
import time

import requests

# Set your ZCash address.
MY_ADDR = 'XXXXXX'
max_items = 20 # zchain API limits 20 items for each API call.

def main():
    r = requests.get("https://api.zcha.in/v2/mainnet/accounts/" + MY_ADDR)
    j = r.json()
    recvCount = int(j["recvCount"])
    print(recvCount)

    n = int(recvCount / max_items) + 1
    for i in range(n):
        offset = i * max_items
        if offset >= recvCount:
            continue

        limit = max_items 

        print("requesting from {0} to {1} ...".format(offset, offset + limit))
        payload = {'limit': limit, 'offset': offset}
        rcv = requests.get("https://api.zcha.in/v2/mainnet/accounts/" + MY_ADDR + "/recv", params = payload )
        filename = "%03d.json" % i
        with open(filename, 'w') as f:
            f.write(rcv.text)

        # Wait for a while to avoid API calling limit
        time.sleep(5)

main()

JSON のレイアウトは以下のようになります.

Screen Shot 2018-01-28 at 19.38.52.png

timestamp はブロック全体のところに, 受け取り(送信先)アドレスは vout[].scriptPubKey.addresses[] に, その額は vout.value にあることがわかります.

上記を踏まえて python で集計するスクリプトを書きます.

import json
import os
import sys
import datetime

# Set your ZCash address.
MY_ADDR = 'XXXXXXXXXX'

def findReceivedAmount(b, addr):
    amount = 0

    for vout in b['vout']:
        if MY_ADDR in vout['scriptPubKey']['addresses']:
            amount += vout['value']

    return amount

def main():
    if len(sys.argv) < 3:
        print("Requires basename count")
        sys.exit(-1)

    print("timestamp, date, amount")

    i = int(sys.argv[1])
    n = int(sys.argv[2])

    while i < n:
        filename = "%03d.json" % i
        i = i + 1

        j = json.loads(open(filename).read())
        # for each block
        for b in j:
            timestamp = b['timestamp']
            # print(b['timestamp'])

            # find received amount for my account
            amount = findReceivedAmount(b, MY_ADDR)
            textualdate = datetime.datetime.fromtimestamp(timestamp)
            print("{0}, {1}, {2}".format(timestamp, textualdate, amount))  

000.json, 001.json, ... とファイルを連番で読んでいき, 以下のように取引履歴を出力します.

timestamp, date, amount
1516959786, 2018-01-26 18:43:06, 0.0102
1516889217, 2018-01-25 23:06:57, 0.0107
1516805807, 2018-01-24 23:56:47, 0.0105
1516740818, 2018-01-24 05:53:38, 0.011
1516658566, 2018-01-23 07:02:46, 0.0105
...

あとはこれで timestamp 時の ZEC/JPY 価格, もしくはなんらかの一貫した価格決め(各日の open 価格など)で取得価格を計算すれば完了です!

TODO

  • unixtime で古い日付からの順番にソートする.
  • 送金時点で時価を計算しほうがよいか, 着金時点で計算したほうがよいか.
  • ウォレットのヒストリあたりと照合して齟齬がないか検証する
  • timestamp の ZEC/JPY 価格で取得価格を計算する.
  • 手数料を考慮する?
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2