forked from EvergreenCrypto/docker-finance
Compare commits
21 Commits
v1.4.0
...
coinbase-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
a5d3486693
|
|||
|
f718f8e3f4
|
|||
|
78f24a2659
|
|||
|
d708135ca1
|
|||
|
6692aa6db0
|
|||
|
50245cf033
|
|||
|
8bc196eff6
|
|||
|
65aa5ef9d0
|
|||
|
1ea16ab580
|
|||
|
fb4566e320
|
|||
|
beae62c884
|
|||
|
22338eb5ac
|
|||
|
72ee9b9607
|
|||
|
76505b6a5e
|
|||
|
c6703ad706
|
|||
|
4417122fee
|
|||
|
6bd16952a6
|
|||
|
35d239588d
|
|||
|
745984766d
|
|||
|
38b2633e6c
|
|||
|
e3598fce8c
|
17
CHANGELOG.md
17
CHANGELOG.md
@@ -18,9 +18,24 @@
|
||||
|
||||
# Changelog (`docker-finance`)
|
||||
|
||||
## 1.4.1 - 2026-03-18
|
||||
|
||||
This patch release fixes broken `import` for Trezor Suite v25.9.1+ by adding new FS support and backward compatibility.
|
||||
|
||||
### 1.4.1 - Fixes
|
||||
|
||||
- Add bash quotes when testing column(s) of given header and add custom delim support (lib_preprocess) ([#326](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/326))
|
||||
|
||||
- Add Trezor Suite v25.9.1+ FS support and backward compatibility ([#327](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/327))
|
||||
* For devs (to generate new FS mockup), with `finance` image, run: `gen type=flow account=trezor dev=on confirm=no profile=<profile/subprofile>`
|
||||
|
||||
### 1.4.1 - Contributors
|
||||
|
||||
- Aaron Fiore
|
||||
|
||||
## 1.4.0 - 2026-03-16
|
||||
|
||||
This release brings a minor `dfi` fix (`fetch`), a new `dfi` feature (custom compose merge file functionality), `dfi` enhancements (base image and end-user), and patch releases for `hledger-flow` and a ROOT.cern (`root`).
|
||||
This release brings a minor `dfi` fix (`fetch`), a new `dfi` feature (custom compose merge file functionality), `dfi` enhancements (base image and end-user), and patch releases for `hledger-flow` and ROOT.cern (`root`).
|
||||
|
||||
### 1.4.0 - Fixes
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ RUN pacman -Syu \
|
||||
|
||||
# Base packages
|
||||
RUN pacman -Syu \
|
||||
bash-completion \
|
||||
bc \
|
||||
csvkit \
|
||||
vim \
|
||||
|
||||
@@ -58,7 +58,7 @@ RUN cabal v1-copy
|
||||
FROM hledger-iadd AS hledger
|
||||
|
||||
WORKDIR /usr/local/src
|
||||
RUN git clone --depth=1 https://github.com/simonmichael/hledger -b 1.51.2
|
||||
RUN git clone --depth=1 https://github.com/simonmichael/hledger -b 1.52
|
||||
|
||||
WORKDIR /usr/local/src/hledger
|
||||
RUN stack setup
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#
|
||||
|
||||
# Release version (tag format)
|
||||
version: "v1.4.0"
|
||||
version: "v1.4.1"
|
||||
|
||||
# Container dependencies (used by `version` command)
|
||||
# NOTE: this must stay inline with Dockerfiles
|
||||
@@ -36,6 +36,7 @@ container:
|
||||
commands:
|
||||
base:
|
||||
packages:
|
||||
- "bash-completion"
|
||||
- "bc"
|
||||
- "csvkit"
|
||||
- "vim"
|
||||
|
||||
@@ -17,6 +17,28 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# - Refactor using `bash-completion` "library" but keep backward compatibility,
|
||||
# as this would otherwise break the "no more than 3 dependencies" approach to client-side `dfi`.
|
||||
#
|
||||
# - When possible, add completion to existing `dfi` arguments that aren't completing
|
||||
# * e.g., `dfi archlinux/${USER}:default edit type=` -> `dfi archlinux/${USER}:default edit type=rules...`
|
||||
#
|
||||
# The not-so-straightforward resolution to this TODO hinges on the fact that
|
||||
# the default delim for all `dfi` completion is the `=` character (which also exists in `COMP_WORDBREAKS`).
|
||||
#
|
||||
# One resolution can be found in:
|
||||
#
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/completions-core/dd.bash
|
||||
#
|
||||
# See also:
|
||||
#
|
||||
# - https://github.com/scop/bash-completion/tree/main/completions-core
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L1105-L1132
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L1450-L1454
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L2964-L2968
|
||||
|
||||
# WARNING: because of completion, the docker-finance environment file
|
||||
# is never read. Ergo, for debugging, you'll need to run the following
|
||||
# with log-level 1 or 2:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# docker-finance | modern accounting for the power-user
|
||||
#
|
||||
# Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
# Copyright (C) 2024-2026 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
#
|
||||
# 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
|
||||
@@ -17,6 +17,28 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# - Refactor using `bash-completion` "library".
|
||||
# * i.e., remove direct access to COMP* and use what's available, etc.
|
||||
#
|
||||
# - Add completion to existing `dfi` arguments that aren't completing.
|
||||
# * e.g., `dfi profile/subprofile edit type=` -> `dfi profile/subprofile edit type=rules...`
|
||||
#
|
||||
# The not-so-straightforward resolution to this TODO hinges on the fact that
|
||||
# the default delim for all `dfi` completion is the `=` character (which also exists in `COMP_WORDBREAKS`).
|
||||
#
|
||||
# One resolution can be found in:
|
||||
#
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/completions-core/dd.bash
|
||||
#
|
||||
# See also:
|
||||
#
|
||||
# - https://github.com/scop/bash-completion/tree/main/completions-core
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L1105-L1132
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L1450-L1454
|
||||
# - https://github.com/scop/bash-completion/blob/c63826f8678e7d1fd36cf188bf1ba2eccaf2552e/bash_completion#L2964-L2968
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
[ "$DOCKER_FINANCE_DEBUG" == 2 ] && set -xv
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# docker-finance | modern accounting for the power-user
|
||||
#
|
||||
# Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
# Copyright (C) 2021-2026 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
#
|
||||
# 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
|
||||
@@ -131,6 +131,7 @@ if %to_address (^0x39aa39c021dfbae8fac545936693ac917d5e7563$|^0x4ddc2d193948926d
|
||||
if %direction ^IN$
|
||||
& %contract_address ^0xc00e94cb662c3520282e6f5717214004a7f26888$
|
||||
& %from_address ^0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b$
|
||||
comment blockchain:%blockchain, type:%type, block:%block_number, blockid:%block_hash, index:%tx_index, subaccount_address:%subaccount_address, contract_address:%contract_address, from_address:%from_address, to_address:%to_address, txid:%tx_hash, direction:%direction, taxed_as:INCOME
|
||||
account2 income:%account_name:%subaccount_name:%blockchain:%symbol
|
||||
comment2 %date +0000,INCOME,%account_name:%subaccount_name:%blockchain,%symbol,%amount_,USD,,COMP rewards
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -82,10 +82,12 @@ function __parse()
|
||||
sub(/^-/, "", $5)
|
||||
sub(/^-/, "", $7)
|
||||
|
||||
# Cleanup timestamp
|
||||
sub(/T/, " ", $9);
|
||||
sub(/Z/, "", $9);
|
||||
sub(/\+.*/, "", $9);
|
||||
# Prepare info_created_at (NOTE: server returns UTC)
|
||||
created_at=$9
|
||||
sub(/T/, " ", created_at);
|
||||
sub(/Z/, "", created_at);
|
||||
sub(/\+.*/, "", created_at);
|
||||
created_at=created_at " +0000"
|
||||
|
||||
# Print [info] object for rules consumption
|
||||
printf $1 OFS # account_id (prepended column)
|
||||
@@ -96,7 +98,7 @@ function __parse()
|
||||
printf "\"" $6 "\"" OFS # info_amount_currency
|
||||
printf $7 OFS # info_native_amount_amount
|
||||
printf "\"" $8 "\"" OFS # info_native_amount_currency
|
||||
printf $9 OFS # info_created_at
|
||||
printf created_at OFS # info_created_at
|
||||
printf $10 OFS # info_resource
|
||||
printf $11 OFS # info_resource_path
|
||||
printf $12 OFS # info_description
|
||||
@@ -210,6 +212,25 @@ function __parse()
|
||||
cost_basis=(direction ~ /^IN$/ ? real_value_amount + $50 : real_value_amount)
|
||||
printf("%.8f", cost_basis); printf OFS # advanced_trade_fill_cost_basis_amount
|
||||
|
||||
#
|
||||
# 1099-DA (2025+): Since Coinbase uses Eastern Time for tax reporting, and
|
||||
# %created_at returns UTC, %taxed_at (and form 8949) must align with 1099-DA.
|
||||
#
|
||||
|
||||
# Only convert for years 2025+
|
||||
cmd = "TZ=\"US/Eastern\" date \"+%F %T %z\" --date="$9 | getline date
|
||||
split(date, year, "-");
|
||||
if (year[1] <= 2024)
|
||||
{
|
||||
cmd = "TZ=\"UTC\" date \"+%F %T %z\" --date="$9 | getline date
|
||||
}
|
||||
taxed_at = date
|
||||
printf taxed_at OFS
|
||||
|
||||
#
|
||||
# Remaining defaults
|
||||
#
|
||||
|
||||
printf direction OFS
|
||||
printf global_subaccount
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# docker-finance | modern accounting for the power-user
|
||||
#
|
||||
# Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
# Copyright (C) 2021-2026 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
#
|
||||
# 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
|
||||
@@ -15,7 +15,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
fields account_id,coinbase_id,type,status_,amount_amount,amount_currency,native_amount_amount,native_amount_currency,created_at,resource,resource_path,description,network_status,network_network_name,network_hash,network_transaction_fee_amount,network_transaction_fee_currency,to_resource,to_address,to_email,from_resource,from_resource_path,from_id,from_name,cancelable,idem,buy_total_amount,buy_total_currency,buy_subtotal_amount,buy_subtotal_currency,buy_fee_amount,buy_fee_currency,buy_id,buy_payment_method_name,sell_total_amount,sell_total_currency,sell_subtotal_amount,sell_subtotal_currency,sell_fee_amount,sell_fee_currency,sell_id,sell_payment_method_name,trade_fee_amount,trade_fee_currency,trade_id,trade_payment_method_name,advanced_trade_fill_fill_price,advanced_trade_fill_product_id,advanced_trade_fill_order_id,advanced_trade_fill_commission,advanced_trade_fill_order_side,native_amount_price,native_network_transaction_fee_amount,network_transaction_amount_amount,advanced_trade_fill_real_value_amount,advanced_trade_fill_pair_lhs,advanced_trade_fill_pair_rhs,advanced_trade_fill_cost_basis_amount,direction,subaccount
|
||||
fields account_id,coinbase_id,type,status_,amount_amount,amount_currency,native_amount_amount,native_amount_currency,created_at,resource,resource_path,description,network_status,network_network_name,network_hash,network_transaction_fee_amount,network_transaction_fee_currency,to_resource,to_address,to_email,from_resource,from_resource_path,from_id,from_name,cancelable,idem,buy_total_amount,buy_total_currency,buy_subtotal_amount,buy_subtotal_currency,buy_fee_amount,buy_fee_currency,buy_id,buy_payment_method_name,sell_total_amount,sell_total_currency,sell_subtotal_amount,sell_subtotal_currency,sell_fee_amount,sell_fee_currency,sell_id,sell_payment_method_name,trade_fee_amount,trade_fee_currency,trade_id,trade_payment_method_name,advanced_trade_fill_fill_price,advanced_trade_fill_product_id,advanced_trade_fill_order_id,advanced_trade_fill_commission,advanced_trade_fill_order_side,native_amount_price,native_network_transaction_fee_amount,network_transaction_amount_amount,advanced_trade_fill_real_value_amount,advanced_trade_fill_pair_lhs,advanced_trade_fill_pair_rhs,advanced_trade_fill_cost_basis_amount,taxed_at,direction,subaccount
|
||||
|
||||
# The above fields; in order and in human-readable form:
|
||||
#
|
||||
@@ -77,17 +77,24 @@ fields account_id,coinbase_id,type,status_,amount_amount,amount_currency,native_
|
||||
# advanced_trade_fill_pair_lhs
|
||||
# advanced_trade_fill_pair_rhs
|
||||
# advanced_trade_fill_cost_basis_amount
|
||||
# taxed_at
|
||||
# direction
|
||||
# subaccount
|
||||
|
||||
date %created_at
|
||||
date-format %Y-%m-%d %H:%M:%S
|
||||
date-format %Y-%m-%d %H:%M:%S %z
|
||||
|
||||
account1 assets:coinbase:%subaccount:%amount_currency
|
||||
amount %amount_amount "%amount_currency"
|
||||
|
||||
# NOTE: server time is UTC, as are the timestamps.
|
||||
description %created_at +0000
|
||||
# NOTE:
|
||||
#
|
||||
# - Server time is UTC, as are the timestamps. However, their generated 1099-DA is ET (Eastern Time).
|
||||
#
|
||||
# - For disposal-related taxable events, use %taxed_at timestamp in tx comment for `taxes`.
|
||||
# * For years 2025+, the %taxed_at time (ET) will be converted from %created_at (UTC).
|
||||
#
|
||||
description %created_at
|
||||
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id
|
||||
|
||||
@@ -164,7 +171,7 @@ if %type ^send$
|
||||
account4 expenses:coinbase:%subaccount:fees:send:%native_amount_currency
|
||||
amount4 %native_network_transaction_fee_amount %native_amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, idem:%idem, network_status:%network_status, network_name:%network_network_name, to_address:%to_address, txid:%network_hash, direction:%direction, taxed_as:SPEND
|
||||
comment3 %created_at +0000,SPEND,coinbase:%subaccount,%network_transaction_fee_currency,%network_transaction_fee_amount,%native_amount_currency,%native_network_transaction_fee_amount,FEE
|
||||
comment3 %taxed_at,SPEND,coinbase:%subaccount,%network_transaction_fee_currency,%network_transaction_fee_amount,%native_amount_currency,%native_network_transaction_fee_amount,FEE
|
||||
# Marked as comment3 in case user-defined rules use comment2 to SPEND/GIFT the non-fee amount
|
||||
|
||||
#
|
||||
@@ -183,14 +190,14 @@ if %type ^send$
|
||||
& %to_resource ^email$
|
||||
account2 expenses:coinbase:%subaccount:send_email:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, idem:%idem, network_status:%network_status, to_resource:%to_resource, direction:%direction, taxed_as:SPEND
|
||||
comment2 %created_at +0000,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Send via email
|
||||
comment2 %taxed_at,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Send via email
|
||||
|
||||
if %type ^send$
|
||||
& %direction ^OUT$
|
||||
& %to_resource ^email$
|
||||
& %to_email [a-z]
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, idem:%idem, network_status:%network_status, to_resource:%to_resource, to_email:%to_email, direction:%direction, taxed_as:SPEND
|
||||
comment2 %created_at +0000,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Send to %to_email
|
||||
comment2 %taxed_at,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Send to %to_email
|
||||
|
||||
# TODO: phone number support
|
||||
|
||||
@@ -276,7 +283,7 @@ if %type ^send$
|
||||
amount %amount_amount "%amount_currency" @@ %native_amount_amount %native_amount_currency
|
||||
account2 income:coinbase:%subaccount:card:%native_amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:REBATE
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
|
||||
# Crypto Spend
|
||||
|
||||
@@ -284,7 +291,7 @@ if %type ^cardspend$
|
||||
amount -%amount_amount "%amount_currency" @@ %native_amount_amount %native_amount_currency
|
||||
account2 expenses:coinbase:%subaccount:card:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:SPEND
|
||||
comment2 %created_at +0000,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Coinbase Card
|
||||
comment2 %taxed_at,SPEND,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,Coinbase Card
|
||||
|
||||
# Cash Spend (Native Fiat Wallet)
|
||||
# TODO: any reference to USD should be a backreferenced %native_amount_currency
|
||||
@@ -307,32 +314,32 @@ if %type ^send$
|
||||
& %from_name ^Coinbase Earn$
|
||||
account2 income:coinbase:%subaccount:earn:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:INCOME
|
||||
comment2 %created_at +0000,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
comment2 %taxed_at,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
|
||||
if %type ^earn_payout$
|
||||
account2 income:coinbase:%subaccount:earn:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:INCOME
|
||||
comment2 %created_at +0000,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
comment2 %taxed_at,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
|
||||
if %type ^tx$
|
||||
& %description ^Earn Task$
|
||||
account2 income:coinbase:%subaccount:earn:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:INCOME
|
||||
comment2 %created_at +0000,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
comment2 %taxed_at,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,REWARD
|
||||
|
||||
# Interest
|
||||
|
||||
if %type ^interest$
|
||||
account2 income:coinbase:%subaccount:interest:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:INCOME
|
||||
comment2 %created_at +0000,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,INTEREST
|
||||
comment2 %taxed_at,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,INTEREST
|
||||
|
||||
# Staking
|
||||
|
||||
if %type (^inflation_reward$|^staking_reward$)
|
||||
account2 income:coinbase:%subaccount:staking:%amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:INCOME
|
||||
comment2 %created_at +0000,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,STAKING
|
||||
comment2 %taxed_at,INCOME,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,STAKING
|
||||
|
||||
################################################################################
|
||||
# #
|
||||
@@ -358,23 +365,23 @@ if %type ^buy$
|
||||
amount %amount_amount "%amount_currency" @@ %buy_total_amount "%buy_total_currency"
|
||||
account2 assets:coinbase:%subaccount:%buy_total_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, buy_id:%buy_id, taxed_as:BUY
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,,
|
||||
|
||||
if %type ^buy$
|
||||
& %buy_fee_amount [1-9]
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,%buy_fee_currency,%buy_fee_amount
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,%buy_fee_currency,%buy_fee_amount
|
||||
# TODO: HACK: re: #51, FeeCurrency and Fee are added even though cost-basis is calculated (for non-fiat fee disposal, see lib_taxes)
|
||||
|
||||
# TODO: HACK: see #51 and respective lib_taxes work-around
|
||||
if %type ^buy$
|
||||
& %buy_fee_amount [1-9]
|
||||
& %buy_fee_currency ^USD$
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%buy_total_currency,%buy_total_amount,,
|
||||
|
||||
if %type ^buy$
|
||||
& %buy_total_currency ^USDC$
|
||||
amount %amount_amount "%amount_currency" @@ %native_amount_amount %native_amount_currency
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
|
||||
if %type ^buy$
|
||||
& %buy_fee_amount [1-9]
|
||||
@@ -413,23 +420,23 @@ if %type ^sell$
|
||||
amount -%amount_amount "%amount_currency" @@ %sell_total_amount "%sell_total_currency"
|
||||
account2 assets:coinbase:%subaccount:%sell_total_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, sell_id:%sell_id, taxed_as:SELL
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,,
|
||||
|
||||
if %type ^sell$
|
||||
& %sell_fee_amount [1-9]
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,%sell_fee_currency,%sell_fee_amount
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,%sell_fee_currency,%sell_fee_amount
|
||||
# TODO: HACK: re: #51, FeeCurrency and Fee are added even though cost-basis is calculated (for non-fiat fee disposal, see lib_taxes)
|
||||
|
||||
# TODO: HACK: see #51 and respective lib_taxes work-around
|
||||
if %type ^sell$
|
||||
& %sell_fee_amount [1-9]
|
||||
& %sell_fee_currency ^USD$
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%sell_total_currency,%sell_total_amount,,
|
||||
|
||||
if %type ^sell$
|
||||
& %sell_total_currency ^USDC$
|
||||
amount -%amount_amount %amount_currency @@ %native_amount_amount %native_amount_currency
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
|
||||
if %type ^sell$
|
||||
& %sell_fee_amount [1-9]
|
||||
@@ -633,7 +640,7 @@ if %type ^trade$
|
||||
amount -%amount_amount "%amount_currency" @@ %native_amount_amount %native_amount_currency
|
||||
account2 equity:coinbase:%subaccount:conversion:%native_amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:SELL
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
|
||||
if %type ^trade$
|
||||
& %direction ^OUT$
|
||||
@@ -649,7 +656,7 @@ if %type ^trade$
|
||||
amount %amount_amount "%amount_currency" @@ %native_amount_amount %native_amount_currency
|
||||
account2 equity:coinbase:%subaccount:conversion:%native_amount_currency
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, taxed_as:BUY
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%amount_currency,%amount_amount,%native_amount_currency,%native_amount_amount,,
|
||||
|
||||
if %type ^trade$
|
||||
& %direction ^IN$
|
||||
@@ -707,14 +714,14 @@ if %type ^advanced_trade_fill$
|
||||
& %direction ^IN$
|
||||
amount %amount_amount "%advanced_trade_fill_pair_lhs" @@ %advanced_trade_fill_real_value_amount "%advanced_trade_fill_pair_rhs"
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, advanced_trade_fill_fill_price:%advanced_trade_fill_fill_price, advanced_trade_fill_product_id:%advanced_trade_fill_product_id, advanced_trade_fill_order_id:%advanced_trade_fill_order_id, advanced_trade_fill_order_side:%advanced_trade_fill_order_side, advanced_trade_fill_pair_lhs:%advanced_trade_fill_pair_lhs, advanced_trade_fill_pair_rhs:%advanced_trade_fill_pair_rhs, direction:%direction, taxed_as:BUY
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
|
||||
if %type ^advanced_trade_fill$
|
||||
& %advanced_trade_fill_order_side ^buy$
|
||||
& %advanced_trade_fill_real_value_amount [1-9]
|
||||
& %advanced_trade_fill_commission [1-9]
|
||||
& %direction ^IN$
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_commission
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_commission
|
||||
# TODO: HACK: re: #51, FeeCurrency and Fee are added even though cost-basis is calculated (for non-fiat fee disposal, see lib_taxes)
|
||||
|
||||
# TODO: HACK: see #51 and respective lib_taxes work-around
|
||||
@@ -724,7 +731,7 @@ if %type ^advanced_trade_fill$
|
||||
& %advanced_trade_fill_commission [1-9]
|
||||
& %advanced_trade_fill_pair_rhs ^USD$
|
||||
& %direction ^IN$
|
||||
comment2 %created_at +0000,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
comment2 %taxed_at,BUY,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
|
||||
#
|
||||
# SELL
|
||||
@@ -743,14 +750,14 @@ if %type ^advanced_trade_fill$
|
||||
& %direction ^OUT$
|
||||
amount -%amount_amount "%advanced_trade_fill_pair_lhs" @@ %advanced_trade_fill_real_value_amount "%advanced_trade_fill_pair_rhs"
|
||||
comment type:%type, status:%status_, account_id:%account_id, coinbase_id:%coinbase_id, advanced_trade_fill_fill_price:%advanced_trade_fill_fill_price, advanced_trade_fill_product_id:%advanced_trade_fill_product_id, advanced_trade_fill_order_id:%advanced_trade_fill_order_id, advanced_trade_fill_order_side:%advanced_trade_fill_order_side, advanced_trade_fill_pair_lhs:%advanced_trade_fill_pair_lhs, advanced_trade_fill_pair_rhs:%advanced_trade_fill_pair_rhs, direction:%direction, taxed_as:SELL
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
|
||||
if %type ^advanced_trade_fill$
|
||||
& %advanced_trade_fill_order_side ^sell$
|
||||
& %advanced_trade_fill_real_value_amount [1-9]
|
||||
& %advanced_trade_fill_commission [1-9]
|
||||
& %direction ^OUT$
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_commission
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_commission
|
||||
# TODO: HACK: re: #51, FeeCurrency and Fee are added even though cost-basis is calculated (for non-fiat fee disposal, see lib_taxes)
|
||||
|
||||
# TODO: HACK: see #51 and respective lib_taxes work-around
|
||||
@@ -760,6 +767,6 @@ if %type ^advanced_trade_fill$
|
||||
& %advanced_trade_fill_commission [1-9]
|
||||
& %advanced_trade_fill_pair_rhs ^USD$
|
||||
& %direction ^OUT$
|
||||
comment2 %created_at +0000,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
comment2 %taxed_at,SELL,coinbase:%subaccount,%advanced_trade_fill_pair_lhs,%amount_amount,%advanced_trade_fill_pair_rhs,%advanced_trade_fill_cost_basis_amount,,
|
||||
|
||||
# vim: sw=2 sts=2 si ai et
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Timestamp,Date,Time,Type,Transaction ID,Fee,Fee unit,Address,Label,Amount,Amount unit,Fiat (USD),Other
|
||||
1773852733,3/18/2026,9:52:13 AM GMT-7,SENT,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX123,0.00001234,BTC,bc1qXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX123,New FS tx,0.00012345,BTC,"8.81",
|
||||
|
@@ -36,16 +36,35 @@ source "${DOCKER_FINANCE_CONTAINER_REPO}/src/hledger-flow/lib/lib_preprocess.bas
|
||||
|
||||
[ -z "$global_in_filename" ] && exit 1
|
||||
|
||||
function reseat_fs()
|
||||
{
|
||||
[ -z $1 ] && exit 1
|
||||
local -r _fs="$1"
|
||||
local -r _header="Timestamp${_fs}Date${_fs}Time${_fs}Type${_fs}Transaction ID${_fs}Fee${_fs}Fee unit${_fs}Address${_fs}Label${_fs}Amount${_fs}Amount unit${_fs}Fiat (USD)${_fs}Other"
|
||||
echo "$_header"
|
||||
}
|
||||
|
||||
function parse()
|
||||
{
|
||||
lib_preprocess::assert_header "Timestamp;Date;Time;Type;Transaction ID;Fee;Fee unit;Address;Label;Amount;Amount unit;Fiat (USD);Other"
|
||||
local _gawk=("gawk")
|
||||
local _fs _header
|
||||
|
||||
_header="$(reseat_fs ";")"
|
||||
if lib_preprocess::test_header "$_header"; then
|
||||
_fs="FS=;"
|
||||
else
|
||||
# Since v25.9.1
|
||||
_header="$(reseat_fs ",")"
|
||||
lib_preprocess::assert_header "$_header"
|
||||
_gawk+=("--csv")
|
||||
fi
|
||||
|
||||
# Get subaccount(s) from filename
|
||||
local _subaccount
|
||||
_subaccount="$(echo $global_in_filename | cut -d'_' -f1)"
|
||||
|
||||
# NOTE: subaccount (account label) is entered within the app
|
||||
gawk \
|
||||
"${_gawk[@]}" \
|
||||
-v global_year="$global_year" \
|
||||
-v global_subaccount="$global_subaccount" \
|
||||
-v subaccount="$_subaccount" \
|
||||
@@ -64,7 +83,7 @@ function parse()
|
||||
# skip # Date (N/A)
|
||||
# skip # Time (N/A)
|
||||
|
||||
# Type # TODO: are there more types?
|
||||
# Type (TODO: are there more types?)
|
||||
direction=($4 ~ /^RECV$/ ? "IN" : "OUT")
|
||||
printf $4 OFS
|
||||
|
||||
@@ -80,7 +99,19 @@ function parse()
|
||||
|
||||
printf("%.8f", $10); printf OFS # Amount # TODO: more than 8 places for Ethereum, etc.?
|
||||
printf "\"" $11 "\"" OFS # Amount unit
|
||||
printf "\"" $12 "\"" OFS # Fiat (USD)
|
||||
|
||||
# Fiat (USD)
|
||||
# NOTE: is already quoted since v25.9.1
|
||||
fiat=$12
|
||||
if (fiat ~ /^"/)
|
||||
{
|
||||
printf fiat OFS
|
||||
}
|
||||
else
|
||||
{
|
||||
printf "\"" fiat "\"" OFS
|
||||
}
|
||||
|
||||
printf "\"" $13 "\"" OFS # Other
|
||||
|
||||
printf direction OFS
|
||||
@@ -88,7 +119,7 @@ function parse()
|
||||
|
||||
printf "\n"
|
||||
|
||||
}' FS=\; OFS=, "$global_in_path" >"$global_out_path"
|
||||
}' "$_fs" OFS=, "$global_in_path" >"$global_out_path"
|
||||
}
|
||||
|
||||
function main()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# docker-finance | modern accounting for the power-user
|
||||
#
|
||||
# Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
# Copyright (C) 2021-2026 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||
#
|
||||
# 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
|
||||
@@ -64,9 +64,16 @@ echo -e " \e[32m│ └─\e[37;2m ${global_in_filename}\e[0m"
|
||||
function lib_preprocess::test_header()
|
||||
{
|
||||
local _column="$1"
|
||||
|
||||
local _header
|
||||
_header="$(lib_preprocess::__sanitize_header $2)"
|
||||
[[ "$_header" =~ (^${_column}$|^${_column},|,${_column},|,${_column}$) ]] && return 0 || return 2
|
||||
|
||||
local _delim="$3"
|
||||
[ -z "$_delim" ] && _delim=","
|
||||
|
||||
# TODO: consolidate regexp
|
||||
[[ "$_header" =~ (^"${_column}"$|^"${_column}${_delim}"|"${_delim}${_column}${_delim}"|"${_delim}${_column}"$) ]] \
|
||||
&& return 0 || return 2
|
||||
}
|
||||
|
||||
# Assert header in given CSV header
|
||||
|
||||
Reference in New Issue
Block a user