112 Commits

Author SHA1 Message Date
d6100d209c Merge pull request #308 into master
1402084a CHANGELOG: add 1.3.0 (Aaron Fiore)
e9137da2 client: manifest: bump version to v1.3.0 (Aaron Fiore)
2026-02-27 13:10:31 -08:00
1402084a7c CHANGELOG: add 1.3.0 2026-02-26 14:58:35 -08:00
e9137da2b8 client: manifest: bump version to v1.3.0 2026-02-26 14:33:15 -08:00
95da584c45 Merge pull request #307 into master
fc4bfe1a client: Dockerfiles: remote: root: bump to 6.38.02-1 (Aaron Fiore)
2026-02-26 14:31:14 -08:00
fc4bfe1a0c client: Dockerfiles: remote: root: bump to 6.38.02-1 2026-02-26 13:38:45 -08:00
41fc0a64db Merge pull request #306 into master
12d9d31d client: docker: completion: add help to `plugins` (Aaron Fiore)
17692e61 client: docker: lib_plugins: update usage help (Aaron Fiore)
0e40b89b container: finance: lib_plugins: update usage help (Aaron Fiore)
2026-02-26 10:40:57 -08:00
12d9d31d2f client: docker: completion: add help to plugins 2026-02-26 10:38:28 -08:00
17692e61fc client: docker: lib_plugins: update usage help 2026-02-26 10:38:28 -08:00
0e40b89be8 container: finance: lib_plugins: update usage help 2026-02-25 11:43:04 -08:00
ea5b3b8d84 Merge pull request #305 into master
a69d0b20 client: plugins: tor: decrease bootstrap wait time (Aaron Fiore)
2026-02-25 10:13:47 -08:00
a69d0b20dd client: plugins: tor: decrease bootstrap wait time
Now that retries are implemented, this can be reduced.

NOTE: while it's possible to add controller support, this works for now.
2026-02-24 13:56:38 -08:00
77185e6b09 Merge pull request #304 into master
2b975345 client: Dockerfiles: remote: root: bump to 6.38.00-4 (Aaron Fiore)
2026-02-23 12:13:06 -08:00
2b9753459e client: Dockerfiles: remote: root: bump to 6.38.00-4 2026-02-23 11:01:07 -08:00
413f5805a5 Merge pull request #303 into master
eca2f75f client: fix base path location deduction when sourced (Aaron Fiore)
2026-02-19 11:26:24 -08:00
eca2f75f74 client: fix base path location deduction when sourced
- Since these files are only ever sourced, deduction must be relative to
  `BASH_SOURCE` (or else realpath will break)

- Fixes client-side `plugins` completion
  * realpath breakage was introduced in #301
2026-02-19 11:10:39 -08:00
f7ca987da3 Merge pull request #302 into master
96964b43 container: root: plugin: common: fix docs (custom plugin location) (Aaron Fiore)
2026-02-19 10:33:58 -08:00
96964b4372 container: root: plugin: common: fix docs (custom plugin location)
`DOCKER_FINANCE_CLIENT_PLUGINS` is bind-mounted to
`DOCKER_FINANCE_CONTAINER_PLUGINS` and docs must reflect container view.
2026-02-18 16:41:35 -08:00
699c838214 Merge pull request #301 into master
7c9f678c repo: gitea: workflows: dfi: update to reflect default paths (Aaron Fiore)
4d6a41a3 client: move `docker-finance.d` to `conf.d` (Aaron Fiore)
8dc028b3 container: lib_finance: change `docker-finance.d` to `conf.d` (Aaron Fiore)
489d7019 client: lib_gen: change `docker-finance.d` to `conf.d` (Aaron Fiore)
dd669929 client: lib_env: change `docker-finance.d` to `conf.d` (Aaron Fiore)
03f43f40 client: docker-finance.d: env: change default paths (Aaron Fiore)
2026-02-18 13:36:27 -08:00
7c9f678c25 repo: gitea: workflows: dfi: update to reflect default paths 2026-02-18 10:14:46 -08:00
4d6a41a38a client: move docker-finance.d to conf.d 2026-02-18 09:58:03 -08:00
8dc028b393 container: lib_finance: change docker-finance.d to conf.d 2026-02-18 09:58:02 -08:00
489d7019ee client: lib_gen: change docker-finance.d to conf.d 2026-02-18 09:58:02 -08:00
dd66992932 client: lib_env: change docker-finance.d to conf.d 2026-02-18 09:58:02 -08:00
03f43f407f client: docker-finance.d: env: change default paths
- Defaults are now consolidated under a single parent directory
- Basenames are now simply-named to avoid verbosity and confusion
  * Assumes that installation instructions were used during setup
2026-02-18 09:57:01 -08:00
29ccab3637 Merge pull request #300 into master
95adaf51 client: plugins: bitcoin: pull tags from remote (Aaron Fiore)
2026-02-17 14:04:53 -08:00
95adaf514c client: plugins: bitcoin: pull tags from remote 2026-02-17 14:03:31 -08:00
2090b4740f Merge pull request #299 into master
e481faf1 client: lib_docker: `exec`: silence noise when not debugging (Aaron Fiore)
2026-02-17 13:13:46 -08:00
e481faf1b9 client: lib_docker: exec: silence noise when not debugging 2026-02-17 12:37:02 -08:00
dc2f6eec3b Merge pull request #298 into master
44707d9f repo: gitea: workflows: dfi: impl: refactor with common exit function (Aaron Fiore)
46ae4007 container: root: test: unit: utility: add exit function no-op case (Aaron Fiore)
8a1d06be container: root: common: add interpreter exit function (Aaron Fiore)
2026-02-13 17:02:27 -08:00
44707d9f00 repo: gitea: workflows: dfi: impl: refactor with common exit function 2026-02-13 16:38:23 -08:00
46ae400773 container: root: test: unit: utility: add exit function no-op case 2026-02-13 16:38:23 -08:00
8a1d06be63 container: root: common: add interpreter exit function
Wrapper (with optional message) to underlying interpreter exit call.
2026-02-13 16:38:23 -08:00
5c35bfd466 Merge pull request #297 into master
e16b1884 container: hledger-flow: trezor: add uniform quotes (Aaron Fiore)
51342a6e container: hledger-flow: paypal-business: add uniform quotes (Aaron Fiore)
dae2880c container: hledger-flow: paypal: add uniform quotes (Aaron Fiore)
c650d9bb container: hledger-flow: ledger: add uniform quotes (Aaron Fiore)
3666baed container: hledger-flow: gemini: add uniform quotes (Aaron Fiore)
3764376b container: hledger-flow: electrum: add uniform quotes (Aaron Fiore)
8efbec30 container: hledger-flow: discover: add uniform quotes (Aaron Fiore)
dadb54d4 container: hledger-flow: coinbase: add uniform quotes (Aaron Fiore)
597ed3cb container: hledger-flow: chase: add uniform quotes (Aaron Fiore)
d81210bb container: hledger-flow: capital-one: add uniform quotes (Aaron Fiore)
7f4e739f container: hledger-flow: btcpayserver: add uniform quotes (Aaron Fiore)
3a7d97b3 container: hledger-flow: ally: add uniform quotes (Aaron Fiore)
2026-02-13 15:06:58 -08:00
e16b1884fc container: hledger-flow: trezor: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:19 -08:00
51342a6ef5 container: hledger-flow: paypal-business: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:16 -08:00
dae2880c06 container: hledger-flow: paypal: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:14 -08:00
c650d9bbc9 container: hledger-flow: ledger: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:11 -08:00
3666baed83 container: hledger-flow: gemini: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:09 -08:00
3764376bfa container: hledger-flow: electrum: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:06 -08:00
8efbec30cd container: hledger-flow: discover: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:04 -08:00
dadb54d45d container: hledger-flow: coinbase: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:47:00 -08:00
597ed3cbe3 container: hledger-flow: chase: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:46:58 -08:00
d81210bb8a container: hledger-flow: capital-one: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:46:56 -08:00
7f4e739f9d container: hledger-flow: btcpayserver: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:46:49 -08:00
3a7d97b3fb container: hledger-flow: ally: add uniform quotes
- Allows undesirable characters in variable-text columns
- Related refactoring
2026-02-13 14:46:38 -08:00
a71d4bcb72 Merge pull request #296 into master
8e21f533 repo: gitea: update repo domain to gitea.evergreencrypto.co (Aaron Fiore)
bd0db926 client: Dockerfiles: remote: root: update PACKAGER value (Aaron Fiore)
ea97e9a0 CHANGELOG: update repo domain to gitea.evergreencrypto.co (Aaron Fiore)
ff577165 README: update repo domain to gitea.evergreencrypto.co (Aaron Fiore)
2026-02-10 16:41:38 -08:00
8e21f53368 repo: gitea: update repo domain to gitea.evergreencrypto.co 2026-02-10 16:00:49 -08:00
bd0db92601 client: Dockerfiles: remote: root: update PACKAGER value 2026-02-10 15:53:24 -08:00
ea97e9a06e CHANGELOG: update repo domain to gitea.evergreencrypto.co 2026-02-10 15:53:18 -08:00
ff57716533 README: update repo domain to gitea.evergreencrypto.co 2026-02-10 15:53:12 -08:00
7809e219b6 Merge pull request #294 into master
e824294c CHANGELOG: add 1.2.0 (Aaron Fiore)
7435fb14 client: manifest: bump version to v1.2.0 (Aaron Fiore)
2026-02-06 12:17:03 -08:00
e824294c05 CHANGELOG: add 1.2.0 2026-02-06 11:23:25 -08:00
7435fb1409 client: manifest: bump version to v1.2.0 2026-02-06 10:45:25 -08:00
91c3fa591b Merge pull request #295 into master
321751d0 container: root: common: add `cppcheck-suppress stlIfStrFind` (Aaron Fiore)
b9b6a0b9 client: dev-tools: lib_linter: cppcheck: bump to --std=c++20 (Aaron Fiore)
2026-02-06 10:36:23 -08:00
321751d009 container: root: common: add cppcheck-suppress stlIfStrFind
`basic_string::starts_with()` is not applicable and breaks functionality
2026-02-05 17:29:27 -08:00
b9b6a0b9a1 client: dev-tools: lib_linter: cppcheck: bump to --std=c++20 2026-02-05 17:22:18 -08:00
9eff9bd6fe Merge pull request #293 into master
c5d2a9e5 repo: gitea: workflows: dfi: impl: add paths to remove (host::clean) (Aaron Fiore)
56c7686e repo: gitea: workflows: dfi: impl: force remove `dfi` images (Aaron Fiore)
2026-02-05 12:22:37 -08:00
c5d2a9e530 repo: gitea: workflows: dfi: impl: add paths to remove (host::clean)
- Host's (guest VM's) `act_runner` does not use (nor create)
  ${HOME}/.config for any other purpose other than for `dfi`'s
  docker-finance.d

- ${HOME}/.docker is removed to keep a clean workspace
2026-02-05 12:19:13 -08:00
56c7686e37 repo: gitea: workflows: dfi: impl: force remove dfi images
As a result of the `backup` action, images were not actually removed:

    "image is referenced in multiple repositories"
2026-02-05 12:19:08 -08:00
2065721625 Merge pull request #292 into master
0871934f repo: gitea: workflows: dfi: plugins: tor: refactor (Aaron Fiore)
aebe9c66 client: plugins: tor: add timeout when `stop`ing tor container (Aaron Fiore)
f302908b client: plugins: tor: implement retries when bootstrapping (Aaron Fiore)
e0c66e74 client: plugins: tor: don't use interactive shell when updating proxychains (Aaron Fiore)
19c2d477 client: plugins: tor: print info instead of warnings (when info) (Aaron Fiore)
890c0631 client: plugins: tor: pull `alpine:latest` when `start`ing (Aaron Fiore)
56ba75e7 client: plugins: tor: fix inspection for running tor container (Aaron Fiore)
810e21d7 client: plugins: tor: refactor check for running `dfi` instance (Aaron Fiore)
2026-02-05 11:26:35 -08:00
0871934f3c repo: gitea: workflows: dfi: plugins: tor: refactor
Reflects updates to plugin impl.
2026-02-04 15:54:08 -08:00
aebe9c66e3 client: plugins: tor: add timeout when stoping tor container 2026-02-04 15:54:04 -08:00
f302908b82 client: plugins: tor: implement retries when bootstrapping 2026-02-04 15:51:10 -08:00
e0c66e74d6 client: plugins: tor: don't use interactive shell when updating proxychains 2026-02-04 15:50:45 -08:00
19c2d477f6 client: plugins: tor: print info instead of warnings (when info) 2026-02-04 15:49:54 -08:00
890c063130 client: plugins: tor: pull alpine:latest when starting 2026-02-04 15:49:36 -08:00
56ba75e790 client: plugins: tor: fix inspection for running tor container 2026-02-04 15:45:59 -08:00
810e21d7d3 client: plugins: tor: refactor check for running dfi instance 2026-02-04 15:45:59 -08:00
578b464f38 Merge pull request #291 into master
6bcad2f2 repo: gitea: workflows: dfi: impl: add `fetch` API keys (secrets); expand coverage (Aaron Fiore)
2b30b2ca repo: gitea: workflows: dfi: config: add `fetch` API keys (secrets) (Aaron Fiore)
2026-02-04 13:29:29 -08:00
6bcad2f24a repo: gitea: workflows: dfi: impl: add fetch API keys (secrets); expand coverage 2026-02-04 12:32:25 -08:00
2b30b2caf4 repo: gitea: workflows: dfi: config: add fetch API keys (secrets) 2026-02-04 12:29:11 -08:00
6f48524ffd Merge pull request #290 into master
ed7342db client: docker-finance.d: fetch: update/cleanup comments (Aaron Fiore)
373796d3 client: docker-finance.d: fetch: update mobula assets (Aaron Fiore)
2026-02-04 12:27:03 -08:00
ed7342dbae client: docker-finance.d: fetch: update/cleanup comments 2026-02-04 10:55:30 -08:00
373796d38a client: docker-finance.d: fetch: update mobula assets
Remove cUSDT since mobula now returns 0 value price for
ethereum:0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9/cUSDT
2026-02-04 10:55:30 -08:00
ffe0650bbe Merge pull request #289 into master
a1a08495 container: lib_fetch: return the value of executor (Aaron Fiore)
2026-02-04 10:53:29 -08:00
a1a08495ff container: lib_fetch: return the value of executor 2026-02-04 10:48:04 -08:00
4d8b68c341 Merge pull request #288 into master
9e88c679 container: hledger-flow: coinomi: add chains to template (Aaron Fiore)
2026-02-04 10:26:53 -08:00
9e88c67910 container: hledger-flow: coinomi: add chains to template
These chains have been supported and provided by the default generated
`fetch` config for coinomi but they were not included during default
coinomi template generation.
2026-02-03 16:33:27 -08:00
d18fe85f4c Merge pull request #287 into master
de556447 repo: add Gitea Workflow Actions for CI (impl) (Aaron Fiore)
26536138 repo: add Gitea Workflow Actions for CI (config) (Aaron Fiore)
2026-02-02 15:50:51 -08:00
de5564478a repo: add Gitea Workflow Actions for CI (impl) 2026-02-02 15:43:20 -08:00
265361388f repo: add Gitea Workflow Actions for CI (config) 2026-01-30 16:45:18 -08:00
533dc8447b Merge pull request #286 into master
a4b73cfe container: root: common: allow quotations in `Pluggable` arguments (Aaron Fiore)
2026-01-29 10:08:32 -08:00
a4b73cfe43 container: root: common: allow quotations in Pluggable arguments
Helps facilitate CLI usage; e.g.,

$ dfi testprofile/testuser root plugins/repo/bitcoin/bitcoin.cc 'dfi::macro::load(\"repo/test/unit.C\")'
2026-01-29 10:03:50 -08:00
489c98c2a1 Merge pull request #285 into master
7e9ecc9a client: lib_gen: generate shared path layout (Aaron Fiore)
2026-01-29 10:02:15 -08:00
7e9ecc9ae4 client: lib_gen: generate shared path layout
If path does not exist prior to bind-mounting, path will be owned by
root (and unwritable by DOCKER_FINANCE_USER).
2026-01-28 17:03:55 -08:00
48d40423c7 Merge pull request #284 into master
0ef10be2 client: docker-finance.d: archlinux: reset USER in optional block (Aaron Fiore)
96ea8fc9 client: archlinux: move `less` from custom build to base build (Aaron Fiore)
bbdb53eb client: docker-finance.d: archlinux: clarify optional blocks (Aaron Fiore)
2026-01-28 15:50:43 -08:00
0ef10be21e client: docker-finance.d: archlinux: reset USER in optional block
- Reset to root after the `pipx install` example
  * Needed for CI (and general annoyance removal)
2026-01-28 15:30:39 -08:00
96ea8fc9b0 client: archlinux: move less from custom build to base build 2026-01-28 15:30:39 -08:00
bbdb53eba5 client: docker-finance.d: archlinux: clarify optional blocks 2026-01-28 15:29:22 -08:00
3b1c430157 Merge pull request #283 into master
697763b1 client: lib_docker: return compose error code (Aaron Fiore)
2026-01-28 15:28:03 -08:00
697763b17e client: lib_docker: return compose error code
Returns code of compose failure or if `run`'s container returns error.
2026-01-28 15:22:21 -08:00
820286ba41 Merge pull request #282 into master
f37e2662 client: Dockerfiles: local: dev-tools: bind-mount .gitea (Aaron Fiore)
2026-01-28 11:38:46 -08:00
f37e2662f6 client: Dockerfiles: local: dev-tools: bind-mount .gitea
Will allow linter to access files in the .gitea directory.
2026-01-28 11:36:49 -08:00
aba07098cd Merge pull request #281 into master
e2d63306 client: lib_gen: generate custom plugin layout for all images (Aaron Fiore)
2026-01-28 11:35:21 -08:00
e2d6330669 client: lib_gen: generate custom plugin layout for all images
Previously only generated for the finance image.
2026-01-28 11:30:10 -08:00
2ed8be4f43 Merge pull request #280 into master
bd6e3c2f container: lib_hledger: make error fatal if `hledger-web` cannot start (Aaron Fiore)
1c6b4493 container: lib_hledger: only feed `visidata` on valid `hledger` command (Aaron Fiore)
2026-01-28 11:28:49 -08:00
bd6e3c2ff7 container: lib_hledger: make error fatal if hledger-web cannot start
Needed for CI.
2026-01-28 11:26:15 -08:00
1c6b449318 container: lib_hledger: only feed visidata on valid hledger command 2026-01-28 11:26:08 -08:00
2b78829c72 Merge pull request #279 into master
5e8fff81 container: lib_taxes: fix for generating `all` years (`year=all`) (Aaron Fiore)
2026-01-28 11:23:21 -08:00
5e8fff8103 container: lib_taxes: fix for generating all years (year=all)
- The expected `hledger` output format appears to have changed, likely
  from a recent `hledger` release (confirmed to be unrelated to `xan`).

- This bug does *not* affect individual year tax report generation, when
  given a specific (or default) year.
2026-01-28 11:22:15 -08:00
5f57ea12b2 Merge pull request #278 into master
f7cefedd container: lib_finance: allow non-root system user; print warning (Aaron Fiore)
cc3226a5 client: lib_env: allow non-root system user; print warning (Aaron Fiore)
2026-01-28 11:17:42 -08:00
f7cefedd96 container: lib_finance: allow non-root system user; print warning
Needed for CI.
2026-01-28 11:16:34 -08:00
cc3226a5ea client: lib_env: allow non-root system user; print warning
Needed for CI.
2026-01-28 11:16:34 -08:00
c9f831b659 Merge pull request #277 into master
fcb5b1fa client: lib_docker: up: only allocate pseudo-TTY when needed (Aaron Fiore)
2026-01-28 11:14:22 -08:00
fcb5b1fa92 client: lib_docker: up: only allocate pseudo-TTY when needed 2026-01-21 14:25:33 -08:00
b0abdca1bf Merge pull request #276 into master
7b155886 client: lib_docker: exec: only allocate pseudo-TTY when needed (Aaron Fiore)
2026-01-21 12:45:57 -08:00
7b15588681 client: lib_docker: exec: only allocate pseudo-TTY when needed 2026-01-21 12:36:46 -08:00
cee9948499 Merge pull request #275 into master
592e08ef client: lib_docker: dev-tools: use fatal error for invalid build types (Aaron Fiore)
2026-01-21 11:36:38 -08:00
592e08efb8 client: lib_docker: dev-tools: use fatal error for invalid build types 2026-01-21 11:34:52 -08:00
87ad0f9dfc Merge pull request #274 into master
af599782 client: plugins: tor: increase bootstrap wait time (Aaron Fiore)
2a0c2610 client: plugins: tor: disable interactive pseudo-TTY (Aaron Fiore)
2026-01-21 11:32:14 -08:00
af59978202 client: plugins: tor: increase bootstrap wait time 2026-01-21 11:08:28 -08:00
2a0c2610b3 client: plugins: tor: disable interactive pseudo-TTY
Not needed, change required for CI.
2026-01-21 11:08:16 -08:00
50 changed files with 2093 additions and 487 deletions

View File

