確定申告に向けて、NiceHash のマイニング収益を自動計算する

## はじめに

暗号資産のマイニングをお手軽にはじめられる [NiceHash](http://nicehash.com) ですが、確定申告のための収益計算を手作業で行うのは厳しいものがあります。

2021年は手動で CSV をダウンロードしてワンライナーで乗り切りましたが、来年こそは自動化しましょう。

自動化なので、使用するプログラミング言語はもちろん Bash です。

※ 本記事は確定申告の正確性を保証するものではありません。

## NiceHash API

[NiceHash - API Docs](https://www.nicehash.com/docs/) を参考に、コードを書いていきます。

```bash
#!/usr/bin/env bash

set -Ceuo pipefail

[ -n "$NICEHASH_API_KEY" ]
[ -n "$NICEHASH_API_SECRET" ]
[ -n "$NICEHASH_ORGANIZATION_ID" ]

function nicehash::GET {
    local _path
    local _query
    _path=$1
    _query=$2

    local _time
    _time=$(date +%s)000 # ミリ秒 000 を追加

    local _nonce
    _nonce=$(uuidgen)

    local _requestId
    _requestId=$(uuidgen)

    local _hmac
    _hmac=$(
        printf "%s\x00%s\x00%s\x00\x00%s\x00\x00GET\x00%s\x00%s" \
            "$NICEHASH_API_KEY" \
            "$_time" \
            "$_nonce" \
            "$NICEHASH_ORGANIZATION_ID" \
            "$_path" \
            "$_query" \
        | openssl dgst -sha256 -hmac "$NICEHASH_API_SECRET"
    )

    curl "https://api2.nicehash.com/${_path#/}?$_query" \
        --silent \
        -H "X-Time: $_time" \
        -H "X-Nonce: $_nonce" \
        -H "X-Organization-Id: $NICEHASH_ORGANIZATION_ID" \
        -H "X-Auth: $NICEHASH_API_KEY:$_hmac" \
        -H "X-Request-Id: $_requestId"
}
```

API キーを払い出して `GET /main/api/v2/mining/rigs/payouts` API を叩いてみます。

```bash
export NICEHASH_API_KEY=xxxxxxxx
export NICEHASH_API_SECRET=yyyyyyyy
export NICEHASH_ORGANIZATION_ID=zzzzzzzz

nicehash::GET /main/api/v2/mining/rigs/payouts ''
```

🎉 無事、払い出し額を得ることができました。

```json
{
  "list": [
    {
      "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "created": 1640851928938,
      "currency": { "enumName": "BTC", "description": "BTC" },
      "amount": "0.00019920",
      "metadata": "{}",
      "accountType": { "enumName": "USER", "description": "USER" },
      "feeAmount": 4.0e-6
    }
  ]
}
```

## 日本円のレート

以上で、マイニングで得たビットコインの量を知ることができました。
しかし、確定申告には日本円のレート (BTC/JPY) が必要です。

今回は bitbank 様の API で BTC/JPY レートを取得します。

```bash
function BTCJPY:1h {
    local _date
    _date=${1//\//}

    curl -s "https://public.bitbank.cc/btc_jpy/candlestick/1hour/$_date" \
    | jq -cr '
        .data.candlestick[0].ohlcv[]
        | [
            (.[5] / 1000 | floor | todate),
            .[0]
          ]
        | @tsv
    '
}

BTCJPY:1h 2021/12/29
```

🎉 こちらは HMAC の計算等がないため簡単ですね。

```tsv
2021-12-29T00:00:00Z	5454044
2021-12-29T01:00:00Z	5478500
2021-12-29T02:00:00Z	5477113
2021-12-29T03:00:00Z	5514258
2021-12-29T04:00:00Z	5523305
2021-12-29T05:00:00Z	5500251
2021-12-29T06:00:00Z	5512511
2021-12-29T07:00:00Z	5508659
2021-12-29T08:00:00Z	5475185
2021-12-29T09:00:00Z	5496011
2021-12-29T10:00:00Z	5521219
2021-12-29T11:00:00Z	5496666
2021-12-29T12:00:00Z	5491029
2021-12-29T13:00:00Z	5394669
2021-12-29T14:00:00Z	5455248
2021-12-29T15:00:00Z	5489450
2021-12-29T16:00:00Z	5516512
2021-12-29T17:00:00Z	5487225
2021-12-29T18:00:00Z	5467948
2021-12-29T19:00:00Z	5463985
2021-12-29T20:00:00Z	5417364
2021-12-29T21:00:00Z	5447607
2021-12-29T22:00:00Z	5430001
2021-12-29T23:00:00Z	5436722
```

## 収益の計算

「NiceHash の収益」と「BTC/JPY レート」を突き合わせて、取得単価を求めます。

方法は色々あると思いますが、`日時\t値` の TSV 形式を作成して `join` で結合しようと思います。

```bash
function nicehash_payouts {
    nicehash::GET /main/api/v2/mining/rigs/payouts '' \
    | jq -r '
        def BTCStringToSAT: .[:-9] + .[-8:] | tonumber;

        .list
        | reverse[] as { $created, $amount, $feeAmount }
        | [
            ($created | . / 1000 | floor | . - . % (1*60*60) | todate),
            ($amount | BTCStringToSAT) - ($feeAmount * 100000000)
          ]
        | @tsv
    '
}

join -t $'\t' \
    <(nicehash_payouts) \
    <(BTCJPY:1h 2021/12/29)
```

🎉 良さそうです。これで安心して来年度の確定申告を迎えられます。

```tsv
# 取得日時	マイニング報酬(SAT)	BTC/JPYレート
2021-12-29T00:00:00Z	19577	5454044
2021-12-29T04:00:00Z	19344	5523305
2021-12-29T08:00:00Z	20999	5475185
2021-12-29T12:00:00Z	19588	5491029
2021-12-29T16:00:00Z	19199	5516512
2021-12-29T20:00:00Z	19088	5417364
```

## 終わりに

Bash と言いつつ、ほぼ `jq`。
途中からデータ構造が複雑になり、TypeScript で書けばよかったなぁと思いました。