Compare commits

..

2 Commits

Author SHA1 Message Date
98674c5b3b container: lib_taxes: add support for bitcoin.tax TransferAccount column
- Is backward compatible to all rules without TransferAccount added.
  * TransferAccount value must be added via custom rules.

- Upstream appears to support TransferAccount for all years even though
  it was introduced specifically for tax years 2025+ (mileage may vary).
2026-04-03 13:57:23 -07:00
f3473beb00 container: lib_taxes: update bitcoin.tax docs/supported tags 2026-04-03 13:53:32 -07:00

View File

@@ -298,10 +298,17 @@ function lib_taxes::__parse_args()
function lib_taxes::__taxes()
{
#
# Supported tags (locally "global")
local -r _income_tags=("INCOME" "GIFTIN" "MINING" "BORROW")
local -r _spends_tags=("SPEND" "DONATION" "GIFT" "REPAY")
local -r _trades_tags=("BUY" "SELL" "SWAP" "MATCH" "REBATE" "RAW_TRADE" "PARTIAL_TRADE")
#
local -r _income_tags=("INCOME" "INTEREST" "GIFTIN" "MINING" "BORROW" "DEPOSIT")
local -r _spends_tags=("SPEND" "DONATION" "GIFT" "REPAY" "WITHDRAWAL")
local _trades_tags
_trades_tags+=("BUY" "SELL" "SWAP") # Upstream
_trades_tags+=("MATCH" "REBATE" "RAW_TRADE" "PARTIAL_TRADE") # Unique to `dfi`
declare -r _trades_tags
local _print_year="$global_arg_year"
[ -z "$_print_year" ] && _print_year="all"
@@ -355,49 +362,63 @@ function lib_taxes::__taxes_print()
for _arg in "${_arg_tag[@]}"; do
case "$_arg" in
income)
#
# Date (date and time as YYYY-MM-DD HH:mm:ss Z)
# Action (INCOME, GIFTIN, MINING or BORROW)
# Account (account or wallet name, e.g. Coinbase or Blockchain)
# Symbol (BTC, ETH, LTC, etc)
# Volume (number of coins received)
# Currency (optional, specify alternative to your default currency, such as USD, GBP or EUR)
# Action (INCOME, INTEREST, GIFTIN, MINING, BORROW or DEPOSIT)
# Account (account or wallet name, e.g. Coinbase or Ledger)
# Symbol (BTC, ETH, USDC, etc)
# Volume (amount of crypto received)
# Total (Fair price or value in Currency or your home currency, or blank for market value
# Currency (optional, specify alternative to your default currency, such as USD, GBP or EUR)
# TransferAccount (name of sending account for DEPOSIT)
# Memo (optional, name of sender or item sold)
# For example,
# Date,Action,Account,Symbol,Volume
# 2020-01-01 13:00:00 -0800,INCOME,"Blockchain Wallet",BTC,1
#
# For example:
#
# Date,Action,Account,Symbol,Volume
# 2020-01-01 13:00:00 -0800,INCOME,"Blockchain Wallet",BTC,1
#
local _tags=("${_income_tags[@]}")
local _is_income=true
;;
spend | spends)
#
# Date (date and time as YYYY-MM-DD HH:mm:ss Z)
# Action (SPEND, DONATION, GIFT or REPAY)
# Account (name of account or wallet, e.g. Coinbase or Blockchain)
# Symbol (BTC, LTC, ETH, etc)
# Volume (number of coins spent)
# Currency (optional, specify alternative to your default currency, such as USD, GBP or EUR)
# Action (SPEND, DONATION, GIFT, REPAY or WITHDRAWAL)
# Account (name of account or wallet, e.g. Coinbase or Ledger)
# Symbol (BTC, ETH, USDC, etc)
# Volume (amount of crypto spent or sent)
# Total (Fair price or cost in Currency or your home currency, or blank for market value
# Currency (optional, specify alternative to your default currency, such as USD, GBP or EUR)
# TransferAccount (name of receiving account for WITHDRAWAL)
# Memo (optional, name of recipient or item purchased)
# For example,
# Date,Action,Account,Symbol,Volume,Total,Currency
# 2020-01-01 13:00:00 -0800,SPEND,"Blockchain Wallet",BTC,1,
#
# For example:
#
# Date,Action,Account,Symbol,Volume,Total,Currency
# 2020-01-01 13:00:00 -0800,SPEND,"Blockchain Wallet",BTC,1,500,USD
#
local _tags=("${_spends_tags[@]}")
local _is_spends=true
;;
trade | trades)
#
# Date (date and time as YYYY-MM-DD HH:mm:ss Z)
# Action (BUY, SELL or SWAP)
# Account (override the exchange or wallet name, e.g. Coinbase)
# Symbol (BTC, LTC, DASH, etc)
# Volume (number of coins traded)
# Currency (specify currency such as USD, GBP, EUR or coins, BTC or LTC)
# Account (override the exchange or wallet name, e.g. Coinbase)
# Total (you can use the total Currency amount or price per coin)
# Price (price per coin in Currency or blank for lookup)
# FeeCurrency (currency of fee if different than Currency)
# Fee (any additional costs of the trade)
# For example,
# Date,Action,Account,Symbol,Volume,Price,Currency,Fee
# 2020-01-01 13:00:00 -0800,BUY,Coinbase,BTC,1500,USD,5.50
# FeeCurrency (currency of fee if different than Currency)
#
# For example:
#
# Date,Action,Account,Symbol,Volume,Price,Currency,Fee
# 2020-01-01 13:00:00 -0800,BUY,Coinbase,BTC,1,500,USD,5.50
#
local _tags=("${_trades_tags[@]}")
local _is_trades=true
;;
@@ -434,16 +455,17 @@ function lib_taxes::__taxes_print()
| xan select '"posting-comment"' \
| tail -n +2 \
| sed -e 's:"::g' -e '/^$/d' \
| gawk -v tag="$_tag" -v is_trades="$_is_trades" \
| gawk \
-v tag="$_tag" \
-v is_income="$_is_income" -v is_spends="$_is_spends" -v is_trades="$_is_trades" \
'BEGIN {
FS=OFS=","
str_one="Date" OFS "Action" OFS "Account" OFS "Symbol" OFS "Volume" OFS "Currency" OFS "Total"
str_two="FeeCurrency" OFS "Fee"
str_three="TransferAccount"
has_fee = (is_trades ? 1 : 0)
printf (has_fee ? str_one OFS str_two : str_one OFS "Memo")
printf (is_trades ? str_one OFS str_two : str_one OFS "Memo" OFS str_three)
printf "\n"
}
{
@@ -456,12 +478,14 @@ function lib_taxes::__taxes_print()
Volume = $5
Currency = $6
Total = $7
Memo = (has_fee ? "" : $8)
if (has_fee)
Memo = (is_trades ? "" : $8)
if (is_trades)
{
FeeCurrency = (has_fee && $9 != "" ? $8 : "")
FeeCurrency = ($9 != "" ? $8 : "")
Fee = (FeeCurrency && $9 != 0 ? $9 : "")
}
# NOTE: TransferAccount value added by custom-rules
TransferAccount = (is_trades ? "" : $9)
# Total is a literal 0. Get market value from bitcoin.tax
if (Total == 0) {Total=""}
@@ -544,7 +568,7 @@ function lib_taxes::__taxes_print()
# TODO: HACK: print SPEND line for non-fiat fee (see #51)
# NOTE: cost-basis *MUST* be calculated above or within preprocess
if (is_trades && has_fee && FeeCurrency != "USD" && Fee)
if (is_trades && FeeCurrency != "USD" && Fee)
{
printf Date OFS "SPEND" OFS Account OFS
printf FeeCurrency OFS Fee OFS "USD"
@@ -569,7 +593,7 @@ function lib_taxes::__taxes_print()
printf Currency OFS
printf Total OFS
if (has_fee)
if (!is_income)
{
# TODO: HACK: see #51 (and related lib_taxes work-around)
# NOTE: cost-basis *MUST* be calculated within preprocess
@@ -579,12 +603,19 @@ function lib_taxes::__taxes_print()
}
else
{
printf FeeCurrency OFS Fee
if (is_trades)
{
printf FeeCurrency OFS Fee
}
else
{
printf Memo OFS TransferAccount
}
}
}
else
{
printf Memo
printf Memo OFS TransferAccount
}
printf "\n"
@@ -1240,6 +1271,13 @@ function lib_taxes::__reports_patch()
&& sort -ru -o "$_spends" "$_spends"
fi
# Allow impl to add to header while providing backward compat for all rules (repo/custom)
local -r _files=("$_income" "$_spends" "$_trades")
local -r _csvclean=("csvclean" "--fill-short-rows")
for _file in "${_files[@]}"; do
[[ -f "$_file" && -s "$_file" ]] && echo "$("${_csvclean[@]}" "${_file}")" >"${_file}"
done
#
# Verify success of patches
#
@@ -1282,7 +1320,7 @@ function lib_taxes::__reports_obfs()
# NOTE: functions inherit local vars
case "$_arg_tag" in
income | spends)
local _all_columns="Date,Action,Account,Symbol,Volume,Currency,Total,Memo"
local _all_columns="Date,Action,Account,Symbol,Volume,Currency,Total,Memo,TransferAccount"
local _obfs_columns=("Account" "Memo")
;;
trades)