@@ -13,5 +13,5 @@ body:
attributes:
label: "Agreement"
options:
- label: I have read and understood the [Development](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-contribute.md#development) and [License](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/Where-is-the-legalese.md#where-is-the-legalese) documentation
- label: I have read and understood the [Development](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-contribute.md#development) and [License](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/Where-is-the-legalese.md#where-is-the-legalese) documentation
required: true

963
.gitea/workflows/dfi.bash Executable file
View File

@@ -0,0 +1,963 @@
#!/usr/bin/env bash
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
set -e
hash vim
declare -xr EDITOR=vim
declare -r ci_shell=("bash" "-i" "-c")
# Defaults to run (most) commands with
declare -r ci_archlinux="dfi archlinux/${USER}:default"
declare -r ci_dev_tools="dfi dev-tools/${USER}:default"
declare -r ci_profile="dfi testprofile/${USER}"
##
## Host (act runner)
##
function host::clean()
{
# Remove previous containers from any failed builds
docker rm -f "$(docker ps -aqf "name=^docker-finance")" 2>/dev/null \
&& echo "WARNING: previous docker-finance containers found and removed" \
|| echo "No docker-finance containers found"
# Remove all images not in use
local -r _images=("$(docker images -a --format=table | grep docker-finance | gawk '{print $3}' | sort -u)")
while read _line; do
docker image rm -f "$_line" || continue
done < <(echo "${_images[@]}")
# Remove all leftovers
docker system prune -f
docker builder prune -af
# Remove default environment and layout
local _paths
_paths+=(".bashrc")
_paths+=(".docker")
_paths+=("docker-finance")
for _path in "${_paths[@]}"; do
rm -fr "${HOME:?}/${_path:?}"
done
# Prepare for installation
# *MUST* exist prior to client::install
touch "${HOME:?}"/.bashrc
}
##
## Client (host)
##
#
# client::install
#
function client::install()
{
"${HOME:?}"/docker-finance/repo/client/install.bash
source "${HOME:?}"/.bashrc
}
#
# client::finance
#
function client::finance::gen()
{
local -r _tags=("micro" "tiny" "slim" "default")
local -r _types=("env" "build" "superscript" "env,build,superscript")
for _tag in "${_tags[@]}"; do
for _type in "${_types[@]}"; do
local _gen="dfi archlinux/${USER}:${_tag} gen"
# Invalid
"${ci_shell[@]}" "$_gen type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_gen INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_gen type=${_type} confirm=no"
done
done
# For CI purposes, only generate flow for 'default'
"${ci_shell[@]}" "$ci_archlinux gen type=flow profile=testprofile/${USER} confirm=no dev=on"
}
function client::finance::edit()
{
local -r tags=("micro" "tiny" "slim" "default")
local types=()
types+=("env")
types+=("shell" "superscript")
types+=("build" "dockerfile")
types+=("env,shell,build")
types+=("env,superscript,dockerfile")
declare -r types
for _tag in "${tags[@]}"; do
for _type in "${types[@]}"; do
local _edit="dfi archlinux/${USER}:${_tag} edit"
# Invalid
"${ci_shell[@]}" "$_edit type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_edit INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_edit type=${_type} & wait ; kill -9 %1"
done
# Build: uncomment all optional packages and plugin dependencies
if [[ "$_tag" == "default" ]]; then
local _file
_file="${HOME:?}/docker-finance/conf.d/client/$(uname -s)-$(uname -m)/archlinux/default/Dockerfiles/${USER:?}@$(uname -n)"
[ ! -f "$_file" ] && exit 1
sed -i '18,56s/#//' "$_file"
fi
done
}
function client::finance::build()
{
local -r _types=("micro" "tiny" "slim" "default")
for _type in "${_types[@]}"; do
local _build="dfi archlinux/${USER}:${_type} build"
# Invalid
"${ci_shell[@]}" "$_build type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_build INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_build type=${_type}"
done
}
function client::finance::backup()
{
local -r _backup=("micro" "tiny" "slim" "default")
for _type in "${_backup[@]}"; do
"${ci_shell[@]}" "dfi archlinux/${USER}:${_type} backup"
sleep 1s
done
}
function client::finance::up()
{
# NOTE: the container is detached but what follows is
# an interactive terminal (so fork this).
local -r _detach="&"
"${ci_shell[@]}" "$ci_archlinux up $_detach wait"
}
function client::finance::stop()
{
"${ci_shell[@]}" "$ci_archlinux stop"
}
function client::finance::start()
{
"${ci_shell[@]}" "$ci_archlinux start"
}
function client::finance::down()
{
"${ci_shell[@]}" "$ci_archlinux down"
}
function client::finance::shell()
{
client::finance::up
local -r _shell="$ci_archlinux shell"
local -r _args=(" " "user=${USER}" "user=root")
for _arg in "${_args[@]}"; do
# Invalid
"${ci_shell[@]}" "$_shell INVALID || exit 0"
"${ci_shell[@]}" "$_shell user=INVALID || exit 0"
# Valid
"${ci_shell[@]}" "$_shell $_arg & wait ; kill -9 %1"
done
client::finance::down
}
function client::finance::exec()
{
client::finance::up
"${ci_shell[@]}" "$ci_archlinux exec 'exit 1' || exit 0"
"${ci_shell[@]}" "$ci_archlinux exec 'exit 0'"
client::finance::down
}
function client::finance::plugins::__tor()
{
[ -z "$_plugins" ] && exit 1
client::finance::up
local -r _tor=("start" "restart" "stop")
for _arg in "${_tor[@]}"; do
"${ci_shell[@]}" "$_plugins repo/tor.bash $_arg"
done
client::finance::down
}
function client::finance::plugins::__bitcoin()
{
[ -z "$_plugins" ] && exit 1
client::finance::up
local _bitcoin
_bitcoin+=("get" "build")
# TODO: build is needed for container's bitcoin plugin)
# _bitcoin+=("clean")
for _arg in "${_bitcoin[@]}"; do
"${ci_shell[@]}" "$_plugins repo/bitcoin.bash $_arg"
done
client::finance::down
}
function client::finance::plugins()
{
local -r _plugins="$ci_archlinux plugins"
# Invalid
"${ci_shell[@]}" "$_plugins INVALID || exit 0"
"${ci_shell[@]}" "$_plugins repo/INVALID || exit 0"
"${ci_shell[@]}" "$_plugins custom/INVALID || exit 0"
# Valid
"${ci_shell[@]}" "$_plugins repo/example.bash"
client::finance::plugins::__tor
client::finance::plugins::__bitcoin
}
function client::finance::run()
{
# Invalid
"${ci_shell[@]}" "$ci_archlinux run 'hash INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$ci_archlinux run 'hash bash'"
}
function client::finance::version()
{
local -r _tags=("micro" "tiny" "slim" "default")
local _types
_types+=("client" "container" "short" "all")
_types+=("client,container,short")
declare -r _types
for _tag in "${_tags[@]}"; do
for _type in "${_types[@]}"; do
local _version="dfi archlinux/${USER}:${_tag} version"
# Invalid
"${ci_shell[@]}" "$_version type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_version INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_version type=${_type}"
done
done
}
function client::finance::update()
{
local -r _types=("micro" "tiny" "slim" "default")
for _type in "${_types[@]}"; do
local _update="dfi archlinux/${USER}:${_type} update"
# Invalid
"${ci_shell[@]}" "$_update type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_update INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_update type=${_type}"
done
}
function client::finance::rm()
{
local -r _build=("micro" "tiny" "slim" "default")
for _type in "${_build[@]}"; do
local _image="dfi archlinux/${USER}:${_type}"
"${ci_shell[@]}" "$_image rm"
docker images -q "$_image" && return $?
# NOTE: don't attempt `dfi` container commands or else image will try to pull/re-build
done
# Re-build (from cache) for future test cases
client::finance::build
}
##
## Container (finance)
##
function container::finance::edit()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _edit="$ci_profile edit"
local -r _types=("add" "iadd" "manual" "fetch" "hledger" "meta" "shell" "subscript" "rules" "preprocess")
# Invalid
for _type in "${_types[@]}"; do
"${ci_shell[@]}" "$_exec '$_edit type=${_type}INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_edit INVALID=${_type}' || exit 0"
if [[ "$_type" =~ ^manual$ ]]; then
"${ci_shell[@]}" "$_exec '$_edit type=${_type} year=abc123' || exit 0"
fi
done
# Valid
for _type in "${_types[@]}"; do
if [[ "$_type" =~ ^rules$|^preprocess$ ]]; then
# Valid type w/ valid account
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=coinbase & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=coinbase/platform & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=coinbase/platform,electrum/wallet-1 & wait ; kill -9 %1'"
# Valid type w/ *invalid* account
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=coinbase/does-not-exist' || exit 0"
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=does-not-exist/here-either' || exit 0"
"${ci_shell[@]}" "$_exec '$_edit type=${_type} account=does-not-exist/here-either,nor/here' || exit 0"
elif [[ "$_type" =~ ^manual$ ]]; then
"${ci_shell[@]}" "$_exec '$_edit type=${_type} year=$(date +%Y) & wait ; kill -9 %1'"
else
"${ci_shell[@]}" "$_exec '$_edit type=${_type} & wait ; kill -9 %1'"
fi
done
"${ci_shell[@]}" "$_exec '$_edit type=add,iadd,manual,fetch,hledger,meta,shell,subscript & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_edit type=rules,preprocess account=coinbase/platform,electrum/wallet-1 & wait ; kill -9 %1'"
#
# Fetch: add API secrets for CI
#
[[ -z "$CI_DFI_FETCH_MOBULA" || -z "$CI_DFI_FETCH_ETHERSCAN" ]] && exit 1
local -r _file="${HOME}/docker-finance/flow/profiles/testprofile/${USER}/conf.d/fetch/fetch.yaml"
[ ! -f "$_file" ] && exit 1
# `prices`
sed -i "77s/.*/ key: \"${CI_DFI_FETCH_MOBULA}\"/" "$_file"
[ ! -z "$CI_DFI_FETCH_COINGECKO" ] \
&& sed -i "118s/.*/ key: \"${CI_DFI_FETCH_COINGECKO}\"/" "$_file" \
|| echo "[INFO] CI_DFI_FETCH_COINGECKO is empty (using free plan)"
# `accounts`
#
# NOTE: For CI, a single etherscan API key is used per account
# (but the flexibility remains to use multiple keys if needed)
#
sed -i "s:etherscan/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:etherscan/${CI_DFI_FETCH_ETHERSCAN}:g" "$_file"
client::finance::down
}
function container::finance::fetch()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _fetch="$ci_profile fetch"
#
# `price`
#
# Invalid
"${ci_shell[@]}" "$_exec '$_fetch price=INVALID api=mobula,coingecko' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch price=bitcoin/BTC,ethereum/ETH api=INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_fetch all=price'"
"${ci_shell[@]}" "$_exec '$_fetch price=bitcoin/BTC,ethereum/ETH api=mobula,coingecko'"
"${ci_shell[@]}" "$_exec '$_fetch price=algorand/ALGO,tezos/XTZ api=mobula year=2024'"
#
# `account`
#
# Test given wallet/chain arguments with test wallets picked at random (mockups)
# NOTE: these are also all caught with `all=account` or `all=all`
local -r _algo_wallet="algorand/phone:mobile-1/55YXQ2AC7PUOOYIWUFIOGFZ7M5CBWFUDOIT7L3FMZVE7HGC3IKABL7HVOE"
local -r _tezos_wallet="tezos/nano:x-1:staking-1/tz1S1ayWDiHzmL6zFNnY1ivvUkEgDcH88cjx"
local -r _ethereum_wallet="ethereum/laptop:wallet-1/0x6546d43EA6DE45EB7298A2074e239D5573cA02F3"
local -r _polygon_wallet="polygon/laptop:wallet-2/0xEad0B2b6f6ab84d527569835cd7fe364e067cFFf"
local -r _arbitrum_wallet="arbitrum/phone:wallet-2/0xd3b29C94a67Cfa949FeD7dd1474B71d006fa0A2A"
local -r _base_wallet="base/laptop:wallet-3/0x4C7219b760b71B9415E0e01Abd34d0f65631e57e"
local -r _optimism_wallet="optimism/phone:wallet-3/0x53004E863Aa0F4028B154ECA65CFb32Eb5a8f5bB"
# Invalid
"${ci_shell[@]}" "$_exec '$_fetch account=INVALID chain=algorand,tezos year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger chain=INVALID year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger chain=algorand,tezos year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=INVALID chain=${_algo_wallet} year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=pera-wallet chain=INVALID year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=pera-wallet chain=${_algo_wallet} year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger,pera-walletINVALID chain=${_tezos_wallet},${_algo_wallet} year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger,pera-wallet chain=INVALID${_tezos_wallet},${_algo_wallet} year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger,pera-wallet chain=${_tezos_wallet},${_algo_wallet} year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamaskINVALID chain=arbitrum year=2025' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=INVALIDarbitrum year=2025' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=arbitrum year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamaskINVALID chain=${_ethereum_wallet},${_polygon_wallet},${_arbitrum_wallet},${_base_wallet},${_optimism_wallet} year=2025' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=INVALID${_ethereum_wallet},${_polygon_wallet},${_arbitrum_wallet},${_base_wallet},${_optimism_wallet} year=2025' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=${_ethereum_wallet},${_polygon_wallet},${_arbitrum_wallet},${_base_wallet},${_optimism_wallet} year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=INVALIDcoinbase-wallet,coinomi,ledger,metamask,pera-wallet chain=algorand,arbitrum,ethereum,polygon,tezos year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=coinbase-wallet,coinomi,ledger,metamask,pera-wallet chain=INVALIDalgorand,arbitrum,ethereum,polygon,tezos year=2024' || exit 0"
"${ci_shell[@]}" "$_exec '$_fetch account=coinbase-wallet,coinomi,ledger,metamask,pera-wallet chain=algorand,arbitrum,ethereum,polygon,tezos year=INVALID' || exit 0"
# Valid
#
# NOTE: not currently fetching Optimism or Base for CI
#
# "[FATAL] Free API access is not supported for this chain. Please upgrade your api plan for full chain coverage. https://etherscan.io/apis"
#
"${ci_shell[@]}" "$_exec '$_fetch account=ledger chain=${_tezos_wallet} year=2024'"
"${ci_shell[@]}" "$_exec '$_fetch account=pera-wallet chain=${_algo_wallet} year=2024'"
"${ci_shell[@]}" "$_exec '$_fetch account=ledger,pera-wallet chain=${_tezos_wallet},${_algo_wallet} year=2024'"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=arbitrum year=2025'"
"${ci_shell[@]}" "$_exec '$_fetch account=metamask chain=${_ethereum_wallet},${_polygon_wallet},${_arbitrum_wallet} year=2025'"
"${ci_shell[@]}" "$_exec '$_fetch account=coinbase-wallet,coinomi,ledger,metamask,pera-wallet chain=algorand,arbitrum,ethereum,polygon,tezos year=2024'"
client::finance::down
}
function container::finance::import()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _import="$ci_profile import"
# mockups are guaranteed to start from this year
local -r _year="2018"
"${ci_shell[@]}" "$_exec '$_import year=${_year}'"
client::finance::down
}
function container::finance::hledger()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _hledger="$ci_profile hledger"
# Invalid
"${ci_shell[@]}" "$_exec '$_hledger INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_hledger --pager=N bal assets liabilities cur:BTC'"
client::finance::down
}
function container::finance::hledger-ui()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _hledger_ui="$ci_profile hledger-ui"
# Invalid
"${ci_shell[@]}" "$_exec '$_hledger_ui --INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_hledger_ui --pager=N bal assets liabilities cur:BTC & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_hledger_ui & wait ; kill -9 %1'"
client::finance::down
}
function container::finance::hledger-vui()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _hledger_vui="$ci_profile hledger-vui"
# Invalid
"${ci_shell[@]}" "$_exec '$_hledger_vui --INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_hledger_vui & wait ; kill -9 %1'"
client::finance::down
}
function container::finance::hledger-web()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _hledger_web="$ci_profile hledger-web"
# Invalid
"${ci_shell[@]}" "$_exec '$_hledger_web --INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_hledger_web && pkill -9 hledger-web'"
client::finance::down
}
function container::finance::meta()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _meta="$ci_profile meta"
# Invalid
"${ci_shell[@]}" "$_exec '$_meta INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_meta INVALID=' || exit 0"
"${ci_shell[@]}" "$_exec '$_meta INVALID=INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_meta ticker=btc & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_meta ticker=btc format=bech32 & wait ; kill -9 %1'"
"${ci_shell[@]}" "$_exec '$_meta ticker=btc format=bech32 account=electrum & wait ; kill -9 %1'"
client::finance::down
}
function container::finance::reports()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _reports="$ci_profile reports"
# Invalid
"${ci_shell[@]}" "$_exec '$_reports INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports INVALID=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports INVALID=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports all=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports all=type interval=INVALID year=2022' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports all=type interval=annual year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports type=INVALID,INVALID interval=quarterly,monthly' || exit 0"
"${ci_shell[@]}" "$_exec '$_reports type=is,bs interval=INVALID,INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_reports all=all'"
"${ci_shell[@]}" "$_exec '$_reports all=type interval=annual year=2022'"
"${ci_shell[@]}" "$_exec '$_reports type=is,bs interval=quarterly,monthly'"
client::finance::down
}
function container::finance::taxes()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _taxes="$ci_profile taxes"
# Invalid
"${ci_shell[@]}" "$_exec '$_taxes INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes INVALID=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes INVALID=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=all year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=account tag=INVALID write=off year=2022' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=account tag=income write=INVALID year=2022' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=account tag=income write=off year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes tag=INVALID,INVALID account=gemini,coinbase year=2022' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes tag=income,spends account=INVALID,INVALID year=2022' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes tag=income,spends account=gemini,coinbase year=INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=tag account=INVALID year=all write=off' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=tag account=nexo year=INVALID write=off' || exit 0"
"${ci_shell[@]}" "$_exec '$_taxes all=tag account=nexo year=all write=INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_taxes all=all'"
"${ci_shell[@]}" "$_exec '$_taxes all=all year=all'"
"${ci_shell[@]}" "$_exec '$_taxes all=account tag=income write=off'"
"${ci_shell[@]}" "$_exec '$_taxes tag=income,spends account=gemini,coinbase year=2022'"
"${ci_shell[@]}" "$_exec '$_taxes all=tag account=nexo year=all write=off'"
client::finance::down
}
function container::finance::times()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _times="$ci_profile times"
# TODO: invalid
# NOTE: impl-specific: currently, timewarrior requires confirmation
# which cannot be passed here (via "< <(echo yes)").
local -r _path="${HOME:?}/docker-finance/flow/times/timew"
mkdir -p "$_path" && touch "${_path}/timewarrior.cfg"
# Initial run presents confirmation dialog (so echo "yes")
"${ci_shell[@]}" "$_exec '$_times start desc=\"Task 1\" comment=\"My long comment\" tag:type=consulting'"
# Create time
sleep 3s
# Stop time
"${ci_shell[@]}" "$_exec '$_times stop'"
# If no tag found in summary, will return a single line but exit 0
[[ $("${ci_shell[@]}" "$_exec '$_times summary tag:type=consulting' | wc -l") -eq 1 ]] && exit 1
# A single entry should return only 3 lines
[[ $("${ci_shell[@]}" "$_exec '$_times export' | wc -l") -ne 3 ]] && exit 1
client::finance::down
}
function container::finance::plugins()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _plugins="$ci_profile plugins"
# Invalid
"${ci_shell[@]}" "$_exec '$_plugins INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_plugins repo/INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_plugins custom/INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_plugins repo/example.bash'"
# WARNING: timeclock plugin requires dfi `times` setup/functionality
# and must run *AFTER* the above container::finance::times() test
"${ci_shell[@]}" "$_exec '$_plugins repo/timew_to_timeclock.bash'"
client::finance::down
}
function container::finance::root()
{
client::finance::up
local -r _exec="$ci_archlinux exec"
local -r _root="$ci_profile root"
# TODO: if tests failing, interpreter not bailing because gtest will catch throws
local -r _exit="| grep FAILED && exit 1 || exit 0"
#
# Base
#
"${ci_shell[@]}" "$_exec '$_root INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_root & wait ; kill -9 %1'"
#
# Macros
#
# Invalid
"${ci_shell[@]}" "$_exec '$_root INVALID' || exit 0"
"${ci_shell[@]}" "$_exec '$_root macro/hash.C' || exit 0"
"${ci_shell[@]}" "$_exec '$_root macro/crypto/hash.C' || exit 0"
"${ci_shell[@]}" "$_exec '$_root macro/repo/crypto/hash.C' || exit 0"
# Valid
"${ci_shell[@]}" "$_exec '$_root macros/repo/crypto/hash.C'"
"${ci_shell[@]}" "$_exec '$_root macros/repo/crypto/hash.C test\\\\\ message'"
"${ci_shell[@]}" "$_exec '$_root macros/repo/crypto/random.C'"
"${ci_shell[@]}" "$_exec '$_root macros/repo/test/benchmark.C'"
"${ci_shell[@]}" "$_exec '$_root macros/repo/test/benchmark.C Random\*'"
"${ci_shell[@]}" "$_exec '$_root macros/repo/test/unit.C' $_exit"
"${ci_shell[@]}" "$_exec '$_root macros/repo/test/unit.C Pluggable\*:Macro\*:Plugin\*' $_exit"
"${ci_shell[@]}" "$_exec '$_root macros/repo/web/server.C dfi::common::exit\(0,\\\\\\\"Server\\\\\\\"\)\;'"
# TODO: ^ return value of macro
#
# Plugins
#
"${ci_shell[@]}" "$_exec '$_root plugins/repo/example/example.cc dfi::plugin::example::MyExamples\\ my\;my.example1\(\)\;dfi::common::exit\(0,\\\\\\\"MyExamples\\\\\\\"\)\;'"
# WARNING: bitcoin plugin requires dfi client-side bitcoin plugin
# and must run *AFTER* the above client::finance::plugins() test
"${ci_shell[@]}" "$_exec '$_root plugins/repo/bitcoin/bitcoin.cc try{dfi::macro::load\(\\\\\\\"repo/test/unit.C\\\\\\\"\)\;}catch\(...\){dfi::common::exit\(1\)\;}dfi::common::exit\(0\)\;' $_exit"
client::finance::down
}
# TODO: all Fetches, imports, generates taxes and reports w/ [args] year
#
# client::dev-tools
#
function client::dev-tools::gen()
{
local -r _tags=("micro" "tiny" "slim" "default")
local -r _types=("env" "build" "superscript" "env,build,superscript")
# TODO: 'default' should only be supported
for _tag in "${_tags[@]}"; do
for _type in "${_types[@]}"; do
local _gen="dfi dev-tools/${USER}:${_tag} gen"
# Invalid
"${ci_shell[@]}" "$_gen type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_gen INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_gen type=${_type} confirm=no"
done
done
}
function client::dev-tools::edit()
{
local -r _tags=("micro" "tiny" "slim" "default")
local _types=()
_types+=("env")
_types+=("shell" "superscript")
_types+=("build" "dockerfile")
_types+=("env,shell,build")
_types+=("env,superscript,dockerfile")
declare -r _types
# Currently, only 'default' is supported
for _tag in "${_tags[@]}"; do
for _type in "${_types[@]}"; do
local _edit="dfi dev-tools/${USER}:${_tag} edit"
# Invalid
"${ci_shell[@]}" "$_edit type=${_type}INVALID & wait ; kill -9 %1 || exit 0"
"${ci_shell[@]}" "$_edit INVALID=${_type} & wait ; kill -9 %1 || exit 0"
# Valid
if "${ci_shell[@]}" "$_edit type=${_type} & wait ; kill -9 %1"; then
[[ "$_tag" != default ]] || continue
fi
done
done
}
# shellcheck disable=SC2178
# shellcheck disable=SC2128
function client::dev-tools::build()
{
local -r types=("micro" "tiny" "slim" "default")
# Currently, only 'default' is supported
for _type in "${types[@]}"; do
local _build="dfi dev-tools/${USER}:${_type} build"
# Invalid
"${ci_shell[@]}" "$_build type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_build INVALID=${_type} || exit 0"
# Valid
if "${ci_shell[@]}" "$_build type=${_type}"; then
[[ "$_type" != default ]] || continue
fi
done
}
function client::dev-tools::backup()
{
local -r _backup=("micro" "tiny" "slim")
# Currently, only 'default' is supported
for _type in "${_backup[@]}"; do
if "${ci_shell[@]}" "dfi dev-tools/${USER}:${_type} backup"; then
[[ "$_type" != default ]] || continue
fi
done
"${ci_shell[@]}" "$ci_dev_tools backup"
}
function client::dev-tools::up()
{
local -r _detach="&"
"${ci_shell[@]}" "$ci_dev_tools up $_detach wait"
}
function client::dev-tools::stop()
{
"${ci_shell[@]}" "$ci_dev_tools stop"
}
function client::dev-tools::start()
{
"${ci_shell[@]}" "$ci_dev_tools start"
}
function client::dev-tools::down()
{
"${ci_shell[@]}" "$ci_dev_tools down"
}
function client::dev-tools::shell()
{
client::dev-tools::up
local -r _shell="$ci_dev_tools shell"
local -r _args=(" " "user=${USER}" "user=root")
for _arg in "${_args[@]}"; do
# Invalid
"${ci_shell[@]}" "$_shell INVALID || exit 0"
"${ci_shell[@]}" "$_shell user=INVALID || exit 0"
# Valid
"${ci_shell[@]}" "$_shell $_arg & wait ; kill -9 %1"
done
client::dev-tools::down
}
function client::dev-tools::exec()
{
client::dev-tools::up
local -r _exec="$ci_dev_tools exec"
"${ci_shell[@]}" "$_exec 'exit 1' || exit 0"
"${ci_shell[@]}" "$_exec 'exit 0'"
client::dev-tools::down
}
function client::dev-tools::plugins()
{
local -r _plugins="$ci_dev_tools plugins"
# Invalid
"${ci_shell[@]}" "$_plugins INVALID || exit 0"
"${ci_shell[@]}" "$_plugins repo/INVALID || exit 0"
"${ci_shell[@]}" "$_plugins custom/INVALID || exit 0"
# Valid
"${ci_shell[@]}" "$_plugins repo/example.bash"
}
function client::dev-tools::run()
{
# Invalid
"${ci_shell[@]}" "$ci_dev_tools run 'hash INVALID' || exit 0"
# Valid
"${ci_shell[@]}" "$ci_dev_tools run 'hash bash'"
}
function client::dev-tools::version()
{
local _types
_types+=("client" "container" "short" "all")
_types+=("client,container,short")
for _type in "${_types[@]}"; do
local _version="$ci_dev_tools version"
# Invalid
"${ci_shell[@]}" "$_version type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_version INVALID=${_type} || exit 0"
# Valid
"${ci_shell[@]}" "$_version type=${_type}"
done
}
function client::dev-tools::update()
{
local -r types=("micro" "tiny" "slim" "default")
# Currently, only 'default' is supported
for _type in "${types[@]}"; do
local _update="dfi dev-tools/${USER}:${_type} update"
# Invalid
"${ci_shell[@]}" "$_update type=${_type}INVALID || exit 0"
"${ci_shell[@]}" "$_update INVALID=${_type} || exit 0"
# Valid
if "${ci_shell[@]}" "$_update type=${_type}"; then
[[ "$_type" != default ]] || continue
fi
done
}
function client::dev-tools::rm()
{
local _image="dev-tools/${USER}:default"
"${ci_shell[@]}" "dfi $_image rm"
docker images -q "$_image" && return $?
# NOTE: don't attempt `dfi` container commands or else image will try to pull/re-build
# Re-build (from cache) for future test cases
client::dev-tools::build
}
function client::dev-tools::license()
{
local _files
_files+=("README.md")
_files+=("client/Dockerfiles/local/dev-tools/Dockerfile")
_files+=("client/docker-finance.yaml")
_files+=("container/.clang-format")
_files+=("container/plugins/root/example/example.cc")
_files+=("container/src/finance/completion.bash")
_files+=("container/src/finance/lib/internal/fetch/fetch.php")
_files+=("container/src/hledger-flow/accounts/coinbase/coinbase-shared.rules")
_files+=("container/src/hledger-flow/accounts/coinbase/template/coinbase/platform/1-in/mockup/2023/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXBTC_transactions.csv")
_files+=("container/src/root/common/utility.hh")
_files+=("container/src/root/macro/rootlogon.C")
for _file in "${_version[@]}"; do
"${ci_shell[@]}" "$ci_dev_tools license file=${_file}"
done
}
function client::dev-tools::linter()
{
local _type
_type+=("bash" "c++" "php")
_type+=("bash,c++,php")
_type+=("all")
for _type in "${_version[@]}"; do
"${ci_shell[@]}" "$ci_dev_tools linter type=${_type}"
done
}
function client::dev-tools::doxygen()
{
local -r _args=("gen" "rm")
for _arg in "${_args[@]}"; do
"${ci_shell[@]}" "$ci_dev_tools doxygen $_arg"
done
}
"$@"

