container: lib_taxes: add support for IRS Rev. Proc. 2024-28
- Creates per-wallet / per-account compliance for IRS Rev. Proc. 2024-28
* Obfuscated keymap now creates a unique indentifier per-wallet /
per-account where all trades, spends and income are now clearly
tied to their respective wallets / accounts.
- Removes support for anonymized ("universal pool") reports.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# docker-finance | modern accounting for the power-user
|
# docker-finance | modern accounting for the power-user
|
||||||
#
|
#
|
||||||
# Copyright (C) 2021-2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
# Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -1067,24 +1067,12 @@ function lib_taxes::__taxes_write()
|
|||||||
lib_taxes::__reports_obfs
|
lib_taxes::__reports_obfs
|
||||||
lib_utils::catch $?
|
lib_utils::catch $?
|
||||||
|
|
||||||
#
|
|
||||||
# Anonymized
|
|
||||||
#
|
|
||||||
|
|
||||||
lib_utils::print_custom " \e[32m├─\e[34m\e[1;3m ${_arg_tag} (anonymized)\e[0m\n"
|
|
||||||
|
|
||||||
local _ext_anon="report_anon.csv"
|
|
||||||
local _out_file="${_base_path}-${_ext_anon}"
|
|
||||||
|
|
||||||
lib_taxes::__reports_anon
|
|
||||||
lib_utils::catch $?
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Verify reports
|
# Verify reports
|
||||||
#
|
#
|
||||||
|
|
||||||
lib_utils::print_custom " \e[32m│\e[0m\n"
|
lib_utils::print_custom " \e[32m│\e[0m\n"
|
||||||
lib_utils::print_custom " \e[32m│\e[0m\t\e[37;2m ... Verifying $_arg_tag (full/obfuscated/anonymized) ...\e[0m\n"
|
lib_utils::print_custom " \e[32m│\e[0m\t\e[37;2m ... Verifying $_arg_tag (full/obfuscated) ...\e[0m\n"
|
||||||
lib_utils::print_custom " \e[32m│\e[0m\n"
|
lib_utils::print_custom " \e[32m│\e[0m\n"
|
||||||
|
|
||||||
local _full
|
local _full
|
||||||
@@ -1093,12 +1081,9 @@ function lib_taxes::__taxes_write()
|
|||||||
local _obfs
|
local _obfs
|
||||||
_obfs="$(wc -l ${_base_path}-${_ext_obfs})"
|
_obfs="$(wc -l ${_base_path}-${_ext_obfs})"
|
||||||
|
|
||||||
local _anon
|
|
||||||
_anon="$(wc -l ${_base_path}-${_ext_anon})"
|
|
||||||
|
|
||||||
# TODO: more involved verification
|
# TODO: more involved verification
|
||||||
|
|
||||||
if [[ "${_full% *}" != "${_obfs% *}" && "${_obfs% *}" != "${_anon% *}" ]]; then
|
if [[ "${_full% *}" != "${_obfs% *}" ]]; then
|
||||||
lib_utils::die_fatal "Report verification: line count mistmatch"
|
lib_utils::die_fatal "Report verification: line count mistmatch"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -1187,6 +1172,8 @@ function lib_taxes::__reports_patch()
|
|||||||
#
|
#
|
||||||
# - Coinbase Pro was sunsetted in late 2022
|
# - Coinbase Pro was sunsetted in late 2022
|
||||||
|
|
||||||
|
# TODO: for 2025+, subaccount will be included before comma
|
||||||
|
# (must add appropriate regex if patch must ever be applied to 2025+)
|
||||||
local _coinbase_string="(coinbase,|coinbase-pro,)"
|
local _coinbase_string="(coinbase,|coinbase-pro,)"
|
||||||
grep -E "$_coinbase_string" "$_spends" &>/dev/null
|
grep -E "$_coinbase_string" "$_spends" &>/dev/null
|
||||||
|
|
||||||
@@ -1282,11 +1269,25 @@ function lib_taxes::__reports_obfs_gen()
|
|||||||
local _count
|
local _count
|
||||||
_count=$(echo "$_raw_column" | wc -l)
|
_count=$(echo "$_raw_column" | wc -l)
|
||||||
|
|
||||||
|
local _sha="sha256sum"
|
||||||
|
lib_utils::deps_check "$_sha"
|
||||||
|
|
||||||
local _obfs_column
|
local _obfs_column
|
||||||
_obfs_column="$(shuf --random-source='/dev/urandom' -i 1-"${_count}" \
|
_obfs_column="$(echo "$_raw_column" \
|
||||||
| while read _line; do
|
| while read _account; do
|
||||||
[ "$_line" -lt 10 ] && _num="0${_line}" || _num="${_line}"
|
#
|
||||||
echo "$_num"
|
# OBFS column key is a truncated SHA digest of complete profile along with complete account.
|
||||||
|
#
|
||||||
|
# NOTE:
|
||||||
|
#
|
||||||
|
# - static delimiter is used to avoid potential inconsistencies
|
||||||
|
# (if ever given a custom delimiter)
|
||||||
|
#
|
||||||
|
# - complete profile is included as a means to provide a 'reasonable' salt
|
||||||
|
# (since default account names and memos can be used across profiles or subprofiles)
|
||||||
|
#
|
||||||
|
echo -n "${global_parent_profile}/${global_child_profile}/${_account}" | "$_sha" | head -c${2:-10}
|
||||||
|
echo
|
||||||
done)"
|
done)"
|
||||||
|
|
||||||
readarray -t _raw <<<"$_raw_column"
|
readarray -t _raw <<<"$_raw_column"
|
||||||
@@ -1309,18 +1310,14 @@ function lib_taxes::__reports_obfs_gen()
|
|||||||
|
|
||||||
for(i = 1; i <= count; i++)
|
for(i = 1; i <= count; i++)
|
||||||
{
|
{
|
||||||
# HACK: makes the data (most likely the Memo) sed friendly,
|
print o[i] OFS r[i]
|
||||||
# if it has delimiter in string.
|
|
||||||
sub(/:/, "_", r[i])
|
|
||||||
|
|
||||||
print tax_year "_" args_tag "-" column "_" o[i] OFS r[i]
|
|
||||||
}
|
}
|
||||||
}' FS=, OFS=, \
|
}' FS=, OFS=, \
|
||||||
| (
|
| (
|
||||||
sed -u 1q
|
sed -u 1q
|
||||||
sort
|
sort
|
||||||
) \
|
) \
|
||||||
| sed 's:, :,:g' >"$_keymap_file"
|
| sed 's|, |,|g' >"$_keymap_file"
|
||||||
|
|
||||||
# Generate a temp file of the given raw column
|
# Generate a temp file of the given raw column
|
||||||
local _tmp_file="${_tmp_dir}/${_styled_column}"
|
local _tmp_file="${_tmp_dir}/${_styled_column}"
|
||||||
@@ -1329,7 +1326,7 @@ function lib_taxes::__reports_obfs_gen()
|
|||||||
# Obfuscate given raw column with keymap data
|
# Obfuscate given raw column with keymap data
|
||||||
tail -n +2 "$_keymap_file" \
|
tail -n +2 "$_keymap_file" \
|
||||||
| while read _line; do
|
| while read _line; do
|
||||||
sed -i "s:${_line#*,}:${_line%,*}:g" "$_tmp_file"
|
sed -i "s|${_line#*,}|${_line%,*}|g" "$_tmp_file"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -1339,25 +1336,4 @@ function lib_taxes::__reports_obfs_gen()
|
|||||||
| xsv select "$_all_columns" -o "$_out_file"
|
| xsv select "$_all_columns" -o "$_out_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# Reports (anonymized)
|
|
||||||
#
|
|
||||||
|
|
||||||
function lib_taxes::__reports_anon()
|
|
||||||
{
|
|
||||||
case "$_arg_tag" in
|
|
||||||
trade | trades)
|
|
||||||
xsv select "Date,Action,Symbol,Volume,Currency,Total,FeeCurrency,Fee" \
|
|
||||||
"$_in_file" -o "$_out_file"
|
|
||||||
;;
|
|
||||||
income | spend | spends)
|
|
||||||
xsv select "Date,Action,Symbol,Volume,Currency,Total" \
|
|
||||||
"$_in_file" -o "$_out_file"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
lib_utils::die_fatal "Unsupported type"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# vim: sw=2 sts=2 si ai et
|
# vim: sw=2 sts=2 si ai et
|
||||||
|
|||||||
Reference in New Issue
Block a user