277
.gitea/workflows/dfi.yaml Normal file
View File

@@ -0,0 +1,277 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# NOTE: see https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs for CI setup
name: docker-finance
run-name: ${{ gitea.actor }} ${{ gitea.event_name }} ${{ gitea.ref }} ${{ gitea.repository }}
on:
push:
paths:
- 'client/**'
- 'container/**'
- 'docker-finance.dox'
- '.gitea/**'
- '!.gitea/ISSUE_TEMPLATE/**'
- '!.gitea/PULL_REQUEST_TEMPLATE.yaml'
- '!.gitignore'
- '!.img/**'
- '!CHANGELOG.md'
- '!LICENSE.md'
- '!README.md'
cache:
enable: false
jobs:
all:
runs-on: archlinux_vm
steps:
##
## Host (act_runner)
##
- name: Host preparation (clone)
uses: actions/checkout@v4
# Rationale: in case of failures, cleanup here (instead of later)
- name: Host preparation (cleanup)
run: |
${{ gitea.workspace }}/.gitea/workflows/dfi.bash host::clean
# Rationale: it's preferred to work with DOCKER_FINANCE_CLIENT_REPO pointing
# toward the runner's actual home rather than the job's temporary cache home
- name: Host preparation (workspace)
run: |
mkdir "${HOME}"/docker-finance && cp -aR ${{ gitea.workspace }} "${HOME}"/docker-finance/repo
##
## Client (host)
##
- name: client::install
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::install
##
## Client (finance)
##
- name: client::finance::gen
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::gen
- name: client::finance::edit
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::edit
- name: client::finance::build
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::build
- name: client::finance::backup
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::backup
- name: client::finance::up
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::up
- name: client::finance::stop
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::stop
- name: client::finance::start
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::start
- name: client::finance::down
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::down
- name: client::finance::shell
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::shell
- name: client::finance::exec
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::exec
- name: client::finance::plugins
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::plugins
- name: client::finance::run
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::run
- name: client::finance::version
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::version
- name: client::finance::update
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::update
- name: client::finance::rm
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::finance::rm
##
## Container (finance)
##
- name: container::finance::edit
run: |
CI_DFI_FETCH_MOBULA=${{ secrets.CI_DFI_FETCH_MOBULA }} \
CI_DFI_FETCH_COINGECKO=${{ secrets.CI_DFI_FETCH_COINGECKO }} \
CI_DFI_FETCH_ETHERSCAN=${{ secrets.CI_DFI_FETCH_ETHERSCAN }} \
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::edit
- name: container::finance::fetch
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::fetch
- name: container::finance::import
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::import
- name: container::finance::hledger
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::hledger
- name: container::finance::hledger-ui
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::hledger-ui
- name: container::finance::hledger-vui
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::hledger-vui
- name: container::finance::hledger-web
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::hledger-web
- name: container::finance::meta
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::meta
- name: container::finance::reports
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::reports
- name: container::finance::taxes
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::taxes
- name: container::finance::times
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::times
- name: container::finance::plugins
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::plugins
- name: container::finance::root
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash container::finance::root
##
## Client (dev-tools)
##
- name: client::dev-tools::gen
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::gen
- name: client::dev-tools::edit
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::edit
- name: client::dev-tools::build
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::build
- name: client::dev-tools::backup
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::backup
- name: client::dev-tools::up
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::up
- name: client::dev-tools::stop
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::stop
- name: client::dev-tools::start
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::start
- name: client::dev-tools::down
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::down
- name: client::dev-tools::shell
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::shell
- name: client::dev-tools::exec
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::exec
- name: client::dev-tools::plugins
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::plugins
- name: client::dev-tools::run
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::run
- name: client::dev-tools::version
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::version
- name: client::dev-tools::update
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::update
- name: client::dev-tools::license
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::license
- name: client::dev-tools::linter
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::linter
- name: client::dev-tools::doxygen
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::doxygen
- name: client::dev-tools::rm
run: |
"${HOME}"/docker-finance/repo/.gitea/workflows/dfi.bash client::dev-tools::rm
##
## Host (act_runner)
##
- name: Job status
run: echo "${{ job.status }}"

View File

@@ -18,22 +18,136 @@
# Changelog (`docker-finance`)
## 1.3.0 - 2026-02-27
This release focuses on `dfi` code/usage enhancements, a ROOT.cern (`root`) patch release and **breaking** changes to the `dfi` client-side default layout (filesystem).
Also included are dfi-docs updates: [how to get started](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-get-started.md), categorical [plugins](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-use-it.md#plugins) and a new demo of the [Bitcoin plugin](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-use-it.md#plugins-bitcoin).
### 1.3.0 - Fixes
- Fix `root` plugin code documentation (custom plugin location) ([#302](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/302))
### 1.3.0 - Enhancements
- 🚨**Breaking** Change layout of default client/container paths (environment, bind-mounts) ([#301](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/301)) ([#303](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/303))
* Defaults are now consolidated under a single parent directory
* Basenames are now simply-named to avoid verbosity and confusion
* For smoothest transition:
1. Create a parent umbrella directory called `./docker-finance`
2. Rename (or symlink) your `docker-finance` repository (`DOCKER_FINANCE_CLIENT_REPO`) to `./docker-finance/repo`
3. Rename (or symlink) your `docker-finance.d` directory (`DOCKER_FINANCE_CLIENT_CONF`) to `./docker-finance/conf.d`
4. Rename (or symlink) your `finance-flow` directory (`DOCKER_FINANCE_CLIENT_FLOW`) to `./docker-finance/flow`
- Within your `./docker-finance/flow/profiles` directory, rename all subprofile `docker-finance.d` directories to `conf.d`
6. Rename (or symlink) your custom `plugins` directory (`DOCKER_FINANCE_CLIENT_PLUGINS`) to `./docker-finance/plugins`
7. Rename (or symlink) your `share.d` directory (`DOCKER_FINANCE_CLIENT_SHARED`) to `./docker-finance/share.d`
8. Manually update all `./docker-finance/conf.d` environment files for all platforms/tags to reflect the new client-side locations:
- e.g.; `$EDITOR ./docker-finance/conf.d/client/Linux-x86_64/archlinux/default/env/$(whoami)@$(uname -n)`
9. Manually update your `superscript.bash`; changing `docker-finance.d` to `conf.d` where applicable:
- e.g.; `sed -i 's:/docker-finance.d/:/conf.d/:g' ./docker-finance/conf.d/container/shell/superscript.bash`
10. Manually remove the docker-finance `source` completion line from `~/.bashrc` (or `~/.bash_aliases`)
11. Re-run install:
- i.e.; `./docker-finance/repo/client/install.bash && source ~/.bashrc`
12. *Optional* Re-run `gen type=env` to produce the new container-side bind-mount locations:
- i.e.; `dfi archlinux/${USER}:default gen type=env confirm=no`
13. 🥳 Your new defaults can now be changed and paths moved/renamed as you please: simply update your environment file in `conf.d`:
- i.e.; `dfi archlinux/${USER}:default edit type=env`
- ⚠ If changing the expected repository location, you'll need to manually update the `conf.d` environment file as well as your aliases/source (`~/.bashrc`)
- Allow undesirable characters in variable-text columns for respective hledger-flow accounts, related refactoring ([#297](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/297))
- Add `root` interpreter common exit function and test case, refactor CI workflow ([#298](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/298))
- Silence client's `exec` noise, when not debugging ([#299](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/299))
- Pull tags from remote in client Bitcoin plugin ([#300](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/300))
- Decrease bootstrap wait time for client Tor plugin ([#305](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/305))
- Improve usage help for client/container `plugins` commmand, add help to client `plugins` completion ([#306](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/306))
### 1.3.0 - Updates
- Update all repo-related domain links to gitea.evergreencrypto.co ([#296](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/296))
* You can still find this repository mirrored to gitea.com
- Bump `root` to 6.38.02-1 ([#304](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/304)) ([#307](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/307))
### 1.3.0 - Contributors
- Aaron Fiore
## 1.2.0 - 2026-02-06
This point release focuses on providing a new CI system using [Gitea Actions](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/actions).
Also included are minor `dfi` changes (mostly client-side) and some usability improvements.
> Note: any re-`gen` instructions below will automatically backup respective data to their respective locations.
### 1.2.0 - Features
- New CI using Gitea Actions Workflow and [instructions](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-contribute.md#ci-using-self-hosted-gitea-with-act_runner) on how to self-host Gitea CI for `dfi` development ([#287](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/287)) ([#291](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/291)) ([#292](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/292)) ([#293](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/293))
### 1.2.0 - Fixes
- Minor internal fixes to work better with the new CI ([#281](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/281)) ([#283](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/283)) ([#289](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/289))
- Fix for container's `taxes` command breaking when generating `all` years (`year=all`) ([#279](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/279))
* This bug does *not* affect individual year tax report generation, when given a specific (or default) year
- Fix client ownership of shared path during client generation ([#285](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/285))
* Was previously owned by root instead of `DOCKER_FINANCE_USER`
- Add missing chains to coinomi template ([#288](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/288))
* To utilize these changes: `dfi archlinux/${USER}:default gen type=flow profile=<profile/subprofile> account=coinomi confirm=no`
- Fix client Tor plugin's container inspection ([#292](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/292))
### 1.2.0 - Enhancements
- Minor internal tweaks to work better with the new CI ([#274](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/274)) ([#275](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/275)) ([#276](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/276)) ([#277](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/277)) ([#278](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/278)) ([#280](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/280)) ([#282](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/282))
- Allow quotations when passing root `Pluggable` arguments ([#286](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/286))
> Helps facilitate CLI usage; e.g.,
> ```bash
> $ dfi testprofile/testuser root plugins/repo/bitcoin/bitcoin.cc 'dfi::macro::load(\"repo/test/unit.C\")'
> ```
- Implement retries when bootstrapping client Tor plugin, misc Tor plugin enhancements ([#292](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/292))
### 1.2.0 - Updates
- `dev-tools`: bump `cppcheck`'s standard to c++20 ([#295](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/295))
### 1.2.0 - Refactoring
- Update optional blocks in default custom Arch Linux Dockerfile, move `less` package from custom build to base build ([#284](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/284))
* To utilize these changes: `dfi archlinux/${USER}:default gen type=build confirm=no`
* To update your new config: `dfi archlinux/${USER}:default edit type=build`
- Update mobula assets and update/cleanup comments in default `fetch` config ([#290](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/290))
* To utilize these changes: `dfi archlinux/${USER}:default gen type=flow profile=<profile/subprofile> config=fetch confirm=no`
* To update your new config (in container): `dfi <profile/subprofile> edit type=fetch`
- Add `cppcheck-suppress stlIfStrFind` to root common ([#295](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/295))
### 1.2.0 - Contributors
- Aaron Fiore
## 1.1.1 - 2026-01-15
This patch release supports recent CoinGecko and PHP-CS-Fixer changes and also includes minor `dfi` developer enhancements/refactoring.
### 1.1.1 - Fixes
- Since CoinGecko now returns error 403 without a "descriptive" User-Agent, an agent has been added when fetching prices from CoinGecko ([#269](https://gitea.com/EvergreenCrypto/docker-finance/pulls/269))
- PHP-CS-Fixer's 3.92 series now requires `init` before any `fix`ing or `check`ing ([#270](https://gitea.com/EvergreenCrypto/docker-finance/pulls/270)) ([#272](https://gitea.com/EvergreenCrypto/docker-finance/pulls/272))
- Since CoinGecko now returns error 403 without a "descriptive" User-Agent, an agent has been added when fetching prices from CoinGecko ([#269](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/269))
- PHP-CS-Fixer's 3.92 series now requires `init` before any `fix`ing or `check`ing ([#270](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/270)) ([#272](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/272))
### 1.1.1 - Enhancements
- Add `API_VERSION` to `fetch`'s PHP environment map ([#269](https://gitea.com/EvergreenCrypto/docker-finance/pulls/269))
- Add `API_VERSION` to `fetch`'s PHP environment map ([#269](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/269))
### 1.1.1 - Refactoring
- Minor dev-tools' `lib_linter` refactoring ([#271](https://gitea.com/EvergreenCrypto/docker-finance/pulls/271)) ([#272](https://gitea.com/EvergreenCrypto/docker-finance/pulls/272))
- Minor dev-tools' `lib_linter` refactoring ([#271](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/271)) ([#272](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/272))
### 1.1.1 - Contributors
@@ -49,52 +163,52 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
> For this release, code fixes that are related to new `root` additions are included in the below Features category
- Remove comma(s) from hledger-flow's Discover credit subaccount description ([#259](https://gitea.com/EvergreenCrypto/docker-finance/pulls/259))
- Remove comma(s) from hledger-flow's Discover credit subaccount description ([#259](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/259))
* Fixes column processing when extra comma(s) are present
- Update deadlinks in Gitea pull request template ([#267](https://gitea.com/EvergreenCrypto/docker-finance/pulls/267))
- Update deadlinks in Gitea pull request template ([#267](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/267))
### 1.1.0 - Features
- New ROOT.cern image/package with C++20 support 🎉, related `dfi` migrating and refactoring ([#237](https://gitea.com/EvergreenCrypto/docker-finance/pulls/237)) ([#238](https://gitea.com/EvergreenCrypto/docker-finance/pulls/238)) ([#240](https://gitea.com/EvergreenCrypto/docker-finance/pulls/240)) ([#247](https://gitea.com/EvergreenCrypto/docker-finance/pulls/247)) ([#248](https://gitea.com/EvergreenCrypto/docker-finance/pulls/248)) ([#251](https://gitea.com/EvergreenCrypto/docker-finance/pulls/251)) ([#255](https://gitea.com/EvergreenCrypto/docker-finance/pulls/255)) ([#257](https://gitea.com/EvergreenCrypto/docker-finance/pulls/257)) ([#262](https://gitea.com/EvergreenCrypto/docker-finance/pulls/262)) ([#265](https://gitea.com/EvergreenCrypto/docker-finance/pulls/265))
- New ROOT.cern image/package with C++20 support 🎉, related `dfi` migrating and refactoring ([#237](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/237)) ([#238](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/238)) ([#240](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/240)) ([#247](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/247)) ([#248](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/248)) ([#251](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/251)) ([#255](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/255)) ([#257](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/257)) ([#262](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/262)) ([#265](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/265))
* The Arch Linux ROOT.cern package, be default, only supports up to C++17. As a result, a new `evergreencrypto/root` Docker image was created and is now maintained to provide an optimized C++20 package
- New `dfi` Pluggable API framework for `root` plugins and macros; auto-(un)load'ing, enhanced `common` system, related refactoring/deprecations and additional tests ([#241](https://gitea.com/EvergreenCrypto/docker-finance/pulls/241)) ([#243](https://gitea.com/EvergreenCrypto/docker-finance/pulls/243)) ([#244](https://gitea.com/EvergreenCrypto/docker-finance/pulls/244)) ([#245](https://gitea.com/EvergreenCrypto/docker-finance/pulls/245)) ([#249](https://gitea.com/EvergreenCrypto/docker-finance/pulls/249)) ([#252](https://gitea.com/EvergreenCrypto/docker-finance/pulls/252)) ([#253](https://gitea.com/EvergreenCrypto/docker-finance/pulls/253)) ([#256](https://gitea.com/EvergreenCrypto/docker-finance/pulls/256)) ([#258](https://gitea.com/EvergreenCrypto/docker-finance/pulls/258)) ([#261](https://gitea.com/EvergreenCrypto/docker-finance/pulls/261)) ([#263](https://gitea.com/EvergreenCrypto/docker-finance/pulls/263)) ([#264](https://gitea.com/EvergreenCrypto/docker-finance/pulls/264))
- New `dfi` Pluggable API framework for `root` plugins and macros; auto-(un)load'ing, enhanced `common` system, related refactoring/deprecations and additional tests ([#241](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/241)) ([#243](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/243)) ([#244](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/244)) ([#245](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/245)) ([#249](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/249)) ([#252](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/252)) ([#253](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/253)) ([#256](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/256)) ([#258](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/258)) ([#261](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/261)) ([#263](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/263)) ([#264](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/264))
* Container's usage help: `dfi <profile/subprofile> root help`
* Doxygen: `dfi dev-tools/${USER}:default doxygen gen`
* Repo examples: [plugins](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root) and [macros](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/src/root/macro)
* Repo examples: [plugins](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root) and [macros](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/src/root/macro)
- ⚠️ Though not recommended, to use the previous method of loading plugins/macros, continue to use the `dfi::common` file loader instead
- New ₿itcoin plugin; related `dfi` API additions and tests ([#254](https://gitea.com/EvergreenCrypto/docker-finance/pulls/254)) ([#261](https://gitea.com/EvergreenCrypto/docker-finance/pulls/261)) ([#263](https://gitea.com/EvergreenCrypto/docker-finance/pulls/263))
* Client's (host's) [plugin](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/client/plugins/docker/bitcoin.bash): `dfi archlinux/${USER}:default plugins repo/bitcoin.bash`
- New ₿itcoin plugin; related `dfi` API additions and tests ([#254](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/254)) ([#261](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/261)) ([#263](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/263))
* Client's (host's) [plugin](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/client/plugins/docker/bitcoin.bash): `dfi archlinux/${USER}:default plugins repo/bitcoin.bash`
- ⚠️ To use the client's plugin, you **MUST** run the following at least once:
* Re-`gen` build file: `dfi archlinux/${USER}:default gen type=build confirm=no`
* Re-`edit` build file: `dfi archlinux/${USER}:default edit type=build` (and then uncomment dependencies)
* Re-`build` image: `dfi archlinux/${USER}:default build type=default` (or use the `update` command)
* Container's [plugin](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root/bitcoin/bitcoin.cc) can be loaded from the command line or from within interpreter:
* Container's [plugin](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root/bitcoin/bitcoin.cc) can be loaded from the command line or from within interpreter:
- Command line: `dfi <profile/subprofile> root plugins/repo/bitcoin/bitcoin.cc`
- Interpreter: `dfi::plugin::load("repo/bitcoin/bitcoin.cc")`
* See [important notes](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/client/plugins/docker/bitcoin.bash#L21-L59) regarding the client/container relationship
- NOTE: all symbols in libbitcoinkernel.so are available but you'll need to load respective headers as needed (e.g., [common loader](https://gitea.com/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root/bitcoin/bitcoin.cc#L80))
* See [important notes](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/client/plugins/docker/bitcoin.bash#L21-L59) regarding the client/container relationship
- NOTE: all symbols in libbitcoinkernel.so are available but you'll need to load respective headers as needed (e.g., [common loader](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/commit/14df4c94e05fce9b557a8c828e384d4691303310/container/plugins/root/bitcoin/bitcoin.cc#L80))
### 1.1.0 - Enhancements
> For this release, code enhancements related to `root` are included in the above Features category
- Add `exec` wrapper to client ([#246](https://gitea.com/EvergreenCrypto/docker-finance/pulls/246))
- Add `exec` wrapper to client ([#246](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/246))
### 1.1.0 - Updates
> For this release, package updates related to `root` are included in the above Features category
- Bump `hledger` to 1.51.2 ([#242](https://gitea.com/EvergreenCrypto/docker-finance/pulls/242)) ([#250](https://gitea.com/EvergreenCrypto/docker-finance/pulls/250)) ([#260](https://gitea.com/EvergreenCrypto/docker-finance/pulls/260))
- Bump `hledger-flow` to v0.16.2 ([#257](https://gitea.com/EvergreenCrypto/docker-finance/pulls/257))
- Bump `hledger` to 1.51.2 ([#242](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/242)) ([#250](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/250)) ([#260](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/260))
- Bump `hledger-flow` to v0.16.2 ([#257](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/257))
### 1.1.0 - Refactoring
> For this release, code refactoring related to `root` is included in the above Features category
- Use Docker multi-stage for `hledger-suite` and `root` images ([#250](https://gitea.com/EvergreenCrypto/docker-finance/pulls/250)) ([#251](https://gitea.com/EvergreenCrypto/docker-finance/pulls/251))
- Use Docker multi-stage for `hledger-suite` and `root` images ([#250](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/250)) ([#251](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/251))
### 1.1.0 - Contributors
@@ -106,61 +220,61 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
### 1.0.0 - Fixes
- client: `linter`: fix finding .clang-format ([#219](https://gitea.com/EvergreenCrypto/docker-finance/pulls/219))
- container: `fetch`: fix wording to reflect impl ([#212](https://gitea.com/EvergreenCrypto/docker-finance/pulls/212))
- container: `taxes`: fixes for 'all' years arg parsing and printing, don't attempt to patch non-existent taxable events ([#230](https://gitea.com/EvergreenCrypto/docker-finance/pulls/230))
- ⚠️ container: hledger-flow: electrum: add lightning, backwards compat ([#227](https://gitea.com/EvergreenCrypto/docker-finance/pulls/227))
* electrum lightning support is a WIP and, as a result, so is the support here (see [#233](https://gitea.com/EvergreenCrypto/docker-finance/issues/233))
- container: plugins: `root`: fix example3()'s shell ([#229](https://gitea.com/EvergreenCrypto/docker-finance/pulls/229))
- client: `linter`: fix finding .clang-format ([#219](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/219))
- container: `fetch`: fix wording to reflect impl ([#212](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/212))
- container: `taxes`: fixes for 'all' years arg parsing and printing, don't attempt to patch non-existent taxable events ([#230](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/230))
- ⚠️ container: hledger-flow: electrum: add lightning, backwards compat ([#227](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/227))
* electrum lightning support is a WIP and, as a result, so is the support here (see [#233](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/issues/233))
- container: plugins: `root`: fix example3()'s shell ([#229](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/229))
### 1.0.0 - Features
- client: add `update` feature ([#225](https://gitea.com/EvergreenCrypto/docker-finance/pulls/225))
- client: add `update` feature ([#225](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/225))
* Update your `dfi` instance with the `update` command (instead of `rm` -> system prune -> `build`)
- container: add lib_root impl (macro/plugin support), update completion and usage help ([#215](https://gitea.com/EvergreenCrypto/docker-finance/pulls/215))
- container: add lib_root impl (macro/plugin support), update completion and usage help ([#215](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/215))
* dfi's `root` now supports shell loading (and running) of macros/plugins
### 1.0.0 - Enhancements
- ⚠️**Potentially Breaking**: container: root: macro: Hash/Random: change output to CSV format ([#217](https://gitea.com/EvergreenCrypto/docker-finance/pulls/217))
- ⚠️**Potentially Breaking**: container: root: macro: Hash/Random: change output to CSV format ([#217](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/217))
* Any end-user expectations (*custom* plugins, etc.) should be adjusted, if needed
- client: `linter`: allow *custom* C++ plugins to also be linted/formatted ([#211](https://gitea.com/EvergreenCrypto/docker-finance/pulls/211))
- container: `taxes`/`reports`: optimize writes by forking ([#221](https://gitea.com/EvergreenCrypto/docker-finance/pulls/221)) ([#223](https://gitea.com/EvergreenCrypto/docker-finance/pulls/223))
- client: `linter`: allow *custom* C++ plugins to also be linted/formatted ([#211](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/211))
- container: `taxes`/`reports`: optimize writes by forking ([#221](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/221)) ([#223](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/223))
* Decreases real time in multicore container environments
- 🚨container: hledger-flow: ethereum-based: compound: add internal swapping when supplying/withdrawing ([#228](https://gitea.com/EvergreenCrypto/docker-finance/pulls/228))
- 🚨container: hledger-flow: ethereum-based: compound: add internal swapping when supplying/withdrawing ([#228](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/228))
* **MUST** re-`import` from oldest applicable year
* **MUST** re-`taxes` for all applicable years
- 🚨container: hledger-flow: finish uniform fiat subaccounts ([#213](https://gitea.com/EvergreenCrypto/docker-finance/pulls/213))
- 🚨container: hledger-flow: finish uniform fiat subaccounts ([#213](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/213))
* **MUST** adjust custom rules/journals as needed
* **MUST** re-`import` from oldest applicable year
* **MUST** re-`report` for all applicable years
- 🚨container: hledger-flow: paypal/paypal-business: add expenses description subaccount ([#214](https://gitea.com/EvergreenCrypto/docker-finance/pulls/214))
- 🚨container: hledger-flow: paypal/paypal-business: add expenses description subaccount ([#214](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/214))
* **MUST** re-`import` from oldest applicable year
* **MUST** re-`report` for all applicable years
- 🚨container: hledger-flow: vultr: add credits support ([#226](https://gitea.com/EvergreenCrypto/docker-finance/pulls/226))
- 🚨container: hledger-flow: vultr: add credits support ([#226](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/226))
* **MUST** re-`import` from oldest applicable year
* **MUST** re-`report` for all applicable years
### 1.0.0 - Updates
- client/container: usage help updates ([#231](https://gitea.com/EvergreenCrypto/docker-finance/pulls/231))
- client: Dockerfiles: remote: hledger-suite: bump to latest `hledger`/`hledger-flow`/`hledger-iadd` ([#216](https://gitea.com/EvergreenCrypto/docker-finance/pulls/216)) ([#220](https://gitea.com/EvergreenCrypto/docker-finance/pulls/220))
- client/container: usage help updates ([#231](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/231))
- client: Dockerfiles: remote: hledger-suite: bump to latest `hledger`/`hledger-flow`/`hledger-iadd` ([#216](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/216)) ([#220](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/220))
* Also updates hledger-suite Dockerfile build process
- repo: gitea: template: update bug template ([#234](https://gitea.com/EvergreenCrypto/docker-finance/pulls/234))
- repo: migrate all docs and related assets to 'dfi-docs' repository, update README ([#232](https://gitea.com/EvergreenCrypto/docker-finance/pulls/232))
* All non-code documentation has been moved to the [dfi-docs](https://gitea.com/EvergreenCrypto/dfi-docs) repository
- repo: remove deprecated donation funding images ([#224](https://gitea.com/EvergreenCrypto/docker-finance/pulls/224))
- repo: gitea: template: update bug template ([#234](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/234))
- repo: migrate all docs and related assets to 'dfi-docs' repository, update README ([#232](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/232))
* All non-code documentation has been moved to the [dfi-docs](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs) repository
- repo: remove deprecated donation funding images ([#224](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/224))
### 1.0.0 - Refactoring
- ⚠️**Potentially Breaking**: client/container: migrate from `xsv` to `xan` ([#222](https://gitea.com/EvergreenCrypto/docker-finance/pulls/222))
- ⚠️**Potentially Breaking**: client/container: migrate from `xsv` to `xan` ([#222](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/222))
* Any end-user *custom* plugins that rely on `xsv` should use `xan` instead
- To continue using `xsv`, add `xsv` to your build: `dfi <platform/user:tag> edit type=build`
- ⚠️**Potentially Breaking**: container: php/c++: `dfi` namespace refactor ([#210](https://gitea.com/EvergreenCrypto/docker-finance/pulls/210))
- ⚠️**Potentially Breaking**: container: php/c++: `dfi` namespace refactor ([#210](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/210))
* Any end-user *custom* plugin namespaces should be adjusted, if needed
* Any Doxygen used should be cleaned and regenerated with the `dev-tools` image, if needed
- container: hledger-flow: add explicit amount4 to applicable rules ([#218](https://gitea.com/EvergreenCrypto/docker-finance/pulls/218))
- container: php general refactoring ([#208](https://gitea.com/EvergreenCrypto/docker-finance/pulls/208)) ([#209](https://gitea.com/EvergreenCrypto/docker-finance/pulls/209))
- container: hledger-flow: add explicit amount4 to applicable rules ([#218](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/218))
- container: php general refactoring ([#208](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/208)) ([#209](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/209))
* Removes deprecations (since PHP 8.4) and linter errors
### 1.0.0 - Contributors
@@ -171,41 +285,41 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
⚠️ **Breaking changes for this release candidate** ⚠️
- **Breaking**: support non-alpha characters (currency) for all applicable accounts ([#202](https://gitea.com/EvergreenCrypto/docker-finance/pulls/202)) ([#205](https://gitea.com/EvergreenCrypto/docker-finance/pulls/205))
- **Breaking**: support non-alpha characters (currency) for all applicable accounts ([#202](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/202)) ([#205](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/205))
* gemini: the 1-in filename for 1INCH trades **MUST** be renamed from "oneinchXXX-Trades.csv" to "1inchXXX-Trades.csv" (where XXX is the counter pair)
- All applicable years in gemini account's 2-preprocessed and 3-journal **MUST** be deleted and re-`import`ed
* **MUST** re-`fetch` respective prices for applicable years
* **MUST** re-run `taxes` for applicable years
- **Breaking**: ethereum-based: support Etherscan V2, add more L2 chains, add/update L2 mockups, add/update L2 spam rules, support non-alpha chars (currency) ([#201](https://gitea.com/EvergreenCrypto/docker-finance/pulls/201))
* **MUST** use new `fetch` config API format and API key (see [#201](https://gitea.com/EvergreenCrypto/docker-finance/pulls/201))
- **Breaking**: ethereum-based: support Etherscan V2, add more L2 chains, add/update L2 mockups, add/update L2 spam rules, support non-alpha chars (currency) ([#201](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/201))
* **MUST** use new `fetch` config API format and API key (see [#201](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/201))
- **MUST** perform subsequent manual adjustment (update any API keys)
* If developing, **MUST** `gen`/re-`gen` the mockups
- **Breaking**: btcpayserver: support "Legacy Invoice Export" plugin, update "Wallets" impl, update mockups ([#203](https://gitea.com/EvergreenCrypto/docker-finance/pulls/203))
- **Breaking**: btcpayserver: support "Legacy Invoice Export" plugin, update "Wallets" impl, update mockups ([#203](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/203))
* As of BTCPayServer v2.2.0, **MUST** install the "Legacy Invoice Export" plugin
- **MUST** export legacy and wallets reports and re-`import` for all applicable years
* If developing, **MUST** re-`gen` the mockup
- **Breaking** paypal: support latest fiat header, update fiat mockup ([#199](https://gitea.com/EvergreenCrypto/docker-finance/pulls/199))
- **Breaking** paypal: support latest fiat header, update fiat mockup ([#199](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/199))
* Adds 'fees' subaccount and new tags from the additional columns
* **MUST** run client-side `gen` for paypal account
- **MUST** re-`import` all applicable years
* If developing, **MUST** re-`gen` the mockup
- paypal-business: update mockup ([#200](https://gitea.com/EvergreenCrypto/docker-finance/pulls/200))
- paypal-business: update mockup ([#200](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/200))
- Fix/enhance client usage handling ([#207](https://gitea.com/EvergreenCrypto/docker-finance/pulls/207))
- Fix/enhance client usage handling ([#207](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/207))
- Fix client completion for when Docker is not found ([#192](https://gitea.com/EvergreenCrypto/docker-finance/pulls/192))
- Fix client completion for when Docker is not found ([#192](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/192))
- Fix permission denied for visidata (change visidata default dir) ([#198](https://gitea.com/EvergreenCrypto/docker-finance/pulls/198))
- Fix permission denied for visidata (change visidata default dir) ([#198](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/198))
- Fix description-like information with '%' character which breaks import in some cases ([#204](https://gitea.com/EvergreenCrypto/docker-finance/pulls/204))
- Fix description-like information with '%' character which breaks import in some cases ([#204](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/204))
- Add more `hledger` commands to container completion ([#194](https://gitea.com/EvergreenCrypto/docker-finance/pulls/194))
- Add more `hledger` commands to container completion ([#194](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/194))
- Bump `hledger` to latest releases ([#193](https://gitea.com/EvergreenCrypto/docker-finance/pulls/193)) ([#195](https://gitea.com/EvergreenCrypto/docker-finance/pulls/195)) ([#196](https://gitea.com/EvergreenCrypto/docker-finance/pulls/196)) ([#197](https://gitea.com/EvergreenCrypto/docker-finance/pulls/197))
- Bump `hledger` to latest releases ([#193](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/193)) ([#195](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/195)) ([#196](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/196)) ([#197](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/197))
---
@@ -229,7 +343,7 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
🚨 For BTCPay Server account:
- ❗**MUST** export only v2 reports
* See ([#181](https://gitea.com/EvergreenCrypto/docker-finance/pulls/181)) for details
* See ([#181](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/181)) for details
- ❗**MUST** re-run `import` command
* Run `import` starting from oldest applicable year
@@ -240,7 +354,7 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
🚨 For Coinbase account:
- ❗**MUST** re-run `edit type=fetch` command
* Update your CDP key (legacy key support has been [removed](https://gitea.com/EvergreenCrypto/docker-finance/commit/ca31fef052819e2c118f57451f64ca94bad01d2b))
* Update your CDP key (legacy key support has been [removed](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/commit/ca31fef052819e2c118f57451f64ca94bad01d2b))
---
@@ -254,53 +368,53 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
##### *Dockerfiles*
- hledger-suite ([#184](https://gitea.com/EvergreenCrypto/docker-finance/pulls/184)) ([#185](https://gitea.com/EvergreenCrypto/docker-finance/pulls/185))
- hledger-suite ([#184](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/184)) ([#185](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/185))
* Bump `hledger` to 1.42.1
##### *docker-finance.d (configurations)*
- Update Coinbase CDP key, remove unused YAML keys ([#176](https://gitea.com/EvergreenCrypto/docker-finance/pulls/176)) ([#177](https://gitea.com/EvergreenCrypto/docker-finance/pulls/177))
- Update Coinbase CDP key, remove unused YAML keys ([#176](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/176)) ([#177](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/177))
##### *src/docker*
- Only allocate TTY when needed (with `run` command) ([#187](https://gitea.com/EvergreenCrypto/docker-finance/pulls/187))
- Only allocate TTY when needed (with `run` command) ([#187](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/187))
#### Container
##### *src/finance*
- `fetch`
* Isolate given year when fetching prices with mobula API ([#188](https://gitea.com/EvergreenCrypto/docker-finance/pulls/188))
* Isolate given year when fetching prices with mobula API ([#188](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/188))
### ☀️ Features / Enhancements
#### Repo
- Add prelim `dfi` logo ([#189](https://gitea.com/EvergreenCrypto/docker-finance/pulls/189))
- Add prelim `dfi` logo ([#189](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/189))
#### Container
##### *src/finance*
- `lib_taxes`
* Optimize record printing, add checks and logging ([#179](https://gitea.com/EvergreenCrypto/docker-finance/pulls/179))
* Optimize record printing, add checks and logging ([#179](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/179))
##### *src/hledger-flow*
- `lib_preprocess`
* Allow testing of single / multiple columns ([#180](https://gitea.com/EvergreenCrypto/docker-finance/pulls/180/))
* Allow testing of single / multiple columns ([#180](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/180/))
- BTCPay Server
- Add prelim support for v2 reports ([#181](https://gitea.com/EvergreenCrypto/docker-finance/pulls/181))
- Add `taxed_as` INCOME tag, add local timezone support ([#183](https://gitea.com/EvergreenCrypto/docker-finance/pulls/183))
- Add prelim support for v2 reports ([#181](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/181))
- Add `taxed_as` INCOME tag, add local timezone support ([#183](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/183))
- Ethereum-based
* Add COMP rewards ([#178](https://gitea.com/EvergreenCrypto/docker-finance/pulls/178))
* Add DeFi swapper tag ([#182](https://gitea.com/EvergreenCrypto/docker-finance/pulls/182))
* Add to Ethereum spam rules ([#186](https://gitea.com/EvergreenCrypto/docker-finance/pulls/186))
* Add COMP rewards ([#178](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/178))
* Add DeFi swapper tag ([#182](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/182))
* Add to Ethereum spam rules ([#186](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/186))
- Ledger
* Skip COMP token (handled by ethereum-based `fetch`) ([#178](https://gitea.com/EvergreenCrypto/docker-finance/pulls/178))
* Skip COMP token (handled by ethereum-based `fetch`) ([#178](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/178))
### 🌴 Misc / Other
@@ -309,12 +423,12 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
##### *src/finance*
- `lib_taxes`
* Some refactoring ([#179](https://gitea.com/EvergreenCrypto/docker-finance/pulls/179))
* Some refactoring ([#179](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/179))
##### *src/hledger-flow*
- `lib_preprocess`
* Symlink to finance's `lib_utils` ([#180](https://gitea.com/EvergreenCrypto/docker-finance/pulls/180/))
* Symlink to finance's `lib_utils` ([#180](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/180/))
## 1.0.0-rc.1 - 2025-01-23
@@ -371,62 +485,62 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
##### *README*
- Fix 'dev-tools' build instructions, misc updates ([#171](https://gitea.com/EvergreenCrypto/docker-finance/pulls/171))
- Fix 'dev-tools' build instructions, misc updates ([#171](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/171))
#### Client
##### *Dockerfiles*
- Version updates for hledger-suite image ([#156](https://gitea.com/EvergreenCrypto/docker-finance/pulls/156))
- Version updates for hledger-suite image ([#156](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/156))
* Bump `hledger` to 1.41
* Change resolver for `hledger-iadd`
##### *docker-finance.d (configurations)*
- Add Coinomi example to fetch ([#170](https://gitea.com/EvergreenCrypto/docker-finance/pulls/170))
- Add Coinomi example to fetch ([#170](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/170))
##### *src/docker*
- Fix typo in usage help ([#158](https://gitea.com/EvergreenCrypto/docker-finance/pulls/158))
- Fix typo in usage help ([#158](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/158))
#### Container
##### *src/finance*
- `lib_hledger`
* Remove `-w` arg to `hledger-ui` ([#157](https://gitea.com/EvergreenCrypto/docker-finance/pulls/157))
* Remove `-w` arg to `hledger-ui` ([#157](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/157))
- `lib_fetch`
* Fix price parsing ([#130](https://gitea.com/EvergreenCrypto/docker-finance/pulls/130))
* Fix Tor plugin (proxychains) check ([#142](https://gitea.com/EvergreenCrypto/docker-finance/pulls/142))
* Fix price parsing ([#130](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/130))
* Fix Tor plugin (proxychains) check ([#142](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/142))
##### *src/hledger-flow*
- BlockFi / Ledger / Trezor
* Fix fees subaccount ordering ([#165](https://gitea.com/EvergreenCrypto/docker-finance/pulls/165))
* Fix fees subaccount ordering ([#165](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/165))
- Electrum
* Fix calculating 'No Data' ([#138](https://gitea.com/EvergreenCrypto/docker-finance/pulls/138))
* Fix calculating 'No Data' ([#138](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/138))
- Capital One (bank)
* Fix direction ([#132](https://gitea.com/EvergreenCrypto/docker-finance/pulls/132))
* Fix direction ([#132](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/132))
- Coinbase
* Fix/update pagination ([#172](https://gitea.com/EvergreenCrypto/docker-finance/pulls/172)) ([#173](https://gitea.com/EvergreenCrypto/docker-finance/pulls/173))
* Fix/update pagination ([#172](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/172)) ([#173](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/173))
- Coinbase Pro
* Fix default account2 for sells ([#166](https://gitea.com/EvergreenCrypto/docker-finance/pulls/166))
* Fix default account2 for sells ([#166](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/166))
##### *src/finance* | *src/hledger-flow*
- **Breaking**: Add compliance for IRS Rev. Proc. 2024-28 ([#163](https://gitea.com/EvergreenCrypto/docker-finance/pulls/163)) ([#174](https://gitea.com/EvergreenCrypto/docker-finance/pulls/174))
- **Breaking**: Add compliance for IRS Rev. Proc. 2024-28 ([#163](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/163)) ([#174](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/174))
* Creates per-wallet / per-account compliance for IRS Rev. Proc. 2024-28
* New obfuscated keymap now creates a unique indentifier per-wallet / per-account
* Removes support for anonymized ("universal pool") reports
#### Client/Container
- Remove `fetch` support for defunct exchanges/services ([#169](https://gitea.com/EvergreenCrypto/docker-finance/pulls/169))
- Remove `fetch` support for defunct exchanges/services ([#169](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/169))
* Bittrex
* Celsius
* Coinbase Pro
@@ -437,59 +551,59 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
##### *README*
- Add support for NonFi, fix TradFi anchor tag ([#141](https://gitea.com/EvergreenCrypto/docker-finance/pulls/141))
- Add docker-finance logo, update README ([#159](https://gitea.com/EvergreenCrypto/docker-finance/pulls/159))
- Add support for NonFi, fix TradFi anchor tag ([#141](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/141))
- Add docker-finance logo, update README ([#159](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/159))
#### Client
##### *docker-finance.d (configurations)*
- Add filters for .in files to produce less cluttered default configs ([#147](https://gitea.com/EvergreenCrypto/docker-finance/pulls/147))
- Rewrite profile default subscript ([#148](https://gitea.com/EvergreenCrypto/docker-finance/pulls/148))
- Add filters for .in files to produce less cluttered default configs ([#147](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/147))
- Rewrite profile default subscript ([#148](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/148))
##### *src/docker*
- Enable linting of client-side (host) plugins ([#136](https://gitea.com/EvergreenCrypto/docker-finance/pulls/136))
- Enable linting of client-side (host) plugins ([#136](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/136))
#### Container
##### *src/finance*
- `completion`
* Add `hledger` commands ([#139](https://gitea.com/EvergreenCrypto/docker-finance/pulls/139))
* Add `hledger` commands ([#139](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/139))
- `edit`
* Add 'subscript' option ([#146](https://gitea.com/EvergreenCrypto/docker-finance/pulls/146))
* Add `hledger add` command ([#152](https://gitea.com/EvergreenCrypto/docker-finance/pulls/152))
* Add 'subscript' option ([#146](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/146))
* Add `hledger add` command ([#152](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/152))
- `fetch`
* Add debug logging to Gemini ([#153](https://gitea.com/EvergreenCrypto/docker-finance/pulls/153))
* Add debug logging to Gemini ([#153](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/153))
- `plugins`
* finance: `timew_to_timeclock`: print all tags ([#133](https://gitea.com/EvergreenCrypto/docker-finance/pulls/133))
* finance: `timew_to_timeclock`: print all tags ([#133](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/133))
##### *src/hledger-flow*
- Algorand
* Add to Governance Rewards ([#135](https://gitea.com/EvergreenCrypto/docker-finance/pulls/135))
* Add to spam rules ([#161](https://gitea.com/EvergreenCrypto/docker-finance/pulls/161))
* Add to Governance Rewards ([#135](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/135))
* Add to spam rules ([#161](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/161))
- Electrum
* Use transaction label for tax memo ([#168](https://gitea.com/EvergreenCrypto/docker-finance/pulls/168))
* Use transaction label for tax memo ([#168](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/168))
- ethereum-based
* Add to Ethereum spam rules ([#162](https://gitea.com/EvergreenCrypto/docker-finance/pulls/162))
* Add to Polygon spam rules ([#167](https://gitea.com/EvergreenCrypto/docker-finance/pulls/167))
* Add to Ethereum spam rules ([#162](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/162))
* Add to Polygon spam rules ([#167](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/167))
- Ledger
* Add more compound tokens ([#164](https://gitea.com/EvergreenCrypto/docker-finance/pulls/164))
* Add more compound tokens ([#164](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/164))
- Vultr
* Add Vultr support ([#140](https://gitea.com/EvergreenCrypto/docker-finance/pulls/140)) ([#151](https://gitea.com/EvergreenCrypto/docker-finance/pulls/151))
* Add Vultr support ([#140](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/140)) ([#151](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/151))
#### Client / Container
- **Breaking**: Complete build overhaul, build optimizations ([#143](https://gitea.com/EvergreenCrypto/docker-finance/pulls/143))
- **Breaking**: Complete build overhaul, build optimizations ([#143](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/143))
* Creates a separation of concerns for 'local' and 'remote' building
* Adds remote image 'hledger-suite'
- Provides the latest versions of all `hledger` related binaries
@@ -510,7 +624,7 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
- e.g., 'default' Arch Linux image size is ~50% smaller
* Cleanup and clarify default generated custom Dockerfiles
- **Breaking**: Complete `gen` overhaul, `gen` improvements ([#144](https://gitea.com/EvergreenCrypto/docker-finance/commit/77351d54e118b84d93779fad5d9a5963fddef940))
- **Breaking**: Complete `gen` overhaul, `gen` improvements ([#144](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/commit/77351d54e118b84d93779fad5d9a5963fddef940))
* New `gen` arguments (see `gen help`)
* `subprofile.bash` is now `subscript.bash`
- Changes filename within superscript source
@@ -518,15 +632,15 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
- Changes actual filename within subprofile's docker-finance.d
* **MUST** manually rename the subprofile's script file from `subprofile.bash` to `subscript.bash`
- **Breaking**: Implement debug log-levels ([#149](https://gitea.com/EvergreenCrypto/docker-finance/pulls/149))
- **Breaking**: Implement debug log-levels ([#149](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/149))
- `completion`
* `plugins` enhancements ([#155](https://gitea.com/EvergreenCrypto/docker-finance/pulls/155))
* `plugins` enhancements ([#155](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/155))
- `plugins`
* Allow path depth when loading plugins ([#134](https://gitea.com/EvergreenCrypto/docker-finance/pulls/134))
* Allow path depth when loading plugins ([#134](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/134))
- Refactoring/enhancements related to `hledger` ([#145](https://gitea.com/EvergreenCrypto/docker-finance/pulls/145))
- Refactoring/enhancements related to `hledger` ([#145](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/145))
### 🌴 Misc / Other
@@ -534,27 +648,27 @@ Also included are minor changes; minor fixes, dependency bumps and refactoring (
##### *Dockerfiles*
- Optimize by moving useradd ([#128](https://gitea.com/EvergreenCrypto/docker-finance/pulls/128))
- Optimize by moving useradd ([#128](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/128))
##### *docker-finance.d (configurations)*
- Remove base cmd from subscript ([#150](https://gitea.com/EvergreenCrypto/docker-finance/pulls/150))
- Remove base cmd from subscript ([#150](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/150))
##### *src/docker*
- `lib_gen`
* Refactor profile variables ([#154](https://gitea.com/EvergreenCrypto/docker-finance/pulls/154))
* Refactor profile variables ([#154](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/154))
- `lib_linter`
* Return function on compose down ([#131](https://gitea.com/EvergreenCrypto/docker-finance/pulls/131))
* Return function on compose down ([#131](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/131))
#### Container
- Run linter ([#137](https://gitea.com/EvergreenCrypto/docker-finance/pulls/137))
- Run linter ([#137](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/137))
#### Client/Container
- Refactor global basename ([#160](https://gitea.com/EvergreenCrypto/docker-finance/pulls/160))
- Refactor global basename ([#160](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/160))
## 1.0.0-beta.3 - 2024-08-20
@@ -609,7 +723,7 @@ Aside from changes above, there are no breaking changes for container.
❗ For accounts:
- 🚨 **SHOULD** re-run `import` command
* Applicable only to Capital One (bank) account ([#124](https://gitea.com/EvergreenCrypto/docker-finance/pulls/124))
* Applicable only to Capital One (bank) account ([#124](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/124))
---
@@ -621,39 +735,39 @@ Aside from changes above, there are no breaking changes for container.
#### Repo
- CHANGELOG.md ([#126](https://gitea.com/EvergreenCrypto/docker-finance/pulls/126))
- CHANGELOG.md ([#126](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/126))
* Add v1.0.0-beta.3
- README.md ([`cab7551`](https://gitea.com/EvergreenCrypto/docker-finance/commit/cab7551cbb343e1b46eaba7e76c6321e1061baf0)) ([`d86da4b`](https://gitea.com/EvergreenCrypto/docker-finance/commit/d86da4b4d5e3734a9685a29e9e94893b457d5b1a)) ([`3bfa39d`](https://gitea.com/EvergreenCrypto/docker-finance/commit/3bfa39de87eebc6c7fa9dca7d80a0f5095eba0ca)) ([#119](https://gitea.com/EvergreenCrypto/docker-finance/pulls/119))
- README.md ([`cab7551`](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/commit/cab7551cbb343e1b46eaba7e76c6321e1061baf0)) ([`d86da4b`](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/commit/d86da4b4d5e3734a9685a29e9e94893b457d5b1a)) ([`3bfa39d`](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/commit/3bfa39de87eebc6c7fa9dca7d80a0f5095eba0ca)) ([#119](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/119))
* Update to reflect latest impl
#### Client
- Bump manifest version to v1.0.0-beta.3 ([#127](https://gitea.com/EvergreenCrypto/docker-finance/pulls/127))
- Change environment defaults for `DOCKER_FINANCE_*_FLOW` ([#114](https://gitea.com/EvergreenCrypto/docker-finance/pulls/114))
- Dockerfiles updates ([#121](https://gitea.com/EvergreenCrypto/docker-finance/pulls/121)) ([#123](https://gitea.com/EvergreenCrypto/docker-finance/pulls/123))
- Bump manifest version to v1.0.0-beta.3 ([#127](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/127))
- Change environment defaults for `DOCKER_FINANCE_*_FLOW` ([#114](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/114))
- Dockerfiles updates ([#121](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/121)) ([#123](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/123))
* Add package `yq` (kislyuk's), remove `shyaml`
* Remove `pipx` from Dockerfiles, replace with packaged `csvkit`
* Comment all optional userspace packages
- `lib_gen` ([#108](https://gitea.com/EvergreenCrypto/docker-finance/pulls/108))
- `lib_gen` ([#108](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/108))
* Refactor flow generation
* Fix missing copy of default custom Dockerfile
- Miscellaneous fixes ([#106](https://gitea.com/EvergreenCrypto/docker-finance/pulls/106)) ([#107](https://gitea.com/EvergreenCrypto/docker-finance/pulls/107)) ([#115](https://gitea.com/EvergreenCrypto/docker-finance/pulls/115)) ([#117](https://gitea.com/EvergreenCrypto/docker-finance/pulls/117))
- Miscellaneous fixes ([#106](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/106)) ([#107](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/107)) ([#115](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/115)) ([#117](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/117))
* Fix usage typo
* Remove share.d from $PATH
* Clarify `hledger` (not `ledger`), update usage help / completion
* Disable shellcheck warning for `DOCKER_FINANCE_DEBUG`
- New installation method ([#104](https://gitea.com/EvergreenCrypto/docker-finance/pulls/104)) ([#105](https://gitea.com/EvergreenCrypto/docker-finance/pulls/105))
- New installation method ([#104](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/104)) ([#105](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/105))
* Add `install.bash`
* Add `dfi` alias to [Mostly-Unified CLI](README.md#mostly-unified-cli)
- Update Doxygen ([#113](https://gitea.com/EvergreenCrypto/docker-finance/pulls/113))
- Update Doxygen ([#113](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/113))
* Bump to 1.9.8
- Change 'modules' to 'topics'
#### Container
- Capital One (bank) ([#124](https://gitea.com/EvergreenCrypto/docker-finance/pulls/124))
- Capital One (bank) ([#124](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/124))
* Add interest income
- `fetch` fixes ([#102](https://gitea.com/EvergreenCrypto/docker-finance/pulls/102))
- `fetch` fixes ([#102](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/102))
- Throw errors with nested status
- Catch unrecoverable CoinGecko error
* Fix for when 'all' years are requested without paid-plan API key
@@ -662,26 +776,26 @@ Aside from changes above, there are no breaking changes for container.
#### Client / Container
- Add bash completion ([#103](https://gitea.com/EvergreenCrypto/docker-finance/pulls/103)) ([#112](https://gitea.com/EvergreenCrypto/docker-finance/pulls/112))
- Add plugins support ([#109](https://gitea.com/EvergreenCrypto/docker-finance/pulls/109)) ([#111](https://gitea.com/EvergreenCrypto/docker-finance/pulls/111)) ([#118](https://gitea.com/EvergreenCrypto/docker-finance/pulls/118)) ([#120](https://gitea.com/EvergreenCrypto/docker-finance/pulls/120)) ([#122](https://gitea.com/EvergreenCrypto/docker-finance/pulls/122))
- Add bash completion ([#103](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/103)) ([#112](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/112))
- Add plugins support ([#109](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/109)) ([#111](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/111)) ([#118](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/118)) ([#120](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/120)) ([#122](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/122))
* Add `plugins` command
* Add documentation, examples
* Add proxychains-ng / [Tor](https://www.torproject.org/) plugin
* Add [`timewarrior`](https://timewarrior.net/) to hledger timeclock plugin
- Add `times` command (timewarrior) ([#110](https://gitea.com/EvergreenCrypto/docker-finance/pulls/110))
- Add `times` command (timewarrior) ([#110](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/110))
### 🌴 Misc / Other
#### Client
- `lib_docker` ([#125](https://gitea.com/EvergreenCrypto/docker-finance/pulls/125))
- `lib_docker` ([#125](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/125))
* Add tag to container name
* Remove platform from network name
#### Client / Container
- Refactor to use `yq` (kislyuk's), remove `shyaml` ([#121](https://gitea.com/EvergreenCrypto/docker-finance/pulls/121))
- Set xtrace if debug is enabled ([#116](https://gitea.com/EvergreenCrypto/docker-finance/pulls/116))
- Refactor to use `yq` (kislyuk's), remove `shyaml` ([#121](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/121))
- Set xtrace if debug is enabled ([#116](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/116))
## 1.0.0-beta.2 - 2024-07-30
@@ -719,98 +833,98 @@ Aside from changes above, there are no breaking changes for container.
#### Repo
- README.md
- Update keyserver for repo verification ([#57](https://gitea.com/EvergreenCrypto/docker-finance/pulls/57))
- Various updates/fixes ([#98](https://gitea.com/EvergreenCrypto/docker-finance/pulls/98))
- Update keyserver for repo verification ([#57](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/57))
- Various updates/fixes ([#98](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/98))
#### Client
- Dockerfiles fixes related to `import` (coinbase/coinbase-pro) and Ubuntu-based `build` ([#58](https://gitea.com/EvergreenCrypto/docker-finance/pulls/58))
- Resolve Dockerfiles `apt` CLI warning ([#82](https://gitea.com/EvergreenCrypto/docker-finance/pulls/82))
- Append subprofile source to superscript before generating ([#87](https://gitea.com/EvergreenCrypto/docker-finance/pulls/87))
- Rewrite/fix global env gen, optimize/refactor repository path, usage update ([#90](https://gitea.com/EvergreenCrypto/docker-finance/pulls/90)) ([#92](https://gitea.com/EvergreenCrypto/docker-finance/pulls/92)) ([#97](https://gitea.com/EvergreenCrypto/docker-finance/pulls/97))
- Dockerfiles fixes related to `import` (coinbase/coinbase-pro) and Ubuntu-based `build` ([#58](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/58))
- Resolve Dockerfiles `apt` CLI warning ([#82](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/82))
- Append subprofile source to superscript before generating ([#87](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/87))
- Rewrite/fix global env gen, optimize/refactor repository path, usage update ([#90](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/90)) ([#92](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/92)) ([#97](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/97))
#### Container
- Algorand
- Add more income (Governance Rewards and spam) to `rules` ([#46](https://gitea.com/EvergreenCrypto/docker-finance/pulls/46)) ([#54](https://gitea.com/EvergreenCrypto/docker-finance/pulls/54))
- Add more income (Governance Rewards and spam) to `rules` ([#46](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/46)) ([#54](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/54))
- Ally
- 'Description' fixes (`preprocess`) ([#53](https://gitea.com/EvergreenCrypto/docker-finance/pulls/53))
- Various additions to `rules` ([#53](https://gitea.com/EvergreenCrypto/docker-finance/pulls/53))
- 'Description' fixes (`preprocess`) ([#53](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/53))
- Various additions to `rules` ([#53](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/53))
- Capital One
- **Breaking:** Upstream column-order changes ([#80](https://gitea.com/EvergreenCrypto/docker-finance/pulls/80)) ([#93](https://gitea.com/EvergreenCrypto/docker-finance/pulls/93))
- **Breaking:** Upstream column-order changes ([#80](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/80)) ([#93](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/93))
- Coinbase
- **Breaking:** SIWC API (V2) compliance ([#49](https://gitea.com/EvergreenCrypto/docker-finance/pulls/49)) ([#50](https://gitea.com/EvergreenCrypto/docker-finance/pulls/50)) ([#63](https://gitea.com/EvergreenCrypto/docker-finance/pulls/63))
- **Breaking:** Full migration to CCXT ([#75](https://gitea.com/EvergreenCrypto/docker-finance/pulls/75))
- Add 1INCH support ([#56](https://gitea.com/EvergreenCrypto/docker-finance/pulls/56))
- **Breaking:** SIWC API (V2) compliance ([#49](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/49)) ([#50](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/50)) ([#63](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/63))
- **Breaking:** Full migration to CCXT ([#75](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/75))
- Add 1INCH support ([#56](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/56))
- Electrum
- Various additions to `rules` ([#43](https://gitea.com/EvergreenCrypto/docker-finance/pulls/43))
- Various additions to `rules` ([#43](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/43))
- Ethereum-based
- Add Aave V2 -> V3 Migration Helper support ([#45](https://gitea.com/EvergreenCrypto/docker-finance/pulls/45))
- Add spam to `rules` ([#45](https://gitea.com/EvergreenCrypto/docker-finance/pulls/45)) ([#55](https://gitea.com/EvergreenCrypto/docker-finance/pulls/55)) ([#91](https://gitea.com/EvergreenCrypto/docker-finance/pulls/91))
- Add Aave V2 -> V3 Migration Helper support ([#45](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/45))
- Add spam to `rules` ([#45](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/45)) ([#55](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/55)) ([#91](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/91))
- Gemini (Exchange)
- Allow optional on-chain transfers ([#52](https://gitea.com/EvergreenCrypto/docker-finance/pulls/52))
- Add 1INCH support ([#56](https://gitea.com/EvergreenCrypto/docker-finance/pulls/56))
- Allow optional on-chain transfers ([#52](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/52))
- Add 1INCH support ([#56](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/56))
- Ledger (Live)
- **Breaking:** Upstream column addition ([#73](https://gitea.com/EvergreenCrypto/docker-finance/pulls/73)) ([#93](https://gitea.com/EvergreenCrypto/docker-finance/pulls/93))
- **Breaking:** Upstream column addition ([#73](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/73)) ([#93](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/93))
- `lib_edit`
- Fix returns, clearer fatal errors ([#81](https://gitea.com/EvergreenCrypto/docker-finance/pulls/81))
- Fix returns, clearer fatal errors ([#81](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/81))
- `lib_taxes` / `hledger-flow`
- **Breaking:** Cost-basis work-arounds for Bitcoin.tax ([#96](https://gitea.com/EvergreenCrypto/docker-finance/pulls/96))
- **Breaking:** Cost-basis work-arounds for Bitcoin.tax ([#96](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/96))
### ☀️ Features / Enhancements
#### Repo
- Add Gitea templates ([#65](https://gitea.com/EvergreenCrypto/docker-finance/pulls/65)) ([#69](https://gitea.com/EvergreenCrypto/docker-finance/pulls/69))
- Add [CHANGELOG.md](https://gitea.com/EvergreenCrypto/docker-finance/src/branch/master/CHANGELOG.md) ([#99](https://gitea.com/EvergreenCrypto/docker-finance/pulls/99))
- Add Gitea templates ([#65](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/65)) ([#69](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/69))
- Add [CHANGELOG.md](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/src/branch/master/CHANGELOG.md) ([#99](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/99))
#### Client
- Add `build` option types and build-specific features ([#68](https://gitea.com/EvergreenCrypto/docker-finance/pulls/68)) ([#70](https://gitea.com/EvergreenCrypto/docker-finance/pulls/70)) ([#79](https://gitea.com/EvergreenCrypto/docker-finance/pulls/79)) ([#85](https://gitea.com/EvergreenCrypto/docker-finance/pulls/85)) ([#86](https://gitea.com/EvergreenCrypto/docker-finance/pulls/86))
- Add `build` option types and build-specific features ([#68](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/68)) ([#70](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/70)) ([#79](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/79)) ([#85](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/85)) ([#86](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/86))
- Types: `default` | `slim` | `tiny` | `micro` | `experimental`
- Separation of concerns for build types
- Support ROOT.cern for Ubuntu
- Support `hledger` source build
- Support `hledger-flow` binary download
- Optimize image sizes
- Add `version` command for all platforms ([#61](https://gitea.com/EvergreenCrypto/docker-finance/pulls/61)) ([#83](https://gitea.com/EvergreenCrypto/docker-finance/pulls/83))
- **Breaking:** Add custom Dockerfile support ([#67](https://gitea.com/EvergreenCrypto/docker-finance/pulls/67)) ([#97](https://gitea.com/EvergreenCrypto/docker-finance/pulls/97))
- **Breaking:** New internal versioning implementation ([#84](https://gitea.com/EvergreenCrypto/docker-finance/pulls/84)) ([#88](https://gitea.com/EvergreenCrypto/docker-finance/pulls/88)) ([#100](https://gitea.com/EvergreenCrypto/docker-finance/pulls/100))
- Add `version` command for all platforms ([#61](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/61)) ([#83](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/83))
- **Breaking:** Add custom Dockerfile support ([#67](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/67)) ([#97](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/97))
- **Breaking:** New internal versioning implementation ([#84](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/84)) ([#88](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/88)) ([#100](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/100))
#### Client / Container
- `hledger` related enhancements, add alternative terminal UI (visidata) ([#64](https://gitea.com/EvergreenCrypto/docker-finance/pulls/64))
- Add `hledger --conf` support, future-proofing for `hledger` features ([#78](https://gitea.com/EvergreenCrypto/docker-finance/pulls/78))
- `hledger` related enhancements, add alternative terminal UI (visidata) ([#64](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/64))
- Add `hledger --conf` support, future-proofing for `hledger` features ([#78](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/78))
#### Container
- `hledger-flow`
- Add support for AdaLite ([#40](https://gitea.com/EvergreenCrypto/docker-finance/pulls/40))
- PayPal Business: catch 'Account Hold' ([#47](https://gitea.com/EvergreenCrypto/docker-finance/pulls/47))
- Add support for AdaLite ([#40](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/40))
- PayPal Business: catch 'Account Hold' ([#47](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/47))
- `price`
- **Breaking:** Add support for multiple crypto aggregator-APIs ([#60](https://gitea.com/EvergreenCrypto/docker-finance/pulls/60))
- **Breaking:** Add support for multiple crypto aggregator-APIs ([#60](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/60))
- **Breaking:** Add API keys/blockchains to `fetch` configuration
- Add support for Mobula
- Add support for CoinGecko Pro
- `root`
- Add internal throw/exception handler / unit test ([#89](https://gitea.com/EvergreenCrypto/docker-finance/pulls/89))
- Macro reorg, refactor ([#94](https://gitea.com/EvergreenCrypto/docker-finance/pulls/94))
- Add crypto macros (`Hash`, `Random`) ([#95](https://gitea.com/EvergreenCrypto/docker-finance/pulls/95))
- Add support for multiple random number types (`Random`), update tests ([#95](https://gitea.com/EvergreenCrypto/docker-finance/pulls/95))
- Add internal throw/exception handler / unit test ([#89](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/89))
- Macro reorg, refactor ([#94](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/94))
- Add crypto macros (`Hash`, `Random`) ([#95](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/95))
- Add support for multiple random number types (`Random`), update tests ([#95](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/95))
### 🌴 Misc / Other
#### Client
- Dockerfiles: remove obsolete 'version' element ([#42](https://gitea.com/EvergreenCrypto/docker-finance/pulls/42))
- `lib_docker`: factor out args parsers ([#71](https://gitea.com/EvergreenCrypto/docker-finance/pulls/71))
- `lib_gen`: return success on client generation ([#76](https://gitea.com/EvergreenCrypto/docker-finance/pulls/76))
- Dockerfiles: remove obsolete 'version' element ([#42](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/42))
- `lib_docker`: factor out args parsers ([#71](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/71))
- `lib_gen`: return success on client generation ([#76](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/76))
#### Container
- `hledger-flow`: btcpayserver: preprocess: fix YYY comment typo ([#44](https://gitea.com/EvergreenCrypto/docker-finance/pulls/44))
- bash: `lib_fetch`: create prices dir if nonexistent ([#101](https://gitea.com/EvergreenCrypto/docker-finance/pulls/101))
- php: `fetch`: gemini: update to ccxt's latest request() signature | run linter ([#62](https://gitea.com/EvergreenCrypto/docker-finance/pulls/62))
- `hledger-flow`: btcpayserver: preprocess: fix YYY comment typo ([#44](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/44))
- bash: `lib_fetch`: create prices dir if nonexistent ([#101](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/101))
- php: `fetch`: gemini: update to ccxt's latest request() signature | run linter ([#62](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance/pulls/62))
## 1.0.0-beta - 2024-03-04

View File

@@ -18,17 +18,17 @@
<div align="center">
[<img src=".img/branding/docker-finance.png" height=75% width=75% align="center" />](https://gitea.com/EvergreenCrypto/docker-finance "docker-finance")
[<img src=".img/branding/docker-finance.png" height=75% width=75% align="center" />](https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance "docker-finance")
</div>
<div align="center">
<img src=".img/branding/dfi.png" height=3% width=3% /> (docker-finance) is a [quasi-"financial operating system"](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md) of accounting for [variant ledgers and metadata](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-is-supported.md).
<img src=".img/branding/dfi.png" height=3% width=3% /> (docker-finance) is a [quasi-"financial operating system"](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md) of accounting for [variant ledgers and metadata](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-is-supported.md).
After [installing and configuring](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-get-started.md), you can [learn how to use `dfi`](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-use-it.md). You can also [contribute](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-contribute.md) or [reach out](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-connect.md) at any time.
After [installing and configuring](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-get-started.md), you can [learn how to use `dfi`](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-use-it.md). You can also [contribute](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-contribute.md) or [reach out](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/How-do-I-connect.md) at any time.
Please, consider the [legalese](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/Where-is-the-legalese.md) before using (or copying) this repository. All other documentation can be found [here](https://gitea.com/EvergreenCrypto/dfi-docs).
Please, consider the [legalese](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/Where-is-the-legalese.md) before using (or copying) this repository. All other documentation can be found [here](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs).
</div>
@@ -36,14 +36,14 @@ Please, consider the [legalese](https://gitea.com/EvergreenCrypto/dfi-docs/src/b
<div align="center">
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/client.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#image-finance "image: finance")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/dev-tools.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#image-dev-tools "image: dev-tools")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/fetch.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#fetch "Fetch prices, remote accounts and blockchain data")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/hledger-suite.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#hledger-suite "hledger-suite")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/meta.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#meta-w-root-c-analysis "Meta (w/ ROOT C++ analysis)")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/root.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#root-cli-w-c-api "ROOT (CLI w/ C++ API)")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/taxes.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#taxes "Tax preparation")
[<img src="https://gitea.com/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/reports.gif" width=22.5% height=22.5% />](https://gitea.com/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#reports "Financial reports")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/client.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#image-finance "image: finance")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/dev-tools.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#image-dev-tools "image: dev-tools")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/fetch.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#fetch "Fetch prices, remote accounts and blockchain data")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/hledger-suite.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#hledger-suite "hledger-suite")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/meta.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#meta-w-root-c-analysis "Meta (w/ ROOT C++ analysis)")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/root.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#root-cli-w-c-api "ROOT (CLI w/ C++ API)")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/taxes.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#taxes "Tax preparation")
[<img src="https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/raw/branch/master/assets/examples/gif/reports.gif" width=22.5% height=22.5% />](https://gitea.evergreencrypto.co/EvergreenCrypto/dfi-docs/src/branch/master/markdown/What-does-it-do.md#reports "Financial reports")
</div>

View File

@@ -1,6 +1,6 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2021-2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
# Copyright (C) 2021-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
@@ -28,6 +28,7 @@ services:
# 2. There's no use-case for custom container configurations
#
- ${DOCKER_FINANCE_CLIENT_REPO}/docker-finance.dox:${DOCKER_FINANCE_CLIENT_REPO}/docker-finance.dox
- ${DOCKER_FINANCE_CLIENT_REPO}/.gitea:${DOCKER_FINANCE_CLIENT_REPO}/.gitea
- ${DOCKER_FINANCE_CLIENT_REPO}/client:${DOCKER_FINANCE_CLIENT_REPO}/client
- ${DOCKER_FINANCE_CLIENT_REPO}/container:${DOCKER_FINANCE_CLIENT_REPO}/container
- ${DOCKER_FINANCE_CLIENT_PLUGINS}/client:${DOCKER_FINANCE_CLIENT_PLUGINS}/client

View File

@@ -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
@@ -36,6 +36,7 @@ RUN pacman -Syu --noconfirm --disable-download-timeout
RUN pacman -Syu \
bc \
csvkit \
less \
vim \
xan \
yq \

View File

@@ -27,7 +27,7 @@ RUN sed -i 's/# %wheel ALL=(ALL:ALL) NOPASSWD: ALL/%wheel ALL=(ALL:ALL) NOPASSWD
USER builder
WORKDIR /home/builder
RUN git clone --depth=1 https://gitlab.archlinux.org/archlinux/packaging/packages/root -b 6.38.00-3
RUN git clone --depth=1 https://gitlab.archlinux.org/archlinux/packaging/packages/root -b 6.38.02-1
WORKDIR /home/builder/root
@@ -79,7 +79,7 @@ RUN sed -i -e '/^ qt6-webengine$/d' PKGBUILD
RUN sed -i "s/options=(\!lto)$/options=('\!debug' '\!lto')/" PKGBUILD
# Execute build
RUN PACKAGER="https://gitea.com/EvergreenCrypto/docker-finance" makepkg -s --noconfirm
RUN PACKAGER="https://gitea.evergreencrypto.co/EvergreenCrypto/docker-finance" makepkg -s --noconfirm
#
# Production stage

View File

@@ -1,6 +1,6 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2021-2024 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
@@ -32,27 +32,31 @@
USER root
RUN pacman -Syu --noconfirm
## Optional: finance-related
##
## Optional (examples)
##
## Finance-related
#RUN pacman -Syu \
# calc \
# less \
# --noconfirm --disable-download-timeout
## Optional: text editors
## Text editors
#RUN pacman -Syu \
# emacs-nox \
# nano \
# --noconfirm --disable-download-timeout
## Optional: python
## Python
#RUN pacman -Syu \
# python-pipx \
# --noconfirm --disable-download-timeout
## Optional: python: xlsx to csv conversion tool
## Python (requires above): xlsx to csv conversion tool
#USER @DOCKER_FINANCE_USER@
#WORKDIR /home/@DOCKER_FINANCE_USER@
#RUN pipx install xlsx2csv
#USER root
##
## Plugins (dependencies)

View File

@@ -2,7 +2,7 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2021-2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
# Copyright (C) 2021-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
@@ -66,26 +66,29 @@ fi
# Client-specific environment, including bind mounts (client view)
if [ -z "$global_client_base_path" ]; then
global_client_base_path="$(realpath -s "${BASH_SOURCE[0]}" | rev | cut -d'/' -f7- | rev)"
fi
if [ -z "$DOCKER_FINANCE_CLIENT_CONF" ]; then
export DOCKER_FINANCE_CLIENT_CONF="${HOME}/.config/docker-finance.d"
export DOCKER_FINANCE_CLIENT_CONF="${global_client_base_path}/conf.d"
fi
if [ -z "$DOCKER_FINANCE_CLIENT_REPO" ]; then
DOCKER_FINANCE_CLIENT_REPO="$(dirname "$(realpath -s $0)" | rev | cut -d'/' -f2- | rev)"
export DOCKER_FINANCE_CLIENT_REPO
export DOCKER_FINANCE_CLIENT_REPO="${global_client_base_path}/repo"
fi
if [[ -z "$DOCKER_FINANCE_CLIENT_PLUGINS" ]]; then
export DOCKER_FINANCE_CLIENT_PLUGINS="${HOME}/plugins"
export DOCKER_FINANCE_CLIENT_PLUGINS="${global_client_base_path}/plugins"
fi
if [[ "$global_platform" != "dev-tools" ]]; then
if [[ -z "$DOCKER_FINANCE_CLIENT_FLOW" ]]; then
export DOCKER_FINANCE_CLIENT_FLOW="${HOME}/finance-flow"
export DOCKER_FINANCE_CLIENT_FLOW="${global_client_base_path}/flow"
fi
if [[ -z "$DOCKER_FINANCE_CLIENT_SHARED" ]]; then
export DOCKER_FINANCE_CLIENT_SHARED="${HOME}/share.d"
export DOCKER_FINANCE_CLIENT_SHARED="${global_client_base_path}/share.d"
fi
# hledger-web
@@ -103,23 +106,23 @@ fi
if [[ "$global_platform" != "dev-tools" ]]; then
if [ -z "$DOCKER_FINANCE_CONTAINER_CONF" ]; then
export DOCKER_FINANCE_CONTAINER_CONF="/home/${DOCKER_FINANCE_USER}/.config/docker-finance.d"
export DOCKER_FINANCE_CONTAINER_CONF="/home/${DOCKER_FINANCE_USER}/docker-finance/conf.d"
fi
if [ -z "$DOCKER_FINANCE_CONTAINER_REPO" ]; then
export DOCKER_FINANCE_CONTAINER_REPO="/home/${DOCKER_FINANCE_USER}/docker-finance"
export DOCKER_FINANCE_CONTAINER_REPO="/home/${DOCKER_FINANCE_USER}/docker-finance/repo"
fi
if [[ -z "$DOCKER_FINANCE_CONTAINER_FLOW" ]]; then
export DOCKER_FINANCE_CONTAINER_FLOW="/home/${DOCKER_FINANCE_USER}/finance-flow"
export DOCKER_FINANCE_CONTAINER_FLOW="/home/${DOCKER_FINANCE_USER}/docker-finance/flow"
fi
if [[ -z "$DOCKER_FINANCE_CONTAINER_SHARED" ]]; then
export DOCKER_FINANCE_CONTAINER_SHARED="/home/${DOCKER_FINANCE_USER}/share.d"
export DOCKER_FINANCE_CONTAINER_SHARED="/home/${DOCKER_FINANCE_USER}/docker-finance/share.d"
fi
if [[ -z "$DOCKER_FINANCE_CONTAINER_PLUGINS" ]]; then
export DOCKER_FINANCE_CONTAINER_PLUGINS="/home/${DOCKER_FINANCE_USER}/plugins"
export DOCKER_FINANCE_CONTAINER_PLUGINS="/home/${DOCKER_FINANCE_USER}/docker-finance/plugins"
fi
if [[ -z "$DOCKER_FINANCE_CONTAINER_CMD" ]]; then

View File

@@ -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
@@ -34,7 +34,7 @@
# Where :subaccount-2:... (and successive subaccounts) are optional
# (the final subaccount in the chain being wallet-name (per address)).
#
# 2. For cryptocurrency assets:
# 2. For asset prices:
#
# - Mobula:
#
@@ -61,12 +61,14 @@
# * For ethereum-based chains:
#
# - As of now, you *MUST* use an API key.
# Generate your API key at etherscan.io
# Generate your API key at etherscan.io but take note
# of what chain is supported by which free/paid plan.
#
# - Use "etherscan" as the blockchain API, as its
# unified API is used for all ethereum-based chains.
# - Use "etherscan/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# as the blockchain API, replacing X with the API key,
# as its unified API is used for all ethereum-based chains.
#
# * For algorand/tezos: currently no API key is required.
# * For algorand/tezos: currently, no API key is required.
#
#
# 5. Feel free to delete any unused accounts/subaccounts as needed.
@@ -89,7 +91,6 @@ version: @DOCKER_FINANCE_VERSION@
price:
mobula:
# NOTE: visit mobula.io for free API key
#key: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
key:
asset:
- "algorand/ALGO"
@@ -120,9 +121,6 @@ version: @DOCKER_FINANCE_VERSION@
# Gemini USD
- "ethereum:0x056fd409e1d7a124bd7017459dfea2f387b6d5cd/GUSD"
# Compound USDT
- "ethereum:0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9/cUSDT"
# MATIC (on Ethereum)
- "ethereum:0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0/MATIC"
@@ -164,8 +162,8 @@ version: @DOCKER_FINANCE_VERSION@
#- "usd-coin/USDC"
account:
# When creating a Gemini API key, create a key with only the "Auditor" role
gemini:
# NOTE: When creating a Gemini API key, create a key with only the "Auditor" role
key: "account-XXXXXXXXXXXXXXXXXXXX"
secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Use this format to fetch all supported symbols/pairs

View File

@@ -20,7 +20,7 @@
#
# Release version (tag format)
version: "v1.1.1"
version: "v1.3.0"
# Container dependencies (used by `version` command)
# NOTE: this must stay inline with Dockerfiles
@@ -38,6 +38,7 @@ container:
packages:
- "bc"
- "csvkit"
- "less"
- "vim"
- "xan"
- "yq"

View File

@@ -2,7 +2,7 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
# Copyright (C) 2025-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
@@ -230,7 +230,7 @@ function bitcoin::__getter()
lib_docker::exec "if [ ! -d $plugin_bitcoin_path ]; then git clone $plugin_arg_remote $plugin_bitcoin_path ; fi" \
|| lib_utils::die_fatal "Could not clone '${plugin_arg_remote}' to '${plugin_bitcoin_path}'"
lib_docker::exec "pushd $plugin_bitcoin_path 1>/dev/null && git pull $plugin_arg_remote && popd 1>/dev/null" \
lib_docker::exec "pushd $plugin_bitcoin_path 1>/dev/null && git pull $plugin_arg_remote --tags && popd 1>/dev/null" \
|| lib_utils::die_fatal "Could not pull '${plugin_arg_remote}' to '${plugin_bitcoin_path}'"
}

View File

@@ -2,7 +2,7 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2024 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
@@ -44,17 +44,17 @@ function tor::start()
# NOTE: proxychains.conf's [ProxyList] won't allow hostnames (or Docker network container name).
# So, to avoid conflicting IP address spaces, docker-finance will not hardcode address space.
# Ergo, a already-running container will be needed (sorry, lib_docker::run())
if ! docker container inspect -f '{{.State.Running}}' "$global_container" &>/dev/null; then
lib_utils::die_fatal "docker-finance not running! Bring \`up\` container and try again."
fi
# Ergo, an already-running container will be needed (sorry, lib_docker::run())
lib_docker::exec "" \
|| lib_utils::die_fatal "docker-finance not running! Bring \`up\` a \`dfi\` instance and try again."
local -r _torrc="/etc/tor/torrc"
if docker container inspect -f '{{.State.Running}}' "$tor_container" &>/dev/null; then
if [[ $(docker container inspect -f '{{.State.Running}}' "$tor_container" 2>/dev/null) == "true" ]]; then
lib_utils::print_error "${tor_container}: instance already running (consider \`restart\`)"
return 1
else
docker pull alpine:latest || lib_utils::die_fatal
docker run -it --rm --detach \
--network "$global_network" \
--name="${tor_container}" \
@@ -71,7 +71,7 @@ function tor::start()
lib_utils::print_info "${tor_container}: container IP '${_ip}'"
# Need to wait for a working installation
lib_utils::print_warning "${tor_container}: waiting for Tor installation"
lib_utils::print_info "${tor_container}: waiting for Tor installation"
while ! docker exec "$tor_container" /bin/sh -c 'apk info -e tor' 1>/dev/null; do
sleep 1s
done && lib_utils::print_info "${tor_container}: Tor installation ready"
@@ -87,11 +87,11 @@ function tor::start()
lib_utils::print_info "${tor_container}: restarting Tor with updated ${_torrc}"
docker exec "$tor_container" /bin/sh -c "pkill -HUP tor" || lib_utils::die_fatal
# Set docker-finance's proxychains to point to Tor instance
# Set `dfi`'s proxychains instance to point to Tor instance
local -r _proxychains="/etc/proxychains.conf"
lib_utils::print_info "${global_container}: updating $_proxychains"
docker exec -it --user root "$global_container" \
/bin/bash -i -c "
docker exec --user root "$global_container" \
/bin/bash -c "
sed -i \
-e 's:^#quiet_mode:quiet_mode:' \
-e 's:^# localnet 127.0.0.0/255.0.0.0:localnet 127.0.0.0/255.0.0.0:' \
@@ -99,15 +99,28 @@ function tor::start()
&& echo 'socks5 $_ip 9050' >>$_proxychains" || lib_utils::die_fatal
# Test Tor connection
local -r _sleep="15s"
lib_utils::print_warning "${global_container}: testing connection (bootstrapping ~${_sleep})"
local -r _sleep="20s"
lib_utils::print_info "${global_container}: testing connection (bootstrapping ~${_sleep})"
sleep "$_sleep" # Give time to bootstrap
# TODO: run timer to verify response (and fail if N times if no response)
docker exec -it "$global_container" \
/bin/bash -i -c "
proxychains curl -s https://check.torproject.org 2>/dev/null \
| grep -B3 'Your IP address appears to be' \
| sed -e 's/^ //g' -e '\$ s/[^\\.0-9]//g' -e '/^\$/d' -e '2,3d'" || lib_utils::die_fatal
local _tries=1
while [ $_tries -ne 3 ]; do
lib_docker::exec "proxychains curl -s https://check.torproject.org 2>/dev/null \
| grep -B3 'Your IP address appears to be' \
| sed -e 's/^ //g' -e '\$ s/[^\\.0-9]//g' -e '/^\$/d' -e '2,3d' \
| grep -A2 --color=never Congratulations || exit 1 2>/dev/null" 2>/dev/null
if [ $? -ne 0 ]; then
lib_utils::print_warning "Could not bootstrap, trying again (${_tries}/3)"
docker exec "$tor_container" /bin/sh -c "pkill -HUP tor" || lib_utils::die_fatal
sleep "$_sleep"
((_tries++))
else
break
fi
done
if [ $_tries -eq 3 ]; then
lib_utils::die_fatal "Could not successfully bootstrap! \`restart\` this instance"
fi
}
function tor::stop()
@@ -116,8 +129,8 @@ function tor::stop()
lib_utils::print_error "${tor_container}: container not running"
return 1
fi
lib_utils::print_warning "${tor_container}: stopping container"
docker container stop "$tor_container" &>/dev/null \
lib_utils::print_info "${tor_container}: stopping container"
docker container stop -t 3 "$tor_container" &>/dev/null \
&& lib_utils::print_info "${tor_container}: container stopped"
}

View File

@@ -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
@@ -131,7 +131,7 @@ function docker-finance::completion()
find "${DOCKER_FINANCE_CLIENT_REPO}"/client/plugins/docker "${_args[@]}" -printf 'repo/%P\n' 2>/dev/null
})
declare -r _plugins
mapfile -t _reply < <(compgen -W "${_plugins[*]}" -- "$_cur")
mapfile -t _reply < <(compgen -W "help ${_plugins[*]}" -- "$_cur")
;;
esac
declare -r _reply

View File

@@ -177,7 +177,7 @@ function lib_linter::__lint_cpp()
local -r _clang_format="clang-format -i --style=file:${_clang_file}"
local -r _cpplint="cpplint --root=${DOCKER_FINANCE_CLIENT_REPO} --filter=-whitespace/braces,-whitespace/newline,-whitespace/line_length,-build/c++11 --headers=hh --extensions=hh,cc,cpp,C"
local -r _cppcheck="cppcheck --enable=warning,style,performance,portability --inline-suppr --std=c++17"
local -r _cppcheck="cppcheck --enable=warning,style,performance,portability --inline-suppr --std=c++20"
if [ -z "${_path[*]}" ]; then
# Do all

View File

@@ -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
@@ -87,9 +87,8 @@ function lib_docker::__docker_compose()
[ ! -f "$global_env_file" ] \
&& lib_utils::die_fatal "$global_env_file not found! Run the gen command!"
pushd "$global_repo_dockerfiles" 1>/dev/null \
|| return $? \
&& docker compose -f docker-compose.yml --env-file "$global_env_file" "$@"
pushd "$global_repo_dockerfiles" 1>/dev/null || return $?
docker compose -f docker-compose.yml --env-file "$global_env_file" "$@" || return $?
popd 1>/dev/null || return $?
}
@@ -278,7 +277,7 @@ function lib_docker::__build()
_files+=("${_path}/Dockerfile.user.in")
;;
*)
lib_utils::print_warning "'${global_arg_type}' is not supported for 'dev-tools', using 'default'"
lib_utils::die_fatal "'${global_arg_type}' is not supported for 'dev-tools', use 'default' instead"
;;
esac
;;
@@ -359,10 +358,14 @@ function lib_docker::__up()
# }
# ]
# }
lib_utils::print_debug "Bringing up network and container"
lib_utils::print_debug "Creating network"
docker network create "$global_network" 2>/dev/null
lib_utils::print_debug "Bringing up container"
local _tty
test -t 1 && _tty="t"
lib_docker::__docker_compose up -d docker-finance "$@" \
&& docker exec -it "$global_container" /bin/bash
&& docker exec -i"${_tty}" "$global_container" /bin/bash
}
function lib_docker::__down()
@@ -507,7 +510,21 @@ function lib_docker::__shell()
function lib_docker::__exec()
{
docker exec -it "$global_container" /bin/bash -i -c "$@"
[ -z "$DOCKER_FINANCE_DEBUG" ] && lib_utils::die_fatal
# Allocate pseudo-TTY, if needed
# NOTE: interactive is kept for cases in which the passed command requires it
local _tty
test -t 1 && _tty="t"
local -r _exec=("docker" "exec" "-i$_tty" "$global_container" "/bin/bash" "-i" "-c" "$@")
if [ "$DOCKER_FINANCE_DEBUG" -eq 0 ]; then
# Silence `bash: cannot set terminal process group (-1): Inappropriate ioctl for device`
# NOTE: lib_utils error handling will still function as expected
"${_exec[@]}" 2>/dev/null
else
"${_exec[@]}"
fi
}
function lib_docker::__parse_args_edit()

View File

@@ -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
@@ -31,7 +31,9 @@ source "${DOCKER_FINANCE_CLIENT_REPO}/container/src/finance/lib/internal/lib_uti
#
if [ $UID -lt 1000 ]; then
lib_utils::die_fatal "Do not run as root or system user!"
[ $UID -eq 0 ] \
&& lib_utils::die_fatal "Cannot run as root!" \
|| lib_utils::print_warning "Running as system user"
fi
# Dependencies
@@ -85,7 +87,10 @@ function lib_env::env()
global_tag_dir="client/$(uname -s)-$(uname -m)/${global_platform}/${global_tag}"
declare -g global_tag_dir
local _env_dir="/home/${USER}/.config/docker-finance.d/${global_tag_dir}/env" # NOTE: keep aligned with gen.bash
# Environment location
# NOTE: keep aligned with gen.bash
local _env_dir
_env_dir="$(realpath -s "${BASH_SOURCE[0]}" | rev | cut -d'/' -f7- | rev)/conf.d/${global_tag_dir}/env"
local _env_file="${_env_dir}/${global_conf_filename}"
# shellcheck source=/dev/null
@@ -93,7 +98,7 @@ function lib_env::env()
if [ -z "$DOCKER_FINANCE_CLIENT_CONF" ]; then
# shellcheck source=/dev/null
source "${DOCKER_FINANCE_CLIENT_REPO}/client/docker-finance.d/client/env/gen.bash"
source "${DOCKER_FINANCE_CLIENT_REPO}/client/conf.d/client/env/gen.bash"
fi
[ -z "$DOCKER_FINANCE_CLIENT_CONF" ] \
@@ -161,7 +166,7 @@ function lib_env::__set_client_globals()
lib_utils::print_debug "DOCKER_FINANCE_VERSION=${DOCKER_FINANCE_VERSION}"
# Repository-provided (not user-defined) default environment
global_repo_conf_dir="${DOCKER_FINANCE_CLIENT_REPO}/client/docker-finance.d"
global_repo_conf_dir="${DOCKER_FINANCE_CLIENT_REPO}/client/conf.d"
declare -g global_repo_conf_dir
lib_utils::print_debug "global_repo_conf_dir=${global_repo_conf_dir}"

View File

@@ -2,7 +2,7 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2021-2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
# Copyright (C) 2021-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
@@ -478,6 +478,57 @@ function lib_gen::__gen_client()
lib_utils::print_custom " \e[32m│ └─\e[34m Edit file now? [Y/n] \e[0m"
lib_gen::__gen_edit "$global_custom_dockerfile"
fi
#
# Generate client-side `plugins` layout (custom)
#
lib_gen::__gen_plugins
#
# Generate shared path layout
#
# TODO: consider supporting for dev-tools
[ -z "$global_platform" ] && lib_utils::die_fatal
if [ "$global_platform" != "dev-tools" ]; then
lib_gen::__gen_shared
fi
}
# Custom plugins layout to drop-in custom plugins
# NOTE: underlying impl expects this layout
function lib_gen::__gen_plugins()
{
lib_utils::print_debug "Generating custom plugins layout"
[ -z "$DOCKER_FINANCE_CLIENT_PLUGINS" ] && lib_utils::die_fatal
if [ ! -d "$DOCKER_FINANCE_CLIENT_PLUGINS" ]; then
mkdir -p "$DOCKER_FINANCE_CLIENT_PLUGINS" || lib_utils::die_fatal
fi
local -r _client="${DOCKER_FINANCE_CLIENT_PLUGINS}/client"
if [ ! -d "${_client}/docker" ]; then
mkdir -p "${_client}/docker" || lib_utils::die_fatal
fi
local -r _container="${DOCKER_FINANCE_CLIENT_PLUGINS}/container"
if [ ! -d "${_container}/finance" ]; then
mkdir -p "${_container}/finance" || lib_utils::die_fatal
fi
if [ ! -d "${_container}/root" ]; then
mkdir -p "${_container}/root" || lib_utils::die_fatal
fi
}
# Shared path layout to drop-in shared files
function lib_gen::__gen_shared()
{
lib_utils::print_debug "Generating shared path"
[ -z "$DOCKER_FINANCE_CLIENT_SHARED" ] && lib_utils::die_fatal
if [ ! -d "$DOCKER_FINANCE_CLIENT_SHARED" ]; then
mkdir -p "$DOCKER_FINANCE_CLIENT_SHARED" || lib_utils::die_fatal
fi
}
function lib_gen::__gen_container()
@@ -500,17 +551,6 @@ function lib_gen::__gen_container()
fi
#
# Generate plugins (custom)
#
[ -z "$DOCKER_FINANCE_CLIENT_PLUGINS" ] && lib_utils::die_fatal
if [ ! -d "$DOCKER_FINANCE_CLIENT_PLUGINS" ]; then
mkdir -p "$DOCKER_FINANCE_CLIENT_PLUGINS" || lib_utils::die_fatal
fi
lib_gen::__gen_plugins
#
# Generate flow
#
@@ -597,34 +637,6 @@ function lib_gen::__gen_superscript_write()
"${global_repo_conf_dir}/container/shell/superscript.bash.in" >"$global_superscript"
}
#
# Generate plugins (custom):
#
# - Provides:
# - A layout to drop-in custom plugins
# * Underlying impl expects this layout
#
function lib_gen::__gen_plugins()
{
[ -z "$DOCKER_FINANCE_CLIENT_PLUGINS" ] && lib_utils::die_fatal
lib_utils::print_debug "Generating custom plugins layout"
local -r _client="${DOCKER_FINANCE_CLIENT_PLUGINS}/client"
if [ ! -d "${_client}/docker" ]; then
mkdir -p "${_client}/docker" || lib_utils::die_fatal
fi
local -r _container="${DOCKER_FINANCE_CLIENT_PLUGINS}/container"
if [ ! -d "${_container}/finance" ]; then
mkdir -p "${_container}/finance" || lib_utils::die_fatal
fi
if [ ! -d "${_container}/root" ]; then
mkdir -p "${_container}/root" || lib_utils::die_fatal
fi
}
#
# Generate flow: times
#
@@ -723,7 +735,7 @@ function lib_gen::__gen_profile()
local -r _gen_path="${_profiles}/${_profile}/${_subprofile}"
lib_utils::print_debug "_gen_path=${_gen_path}"
local -r _gen_conf_path="${_gen_path}/docker-finance.d"
local -r _gen_conf_path="${_gen_path}/conf.d"
lib_utils::print_debug "_gen_conf_path=${_gen_conf_path}"
lib_gen::__gen_subprofile_flow
@@ -883,7 +895,7 @@ function lib_gen::__gen_subprofile_flow_superscript()
[ ! -f "$global_superscript" ] && lib_utils::die_fatal "Superscript does not exist!"
# Append subprofile source to superscript
local -r _source="source \"\${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/${_profile}/${_subprofile}/docker-finance.d/shell/subscript.bash\""
local -r _source="source \"\${DOCKER_FINANCE_CONTAINER_FLOW}/profiles/${_profile}/${_subprofile}/conf.d/shell/subscript.bash\""
lib_utils::print_custom " \e[32m│ │ │ └─\e[34m Appending subprofile to superscript\e[0m\n"
# If source subprofile does not exist, append

View File

@@ -2,7 +2,7 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 2024 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
@@ -71,14 +71,32 @@ function lib_plugins::__parse_args()
\e[32mUsage:\e[0m
$ $global_usage <repo${global_arg_delim_1}plugin | custom${global_arg_delim_1}plugin> [args]
$ $global_usage <help | [TAB COMPLETION]> [args]
\e[32mArguments:\e[0m
[None | help]: show this usage help
[TAB COMPLETION]: run given shell plugin
custom = custom plugins in custom plugin location
repo = repository plugins in repository location
[args]: arguments to plugin
\e[32mExamples:\e[0m
\e[37;2m# Execute a repository plugin in '${_repo}'\e[0m
\e[37;2m# See this usage help\e[0m
$ $global_usage help
\e[37;2m# The output of tab completion\e[0m
$ $global_usage \\\t\\\t
custom/example.bash help repo/bitcoin.bash repo/example.bash repo/tor.bash
\e[37;2m# Execute a repository shell plugin in '${_repo}'\e[0m
$ $global_usage repo${global_arg_delim_1}example.bash \"I'm in repo\"
\e[37;2m# Execute a custom plugin in '${_custom}'\e[0m
\e[37;2m# Execute a custom shell plugin in '${_custom}'\e[0m
$ $global_usage custom${global_arg_delim_1}example.bash \"I'm in custom\"
"

View File

@@ -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
@@ -871,7 +871,10 @@ function lib_fetch::__fetch_exec()
#
__DFI_PHP_DEPS__="${_deps}" __DFI_PHP_ROOT__="${_impl}" "${_exec[@]}" "${_impl}/fetch.php" "$_type" "$_subtype"
local -r _return=$?
IFS="$_ifs"
return $_return
}
# vim: sw=2 sts=2 si ai et

View File

@@ -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
@@ -167,7 +167,12 @@ function lib_hledger::__hledger-vui()
[ -z "$global_conf_visidata" ] && lib_utils::die_fatal
local -r _visidata=("--visidata-dir" "$global_conf_visidata" "--motd-url" "file:///dev/null" "--filetype" "csv")
visidata "${_visidata[@]}" < <(hledger "${global_base_args[@]}" print -O csv "$@")
local -r _hledger=("hledger" "${global_base_args[@]}" "print" "-O" "csv" "$@")
# If hledger command is valid, output into visidata
if "${_hledger[@]}" 1>/dev/null; then
visidata "${_visidata[@]}" < <("${_hledger[@]}")
fi
}
function lib_hledger::__hledger-web()
@@ -183,7 +188,7 @@ function lib_hledger::__hledger-web()
sleep 3s
if ! ps -p "$_pid" 1>/dev/null; then
lib_utils::print_error "hledger-web failed. See above error message"
lib_utils::die_fatal "hledger-web failed. See above error message"
else
lib_utils::print_info "hledger-web started (PID ${_pid}). Point web browser to $_url"
fi

View File

@@ -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
@@ -71,7 +71,7 @@ function lib_plugins::__parse_args()
\e[32mUsage:\e[0m
$ $global_usage [help | [TAB COMPLETION]] [args]
$ $global_usage <help | [TAB COMPLETION]> [args]
\e[32mArguments:\e[0m
@@ -91,8 +91,8 @@ function lib_plugins::__parse_args()
\e[37;2m# The output of tab completion\e[0m
$ $global_usage \\\t\\\t
custom/billing/invoice.bash help repo/timew_to_timeclock.bash
custom/billing/manage.bash repo/example.bash
custom/billing/invoice.bash custom/example.bash repo/example.bash
custom/billing/manage.bash help repo/timew_to_timeclock.bash
\e[37;2m# Execute a repository shell plugin in '${_repo}'\e[0m
$ $global_usage repo${global_arg_delim_1}example.bash \"I'm in repo\"

View File

@@ -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
@@ -1003,7 +1003,7 @@ function lib_taxes::__taxes_write()
if [ -z "$global_arg_year" ]; then
lib_utils::print_info "Capturing the year of the oldest tagged record ...\n"
local -r _oldest_year="$("${_base_hledger[@]}" | head -n2 | xan select \"date\" | tail -n1 | cut -d'-' -f1)"
local -r _oldest_year="$("${_base_hledger[@]}" | head -n2 | xan select \"date\" | gawk 'END {gsub(/"/, ""); printf $1}' FS=- OFS=-)"
[ -z "$_oldest_year" ] && lib_utils::die_fatal "No records available to write"
elif [[ "$global_arg_year" -gt "$_current_year" ]]; then

View File

@@ -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
@@ -29,7 +29,9 @@ source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_utils.bash
#
if [ $UID -lt 1000 ]; then
lib_utils::die_fatal "Do not run as root or system user!"
[ $UID -eq 0 ] \
&& lib_utils::die_fatal "Cannot run as root!" \
|| lib_utils::print_warning "Running as system user"
fi
# IMPORTANT: keep umask for security
@@ -77,11 +79,11 @@ function lib_finance::finance()
declare -grx global_hledger_cmd=("hledger" "-f" "$global_child_profile_journal")
# Globals (configuration)
declare -grx global_conf_fetch="${global_child_profile_flow}/docker-finance.d/fetch/fetch.yaml"
declare -grx global_conf_hledger="${global_child_profile_flow}/docker-finance.d/hledger/hledger.conf"
declare -grx global_conf_meta="${global_child_profile_flow}/docker-finance.d/meta/meta.csv"
declare -grx global_conf_subscript="${global_child_profile_flow}/docker-finance.d/shell/subscript.bash"
declare -grx global_conf_visidata="${global_child_profile_flow}/docker-finance.d/visidata" # dir for config/addons
declare -grx global_conf_fetch="${global_child_profile_flow}/conf.d/fetch/fetch.yaml"
declare -grx global_conf_hledger="${global_child_profile_flow}/conf.d/hledger/hledger.conf"
declare -grx global_conf_meta="${global_child_profile_flow}/conf.d/meta/meta.csv"
declare -grx global_conf_subscript="${global_child_profile_flow}/conf.d/shell/subscript.bash"
declare -grx global_conf_visidata="${global_child_profile_flow}/conf.d/visidata" # dir for config/addons
# Implementation "libraries" (requires previously set globals)
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_edit.bash" || exit 1

View File

@@ -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
@@ -38,17 +38,13 @@ function parse()
{
lib_preprocess::assert_header "Date, Time, Amount, Type, Description"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
# `Description` cleanup
sub(/^ /, "", $5) # may have an empty space in front of line
gsub(/, /, " - ") # may have (multiple) commas followed by space
gsub(/"/, "", $5) # may have (multiple) quotes
sub(/%/, "%%", $5) # remove potential interpretation
printf $1 OFS # Date
printf $2 OFS # Time
@@ -56,13 +52,18 @@ function parse()
printf $3 OFS # Amount
printf $4 OFS # Type
printf $5 OFS # Description
# Description
sub(/^ /, "", $5) # may have an empty space in front of line
sub(/%/, "%%", $5) # remove potential interpretation
gsub(/"/, "", $5) # remove nested quote(s)
printf "\"" $5 "\"" OFS
printf ($4 ~ /^Withdrawal$/ ? "OUT" : "IN") OFS # Direction
printf global_subaccount
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -74,7 +74,9 @@ function btcpayserver::print_warning()
# "Legacy Invoice" report
function btcpayserver::legacy()
{
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -126,9 +128,10 @@ function btcpayserver::legacy()
printf $21 OFS # InvoiceSubtotal
printf $22 OFS # InvoiceItemCode
# TODO: if description contains comma(s)?
# InvoiceItemDesc
sub(/%/, "%%", $23)
printf $23 OFS # InvoiceItemDesc
gsub(/"/, "", $23)
printf "\"" $23 "\"" OFS
printf $24 OFS # InvoiceFullStatus
printf $25 OFS # InvoiceStatus
@@ -141,7 +144,7 @@ function btcpayserver::legacy()
printf global_subaccount # Subaccount
printf "\n"
}' FS=, OFS=, "$global_in_path"
}' OFS=, "$global_in_path"
}
# "Payments" report
@@ -173,7 +176,9 @@ function btcpayserver::sales()
# "Wallets" report
function btcpayserver::wallets()
{
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -238,7 +243,7 @@ function btcpayserver::wallets()
printf global_subaccount # Subaccount
printf "\n"
}' FS=, OFS=, "$global_in_path"
}' OFS=, "$global_in_path"
}
function btcpayserver::parse()

View File

@@ -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
@@ -38,7 +38,9 @@ function parse_credit()
{
lib_preprocess::assert_header "Transaction Date,Posted Date,Card No.,Description,Category,Debit,Credit"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || !NF || $1 !~ global_year)
next
@@ -47,31 +49,35 @@ function parse_credit()
printf $2 OFS # Posted Date
printf $3 OFS # Card No.
# Description
sub(/%/, "%%", $4)
printf $4 OFS # Description
gsub(/"/, "", $4)
printf "\"" $4 "\"" OFS
printf $5 OFS # Category
printf "\"" $5 "\"" OFS # Category
# Debit = OUT, Credit = IN
direction=($6 ~ /[1-9]/ ? "OUT" : "IN")
# Amount
if (direction == "OUT") {printf $6 FS} # Debit
else {printf $7 FS} # Credit
if (direction == "OUT") {printf $6 OFS} # Debit
else {printf $7 OFS} # Credit
printf direction OFS
printf global_subaccount
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function parse_bank()
{
lib_preprocess::assert_header "Account Number,Transaction Description,Transaction Date,Transaction Type,Transaction Amount,Balance"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR>1 || NF)
{
@@ -88,11 +94,13 @@ function parse_bank()
printf $1 OFS # Account Number
# Transaction Description
sub(/%/, "%%", $2)
printf $2 OFS # Transaction Description
gsub(/"/, "", $2)
printf "\"" $2 "\"" OFS
printf $3 OFS # Transaction Date
printf $4 OFS # Transaction Type
printf "\"" $4 "\"" OFS # Transaction Type
printf $5 OFS # Transaction Amount
printf $6 OFS # Balance
@@ -104,7 +112,7 @@ function parse_bank()
printf "\n"
}
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -38,7 +38,9 @@ function parse_credit()
{
lib_preprocess::assert_header "Transaction Date,Post Date,Description,Category,Type,Amount,Memo"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -46,48 +48,57 @@ function parse_credit()
printf $1 OFS # Transaction Date
printf $2 OFS # Post Date
# Description
sub(/%/, "%%", $3)
printf $3 OFS # Description
gsub(/"/, "", $3)
printf "\"" $3 "\"" OFS
printf $4 OFS # Category
printf $5 OFS # Type
printf "\"" $4 "\"" OFS # Category
printf "\"" $5 "\"" OFS # Type
# Amount
direction=($6 ~ /^-/ ? "OUT" : "IN")
sub(/^-/, "", $6)
printf $6 OFS
printf $7 OFS # Memo
# Memo
sub(/%/, "%%", $7)
gsub(/"/, "", $7)
printf "\"" $7 "\"" OFS
printf direction OFS
printf global_subaccount
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function parse_bank()
{
lib_preprocess::assert_header "Details,Posting Date,Description,Amount,Type,Balance,Check or Slip #"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $2 !~ global_year)
next
printf $1 OFS # Details (CREDIT/DEBIT/DSLIP/etc.)
printf "\"" $1 "\"" OFS # Details (CREDIT/DEBIT/DSLIP/etc.)
printf $2 OFS # Posting Date
# Description
sub(/%/, "%%", $3)
printf $3 OFS # Description
gsub(/"/, "", $3)
printf "\"" $3 "\"" OFS
# Amount
direction=($4 ~ /^-/ ? "OUT" : "IN")
sub(/^-/, "", $4)
printf $4 OFS
printf $5 OFS # Type
printf "\"" $5 "\"" OFS # Type
printf $6 OFS # Balance
printf $7 OFS # Check or Slip #
@@ -96,7 +107,7 @@ function parse_bank()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -70,7 +70,9 @@ function join_to_header()
function __parse()
{
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $9 !~ global_year)
next
@@ -91,18 +93,18 @@ function __parse()
printf $3 OFS # info_type
printf $4 OFS # info_status
printf $5 OFS # info_amount_amount
printf $6 OFS # info_amount_currency
printf "\"" $6 "\"" OFS # info_amount_currency
printf $7 OFS # info_native_amount_amount
printf $8 OFS # info_native_amount_currency
printf "\"" $8 "\"" OFS # info_native_amount_currency
printf $9 OFS # info_created_at
printf $10 OFS # info_resource
printf $11 OFS # info_resource_path
printf $12 OFS # info_description
printf $13 OFS # info_network_status
printf $14 OFS # info_network_network_name
printf "\"" $14 "\"" OFS # info_network_network_name
printf $15 OFS # info_network_hash (txid)
printf("%.8f", $16); printf OFS # info_network_transaction_fee_amount
printf $17 OFS # info_network_transaction_fee_currency
printf "\"" $17 "\"" OFS # info_network_transaction_fee_currency
printf $18 OFS # info_to_resource
printf $19 OFS # info_to_address
printf $20 OFS # info_to_email
@@ -113,25 +115,37 @@ function __parse()
printf $25 OFS # info_cancelable
printf $26 OFS # info_idem
printf("%.8f", $27); printf OFS # info_buy_total_amount
printf $28 OFS # info_buy_total_currency
printf "\"" $28 "\"" OFS # info_buy_total_currency
printf("%.8f", $29); printf OFS # info_buy_subtotal_amount
printf $30 OFS # info_buy_subtotal_currency
printf "\"" $30 "\"" OFS # info_buy_subtotal_currency
printf("%.8f", $31); printf OFS # info_buy_fee_amount
printf $32 OFS # info_buy_fee_currency
printf "\"" $32 "\"" OFS # info_buy_fee_currency
printf $33 OFS # info_buy_id
printf $34 OFS # info_buy_payment_method_name
# info_buy_payment_method_name
gsub(/"/, "", $34);
printf "\"" $34 "\"" OFS
printf("%.8f", $35); printf OFS # info_sell_total_amount
printf $36 OFS # info_sell_total_currency
printf "\"" $36 "\"" OFS # info_sell_total_currency
printf("%.8f", $37); printf OFS # info_sell_subtotal_amount
printf $38 OFS # info_sell_subtotal_currency
printf "\"" $38 "\"" OFS # info_sell_subtotal_currency
printf("%.8f", $39); printf OFS # info_sell_fee_amount
printf $40 OFS # info_sell_fee_currency
printf "\"" $40 "\"" OFS # info_sell_fee_currency
printf $41 OFS # info_sell_id
printf $42 OFS # info_sell_payment_method_name
# info_sell_payment_method_name
gsub(/"/, "", $42);
printf "\"" $42 "\"" OFS
printf("%.8f", $43); printf OFS # info_trade_fee_amount
printf $44 OFS # info_trade_fee_currency
printf "\"" $44 "\"" OFS # info_trade_fee_currency
printf $45 OFS # info_trade_id
printf $46 OFS # info_trade_payment_method_name
# info_trade_payment_method_name
gsub(/"/, "", $46);
printf "\"" $46 "\"" OFS
printf("%.8f", $47); printf OFS # info_advanced_trade_fill_fill_price
printf $48 OFS # info_advanced_trade_fill_product_id
printf $49 OFS # info_advanced_trade_fill_order_id
@@ -185,8 +199,8 @@ function __parse()
#
split($48, pair, "-"); # Pair exists as advanced_trade_fill_product_id
printf pair[1] OFS # advanced_trade_fill_pair_lhs (left-hand side of the pair)
printf pair[2] OFS # advanced_trade_fill_pair_rhs (right-hand side of the pair)
printf "\"" pair[1] "\"" OFS # advanced_trade_fill_pair_lhs (left-hand side of the pair)
printf "\"" pair[2] "\"" OFS # advanced_trade_fill_pair_rhs (right-hand side of the pair)
#
# Advanced Trade: add column for cost-basis (comment2)
@@ -201,7 +215,7 @@ function __parse()
printf "\n";
}' FS=, OFS=,
}' OFS=,
}
#

View File

@@ -0,0 +1,20 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
include ../../algorand-shared.rules
# vim: sw=2 sts=2 si ai et

View File

@@ -0,0 +1 @@
../../algorand-shared.bash

View File

@@ -0,0 +1,20 @@
# docker-finance | modern accounting for the power-user
#
# Copyright (C) 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
include ../../ethereum-based-shared.rules
# vim: sw=2 sts=2 si ai et

View File

@@ -0,0 +1 @@
../../ethereum-based-shared.bash

View File

@@ -40,7 +40,9 @@ function parse_credit()
# NOTE: sed needed to remove CR. TODO: use gawk
sed 's:\r::g' "$global_in_path" \
| gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
| gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -49,38 +51,42 @@ function parse_credit()
printf $2 OFS # Post Date
# Description
gsub(/, /, " ") # may have comma(s) followed by space
sub(/%/, "%%", $3) # remove potential interpretation
printf $3 OFS
sub(/%/, "%%", $3)
gsub(/"/, "", $3)
printf "\"" $3 "\"" OFS
# Flip the amount signs for proper liabilities accounting
direction=($4 > 0 ? "OUT" : "IN")
sub("-", "", $4)
printf $4 OFS # Amount
printf $5 OFS # Category
printf "\"" $5 "\"" OFS # Category
printf direction OFS
printf global_subaccount
printf "\n"
}' FS=, OFS=, >"$global_out_path"
}' OFS=, >"$global_out_path"
}
function parse_bank()
{
lib_preprocess::assert_header "Transaction Date,Transaction Description,Transaction Type,Debit,Credit,Balance"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
printf $1 OFS # Transaction Date
# Transaction Description
sub(/%/, "%%", $2)
printf $2 OFS # Transaction Description
gsub(/"/, "", $2)
printf "\"" $2 "\"" OFS
printf $3 OFS # Transaction Type
@@ -99,7 +105,7 @@ function parse_bank()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -39,7 +39,9 @@ function parse_without-lightning-header()
{
lib_preprocess::assert_header "transaction_hash,label,confirmations,value,fiat_value,fee,fiat_fee,timestamp"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $8 !~ global_year)
next
@@ -61,7 +63,7 @@ function parse_without-lightning-header()
#
sub(/%/, "%%", $2)
printf $2 OFS
printf "\""; printf $2; printf "\"" OFS
#
# confirmations
@@ -128,7 +130,7 @@ function parse_without-lightning-header()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
# Since electrum 4.6.2
@@ -137,7 +139,9 @@ function parse_with-lightning-header()
{
lib_preprocess::assert_header "oc_transaction_hash,ln_payment_hash,label,confirmations,amount_chain_bc,amount_lightning_bc,fiat_value,network_fee_satoshi,fiat_fee,timestamp"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $10 !~ global_year)
next
@@ -159,7 +163,7 @@ function parse_with-lightning-header()
#
sub(/%/, "%%", $3)
printf $3 OFS
print "\""; printf $3; printf "\"" OFS
#
# confirmations
@@ -254,7 +258,7 @@ function parse_with-lightning-header()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -198,8 +198,10 @@ function parse_trades()
local _account_currency
_account_currency="$(echo $global_in_filename | cut -d"-" -f1 | sed 's:...$::')"
gawk -v account_currency="$_account_currency" \
-v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v account_currency="$_account_currency" \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2)
next
@@ -212,9 +214,13 @@ function parse_trades()
printf $9 OFS # UID (tid)
printf date OFS # Date
printf "TRADE" OFS # Type
printf $5 OFS # OrderType (type)
printf toupper(account_currency) OFS # CurrencyOne (account_currency)
printf $7 OFS # CurrencyTwo (fee_currency)
printf "\"" $5 "\"" OFS # OrderType (type)
# CurrencyOne (account_currency)
printf "\"" toupper(account_currency) "\"" OFS
# CurrencyTwo (fee_currency)
printf "\"" $7 "\"" OFS
# TODO: getline an gawk remove-zeros script
amount=sprintf("%.8f", $2)
@@ -271,14 +277,17 @@ function parse_trades()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function parse_earn()
{
lib_preprocess::assert_header "earnTransactionId,transactionId,transactionType,amountCurrency,amount,priceCurrency,priceAmount,dateTime"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" -M -v PREC=100 \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
-M -v PREC=100 \
'{
if (NR<2)
next
@@ -292,7 +301,7 @@ function parse_earn()
printf date OFS # Date
printf "INTEREST" OFS # Type
printf "EARN" OFS # OrderType (type)
printf $4 OFS # CurrencyOne (amountCurrency)
printf "\"" $4 "\""OFS # CurrencyOne (amountCurrency)
printf OFS # CurrencyTwo
# Amount
@@ -329,14 +338,16 @@ function parse_earn()
printf "\n";
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function parse_card()
{
lib_preprocess::assert_header "Reference Number,Transaction Post Date,Description of Transaction,Transaction Type,Amount"
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2)
next
@@ -350,8 +361,13 @@ function parse_card()
printf $1 OFS # Reference Number
printf $2 OFS # Transaction Post Date
printf $3 OFS # Description of Transaction
printf $4 OFS # Transaction Type
# Description of Transaction
gsub(/%/, "%%", $3)
gsub(/"/, "", $3)
printf "\"" $3 "\"" OFS
printf "\"" $4 "\"" OFS # Transaction Type
printf $5 OFS # Amount
direction=($5 ~ /^-/ ? "IN" : "OUT")
@@ -361,7 +377,7 @@ function parse_card()
printf "\n";
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -39,7 +39,8 @@ function parse()
# NOTE: subaccount (account label) is entered within app.
# Label your subaccount as subaccount1:subaccount2:etc
gawk -v global_year="$global_year" \
gawk --csv \
-v global_year="$global_year" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -53,9 +54,9 @@ function parse()
sub(/\.001Z/, "", $1)
printf $1 OFS # Operation Date
printf $2 OFS # Status
printf $3 OFS # Currency Ticker
printf $4 OFS # Operation Type
printf "\"" $2 "\"" OFS # Status
printf "\"" $3 "\"" OFS # Currency Ticker
printf "\"" $4 "\"" OFS # Operation Type
# Operation Amount (minus fee w/ this regexp)
amount=($4 ~ /^OUT$|^DELEGATE$/ ? $5-$6 : $5)
@@ -63,9 +64,13 @@ function parse()
printf("%.8f", $6); printf OFS # Operation Fees
printf $7 OFS # Operation Hash
printf $8 OFS # Account Name (subaccount)
# Account Name (subaccount)
gsub(/"/, "", $8)
printf "\"" $8 "\"" OFS
printf $9 OFS # Account xpub
printf $10 OFS # Countervalue Ticker
printf "\"" $10 "\"" OFS # Countervalue Ticker
printf $11 OFS # Countervalue at Operation Date
printf $12 OFS # Countervalue at CSV Export
@@ -74,7 +79,7 @@ function parse()
printf "\n"
}' FS=, OFS=, "$global_in_path" >"$global_out_path"
}' OFS=, "$global_in_path" >"$global_out_path"
}
function main()

View File

@@ -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
@@ -43,8 +43,9 @@ function parse()
# Paypal is known to allow commas within description ("Name") and amounts
# TODO: refactor xan/sed -> gawk (the sed line should remove non-csv commas and quotations)
xan select "$(echo "$_header" | sed 's:"::g')" $global_in_path \
| sed -e 's:, : :g' -e 's:,",:,:g' -e 's:,"\([0-9]*\),:,\1:g' -e 's:,"-\([0-9]*\),:,\1:g' -e 's:"::g' \
| gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
| gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -56,12 +57,14 @@ function parse()
printf $1 " " $2 OFS # Date/Time
# Name (description)
sub(/%/, "%%", $4)
printf $4 OFS # Name (description)
gsub(/"/, "", $4)
printf "\"" $4 "\"" OFS
printf $5 OFS # Type
printf $6 OFS # Status
printf $7 OFS # Currency
printf "\"" $5 "\"" OFS # Type
printf "\"" $6 "\"" OFS # Status
printf "\"" $7 "\"" OFS # Currency
# direction will be used in rules
sub(/^-/, "", $8)
@@ -72,8 +75,10 @@ function parse()
printf $13 OFS # Transaction ID
printf $(NF-4) OFS # Contact Phone Number
# Note
sub(/%/, "%%", $(NF-2))
printf $(NF-2) OFS # Note
gsub(/"/, "", $(NF-2))
printf "\"" $(NF-2) "\"" OFS
printf $(NF) OFS # Balance Impact
@@ -84,7 +89,7 @@ function parse()
printf "\n"
}' FS=, OFS=, >"$global_out_path"
}' OFS=, >"$global_out_path"
}
function main()

View File

@@ -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
@@ -47,10 +47,10 @@ function parse_report()
# Paypal is known to allow commas within description ("Name") and amounts
# NOTE: using custom timezone offset instead of provided timezone
# TODO: refactor xan/sed -> gawk (the sed line should remove non-csv commas and quotations)
xan select "Date,Time,Name,Type,Status,Currency,Amount,Fees,Total,Exchange Rate,Receipt ID,Balance,Transaction ID,Item Title" "$global_in_path" \
| sed -e 's:, : :g' -e 's:,",:,:g' -e 's:,"\([0-9]*\),:,\1:g' -e 's:,"-\([0-9]*\),:,-\1:g' -e 's:"::g' \
| gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
| gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -71,32 +71,44 @@ function parse_report()
# Print
printf timestamp OFS # timestamp
# description (Name)
sub(/%/, "%%", $3)
printf $3 OFS # description (Name)
gsub(/"/, "", $3)
printf "\"" $3 "\"" OFS
printf $4 OFS # type
printf $5 OFS # status
printf $6 OFS # currency
printf "\"" $4 "\"" OFS # type
printf "\"" $5 "\"" OFS # status
printf "\"" $6 "\"" OFS # currency
# amount
direction=($7 ~ /^-/ ? "OUT" : "IN")
sub(/^-/, "", $7)
printf $7 OFS # amount
gsub(/,/, "", $7)
printf "\"" $7 "\"" OFS
# fees
sub(/^-/, "", $8)
printf $8 OFS # fees
gsub(/,/, "", $8)
printf "\"" $8 "\"" OFS
# total
sub(/^-/, "", $9)
printf $9 OFS # total
gsub(/,/, "", $9)
printf "\"" $9 "\"" OFS
printf $10 OFS # exchange rate
# exchange rate
gsub(/,/, "", $10)
printf "\"" $10 "\"" OFS
printf $11 OFS # code (Receipt ID)
printf $12 OFS # balance
printf "\"" $11 "\"" OFS # code (Receipt ID)
printf "\"" $12 "\"" OFS # balance
printf $13 OFS # txid (Transaction ID)
printf $13 OFS # txid (Transaction ID)
# title (Item Title)
sub(/%/, "%%", $14)
printf $14 OFS # title (Item Title)
gsub(/"/, "", $14)
printf "\"" $14 "\"" OFS
printf direction OFS
printf global_subaccount OFS
@@ -110,7 +122,7 @@ function parse_report()
# fiat_value
printf "\n"
}' FS=, OFS=, >"$global_out_path"
}' OFS=, >"$global_out_path"
}
# NOTE: crypto transactions CSV, not crypto statement CSV
@@ -122,7 +134,9 @@ function parse_crypto()
# TODO: refactor into gawk after assert_header is fixed
xan select "DateTime,Transaction Type,Asset In (Quantity),Asset In (Currency),Asset Out (Quantity),Asset Out (Currency),Transaction Fee (Quantity),Transaction Fee (Currency),Market Value (USD)" <(tail +4 "$global_in_path") \
| gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" \
| gawk --csv \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
'{
if (NR<2 || $1 !~ global_year)
next
@@ -150,16 +164,19 @@ function parse_crypto()
printf OFS # direction
printf global_subaccount OFS
printf $3 OFS # in_value
printf $4 OFS # in_ticker
printf $5 OFS # out_value
printf $6 OFS # out_ticker
printf $7 OFS # tx_fee_value
printf $8 OFS # tx_fee_ticker
printf $3 OFS # in_value
printf "\"" $4 "\"" OFS # in_ticker
printf $5 OFS # out_value
printf "\"" $6 "\"" OFS # out_ticker
printf $7 OFS # tx_fee_value
printf "\"" $8 "\"" OFS # tx_fee_ticker
printf $9 # fiat_value
printf "\n"
}' FS=, OFS=, >"$global_out_path"
}' OFS=, >"$global_out_path"
}
function main()

View File

@@ -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
@@ -45,7 +45,10 @@ function parse()
_subaccount="$(echo $global_in_filename | cut -d'_' -f1)"
# NOTE: subaccount (account label) is entered within the app
gawk -v global_year="$global_year" -v global_subaccount="$global_subaccount" -v subaccount="$_subaccount" \
gawk \
-v global_year="$global_year" \
-v global_subaccount="$global_subaccount" \
-v subaccount="$_subaccount" \
'{
if (NR<2)
next
@@ -55,9 +58,6 @@ function parse()
if (date !~ global_year)
next
# Be rid of commas for OFS sake
gsub(/,/, "-")
# Timestamp provides UTC. UTC is used even though Time provides
# local timezone because fetching outside of the app provides UTC
printf date OFS # Timestamp
@@ -70,16 +70,18 @@ function parse()
printf $5 OFS # Transaction ID
printf $6 OFS # Fee
printf $7 OFS # Fee unit
printf "\"" $7 "\"" OFS # Fee unit
printf $8 OFS # Address
# Label
sub(/%/, "%%", $9)
printf $9 OFS # Label
gsub(/"/, "", $9)
printf "\"" $9 "\"" OFS
printf("%.8f", $10); printf OFS # Amount # TODO: more than 8 places for Ethereum, etc.?
printf $11 OFS # Amount unit
printf $12 OFS # Fiat (USD)
printf $13 OFS # Other
printf "\"" $11 "\"" OFS # Amount unit
printf "\"" $12 "\"" OFS # Fiat (USD)
printf "\"" $13 "\"" OFS # Other
printf direction OFS
printf global_subaccount":"subaccount

View File

@@ -26,8 +26,10 @@
#include <ctime>
#include <filesystem>
#include <initializer_list>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
@@ -274,6 +276,19 @@ int exec(const std::string& cmd)
return gSystem->Exec(cmd.c_str());
}
//! \brief Exit the interpreter with given status (and message)
//! \param code Exit code status (return code)
//! \param message Optional exit message
//! \since docker-finance 1.2.0
void exit(const int code, const std::string& message = {})
{
// TODO(unassigned): logger
if (!message.empty())
std::cout << "Exiting: '" << message << "'" << std::endl;
gSystem->Exit(code);
}
//! \brief Make current timestamp
//! \return timestamp in "yyyy-mm-ddThh:mm:ssZ" format
//! \since docker-finance 1.0.0
@@ -440,15 +455,15 @@ class PluggableSpace
"[a-zA-Z0-9:/_\\-\\.]+"} /* TODO(unassigned): refine */),
"invalid characters in pluggable space");
if (parsed.find('/'))
if (parsed.find('/')) // cppcheck-suppress stlIfStrFind
{
parsed = std::regex_replace(parsed, std::regex{"/"}, "::");
}
if (parsed.find('-'))
if (parsed.find('-')) // cppcheck-suppress stlIfStrFind
{
parsed = std::regex_replace(parsed, std::regex{"-"}, "_");
}
if (parsed.find('.'))
if (parsed.find('.')) // cppcheck-suppress stlIfStrFind
{
parsed = std::regex_replace(parsed, std::regex{"\\."}, "_");
}
@@ -619,11 +634,17 @@ class Pluggable
// Load pluggable file
::dfi::common::load(m_plug.path().absolute());
// Execute pluggable's loader
const std::string s{
// Prepare pluggable entry
const std::string entry{
"dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner()
+ "::" + m_plug.space().entry()};
::dfi::common::line(s + "::load(\"" + m_plug.args().load() + "\")");
// Allow quotations in loader argument
std::stringstream arg;
arg << std::quoted(m_plug.args().load());
// Execute pluggable's loader
::dfi::common::line(entry + "::load(" + arg.str() + ")");
return *this;
}
@@ -634,11 +655,17 @@ class Pluggable
//! \since docker-finance 1.1.0
const auto& unload() const
{
// Execute pluggable's unloader
const std::string s{
// Prepare pluggable entry
const std::string entry{
"dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner()
+ "::" + m_plug.space().entry()};
::dfi::common::line(s + "::unload(\"" + m_plug.args().unload() + "\")");
// Allow quotations in unloader argument
std::stringstream arg;
arg << std::quoted(m_plug.args().unload());
// Execute pluggable's unloader
::dfi::common::line(entry + "::unload(" + arg.str() + ")");
// Unload pluggable file
::dfi::common::unload(m_plug.path().absolute());

View File

@@ -141,7 +141,7 @@ class Plugin final
//!
//! Will load:
//!
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! and pass `using bar = char; bar b;` to the plugin's loader (plugin-implementation defined).
//!
@@ -178,12 +178,12 @@ void load(const common::PluginPath& path, const common::PluginArgs& args)
//! Will load:
//!
//! &emsp; `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! And pass plugin-implementation defined auto-loader arguments:
//!
//! &emsp; `using foo = int; foo f;` for `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n
@@ -228,7 +228,7 @@ void load(
//!
//! Will load:
//!
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! and pass `using bar = char; bar b;` to the plugin's loader (plugin-implementation defined).
//!
@@ -260,7 +260,7 @@ void load(const std::string& path, const std::string& arg = {})
//! Will load both:
//!
//! &emsp; ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc\n
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n
@@ -306,7 +306,7 @@ void load(const std::initializer_list<std::string>& paths)
//!
//! Will unload:
//!
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! and pass `using bar = char; bar b;` to the plugin's unloader (plugin-implementation defined).
//!
@@ -343,12 +343,12 @@ void unload(const common::PluginPath& path, const common::PluginArgs& args)
//! Will unload:
//!
//! &emsp; `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! And pass plugin-implementation defined auto-unloader arguments:
//!
//! &emsp; `using foo = int; foo f;` for `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n
@@ -393,7 +393,7 @@ void unload(
//!
//! Will unload:
//!
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! and pass `using bar = char; bar b;` to the plugin's unloader (plugin-implementation defined).
//!
@@ -425,7 +425,7 @@ void unload(const std::string& path, const std::string& arg = {})
//! Will unload both:
//!
//! &emsp; ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc\n
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n
@@ -497,12 +497,12 @@ void reload(const common::PluginPath& path, const common::PluginArgs& args)
//! Will reload:
//!
//! &emsp; `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! And pass plugin-implementation defined auto-loader arguments:
//!
//! &emsp; `using foo = int; foo f;` for `${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc`\n
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc`
//! &emsp; `using bar = char; bar b;` for `${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc`
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n
@@ -547,7 +547,7 @@ void reload(
//!
//! Will reload:
//!
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! and pass `using bar = char; bar b;` to the plugin's auto-unloader (plugin-implementation defined).
//!
@@ -581,7 +581,7 @@ void reload(
//! Will reload both:
//!
//! &emsp; ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example/example.cc\n
//! &emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example/example.cc
//! &emsp; ${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/example/example.cc
//!
//! \warning
//! To utilize plugin auto-(un)loader functionality, the plugin's parent directory *MUST* align with the plugin's namespace\n

View File

@@ -341,6 +341,12 @@ TEST_F(CommonFree, exec)
ASSERT_EQ(common::exec("pwd"), 0);
}
TEST_F(CommonFree, exit)
{
// NOTE: no-op (or else entire framework exits).
// Execution is covered in functional tests (gitea workflow).
}
TEST_F(CommonFree, make_timestamp)
{
ASSERT_EQ(common::make_timestamp().size(), 20);