eth-portfolio-temp 0.2.5.dev0__tar.gz → 0.2.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.github/workflows/black.yaml +3 -0
  2. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.github/workflows/compile.yaml +20 -3
  3. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.github/workflows/release.yaml +48 -14
  4. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/PKG-INFO +4 -3
  5. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/exporter.rst +1 -1
  6. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_cache.py +2 -2
  7. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_db/utils.py +6 -8
  8. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_decimal.py +11 -10
  9. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_ledgers/address.py +1 -1
  10. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/token_transfer.py +1 -1
  11. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/transaction.py +1 -1
  12. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/utils.py +1 -1
  13. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_shitcoins.py +26 -0
  14. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_utils.py +1 -5
  15. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/buckets.py +1 -1
  16. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/liquity.py +1 -1
  17. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/maker.py +1 -1
  18. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/structs/structs.py +2 -2
  19. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/typing/__init__.py +4 -4
  20. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/_portfolio.py +11 -6
  21. eth_portfolio_temp-0.2.14/eth_portfolio_scripts/docker/check.py +67 -0
  22. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/docker-compose.yaml +2 -2
  23. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/docker_compose.py +11 -8
  24. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/main.py +2 -2
  25. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/PKG-INFO +4 -3
  26. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/requires.txt +3 -2
  27. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/top_level.txt +1 -1
  28. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/pyproject.toml +4 -3
  29. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/requirements.txt +3 -2
  30. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/setup.py +1 -0
  31. eth_portfolio_temp-0.2.5.dev0/eth_portfolio_scripts/docker/check.py +0 -56
  32. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.env.sample +0 -0
  33. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.github/workflows/deploy_docs.yaml +0 -0
  34. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.github/workflows/mypy.yaml +0 -0
  35. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/.gitignore +0 -0
  36. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/Makefile +0 -0
  37. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/README.md +0 -0
  38. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/brownie-config.yaml +0 -0
  39. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/Makefile +0 -0
  40. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/alabaster.css +0 -0
  41. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/basic.css +0 -0
  42. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/custom.css +0 -0
  43. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/doctools.js +0 -0
  44. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/documentation_options.js +0 -0
  45. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/file.png +0 -0
  46. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/language_data.js +0 -0
  47. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/minus.png +0 -0
  48. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/plus.png +0 -0
  49. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/pygments.css +0 -0
  50. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/searchtools.js +0 -0
  51. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/_build/html/_static/sphinx_highlight.js +0 -0
  52. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/caching.rst +0 -0
  53. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/conf.py +0 -0
  54. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/index.rst +0 -0
  55. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/make.bat +0 -0
  56. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/docs/new-protocols.rst +0 -0
  57. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/__init__.py +0 -0
  58. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_argspec.py +0 -0
  59. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_config.py +0 -0
  60. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_db/__init__.py +0 -0
  61. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_db/decorators.py +0 -0
  62. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_db/entities.py +0 -0
  63. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_decorators.py +0 -0
  64. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_exceptions.py +0 -0
  65. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_ledgers/__init__.py +0 -0
  66. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_ledgers/portfolio.py +0 -0
  67. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/__init__.py +0 -0
  68. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/_nonce.py +0 -0
  69. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_loaders/balances.py +0 -0
  70. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_stableish.py +0 -0
  71. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_submodules.py +0 -0
  72. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_ydb/__init__.py +0 -0
  73. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/_ydb/token_transfers.py +0 -0
  74. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/address.py +0 -0
  75. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/constants.py +0 -0
  76. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/portfolio.py +0 -0
  77. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/__init__.py +0 -0
  78. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/_base.py +0 -0
  79. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/convex.py +0 -0
  80. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/dsr.py +0 -0
  81. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/README.md +0 -0
  82. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/__init__.py +0 -0
  83. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/_base.py +0 -0
  84. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/compound.py +0 -0
  85. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/lending/unit.py +0 -0
  86. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/protocols/liquity.py +0 -0
  87. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/py.typed +0 -0
  88. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/structs/__init__.py +0 -0
  89. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/structs/modified.py +0 -0
  90. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio/typing/balance/single.py +0 -0
  91. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/__init__.py +0 -0
  92. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/_args.py +0 -0
  93. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/_logging.py +0 -0
  94. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/_utils.py +0 -0
  95. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/balances.py +0 -0
  96. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/.grafana/dashboards/Portfolio/Balances.json +0 -0
  97. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/.grafana/dashboards/dashboards.yaml +0 -0
  98. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/.grafana/datasources/datasources.yml +0 -0
  99. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/docker/__init__.py +0 -0
  100. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/py.typed +0 -0
  101. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/victoria/__init__.py +0 -0
  102. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_scripts/victoria/types.py +0 -0
  103. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/SOURCES.txt +0 -0
  104. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/dependency_links.txt +0 -0
  105. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/entry_points.txt +0 -0
  106. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/eth_portfolio_temp.egg-info/not-zip-safe +0 -0
  107. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/renovate.json +0 -0
  108. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/setup.cfg +0 -0
  109. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/_test_completeness.py +0 -0
  110. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/conftest.py +0 -0
  111. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/fixtures.py +0 -0
  112. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/protocols/test_external.py +0 -0
  113. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/scripts/test_utils.py +0 -0
  114. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/test_portfolio.py +0 -0
  115. {eth_portfolio_temp-0.2.5.dev0 → eth_portfolio_temp-0.2.14}/tests/test_typing.py +0 -0
@@ -4,6 +4,9 @@ on:
4
4
  pull_request:
5
5
  branches:
6
6
  - master
7
+ paths-ignore:
8
+ - '.github/workflows/**'
9
+ - '!.github/workflows/black.yaml'
7
10
 
8
11
  jobs:
9
12
  format:
@@ -4,6 +4,9 @@ on:
4
4
  pull_request:
5
5
  branches:
6
6
  - master
7
+ paths-ignore:
8
+ - '.github/workflows/**'
9
+ - '!.github/workflows/compile.yaml'
7
10
 
8
11
  concurrency:
9
12
  group: ${{ github.workflow }}-${{ github.ref }}
@@ -23,12 +26,26 @@ jobs:
23
26
  uses: actions/setup-python@v6
24
27
  with:
25
28
  python-version: "3.13"
26
-
27
- - name: Install Requirements
28
- run: pip install -r requirements.txt
29
+
30
+ - name: Delete existing build files
31
+ run: rm -rf build
29
32
 
30
33
  - name: Install Eth Portfolio
31
34
  run: pip install .
35
+
36
+ - name: Normalize C files for diffchecking
37
+ # This makes it much easier to diffcheck changes in the C files
38
+ run: |
39
+ # Insert DIFFCHECK_PLACEHOLDER macro at the top if not present
40
+ for f in build/*.c; do
41
+ if ! grep -q 'DIFFCHECK_PLACEHOLDER' "$f"; then
42
+ sed -i '1i#ifndef DIFFCHECK_PLACEHOLDER\n#define DIFFCHECK_PLACEHOLDER 0\n#endif' "$f"
43
+ fi
44
+ done
45
+ # Replace line number in CPy_AddTraceback with macro
46
+ sed -i 's/\(CPy_AddTraceback([^,]*, *[^,]*, *\)[0-9]\+\(, *[^)]*)\)/\1DIFFCHECK_PLACEHOLDER\2/g' build/*.c
47
+ # Replace index in CPyStatics[...] with macro
48
+ sed -i 's/CPyStatics\[[0-9]\+\]/CPyStatics[DIFFCHECK_PLACEHOLDER]/g' build/*.c
32
49
 
33
50
  - name: Check for changes
34
51
  run: |
@@ -5,6 +5,11 @@ on:
5
5
  branches:
6
6
  - master
7
7
  types: [published]
8
+ workflow_dispatch:
9
+ inputs:
10
+ fake_tag:
11
+ description: 'Fake tag name to use for dry run (e.g. v2.3.4)'
12
+ required: true
8
13
 
9
14
  jobs:
10
15
  build_wheels:
@@ -73,8 +78,19 @@ jobs:
73
78
  uses: actions/checkout@v5
74
79
  with:
75
80
  fetch-depth: 0
76
- fetch-tags: true
77
- ref: refs/tags/${{ github.event.release.tag_name }}
81
+
82
+ # ----------------------------------------------------
83
+ # Extract version from git tag or use fake tag for dry run (strip leading 'v')
84
+ # ----------------------------------------------------
85
+ - name: Extract version from tag
86
+ id: get_version
87
+ shell: bash
88
+ run: |
89
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
90
+ echo "version=$(echo '${{ github.event.inputs.fake_tag }}' | sed 's/^v//')" >> $GITHUB_OUTPUT
91
+ else
92
+ echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
93
+ fi
78
94
 
79
95
  - name: Set up Python
80
96
  uses: actions/setup-python@v6
@@ -95,11 +111,15 @@ jobs:
95
111
  CIBW_ARCHS_WINDOWS: ${{ matrix.cibw_archs_windows || '' }}
96
112
  # Which wheels to build for Linux (manylinux vs. musllinux)
97
113
  CIBW_BUILD: ${{ matrix.cibw_build || '' }}
114
+ # Use version from git tag (stripped 'v')
115
+ SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.get_version.outputs.version }}
116
+ # Pass version into Docker for Linux builds
117
+ CIBW_ENVIRONMENT: "SETUPTOOLS_SCM_PRETEND_VERSION=${{ steps.get_version.outputs.version }}"
98
118
  run: |
99
119
  python -m cibuildwheel --output-dir wheelhouse
100
120
 
101
121
  - name: Upload wheels
102
- uses: actions/upload-artifact@v4
122
+ uses: actions/upload-artifact@v5
103
123
  with:
104
124
  name: ${{ matrix.artifact_name }}
105
125
  path: wheelhouse/*.whl
@@ -113,8 +133,19 @@ jobs:
113
133
  uses: actions/checkout@v5
114
134
  with:
115
135
  fetch-depth: 0
116
- fetch-tags: true
117
- ref: refs/tags/${{ github.event.release.tag_name }}
136
+
137
+ # ----------------------------------------------------
138
+ # Extract version from git tag or use fake tag for dry run (strip leading 'v')
139
+ # ----------------------------------------------------
140
+ - name: Extract version from tag
141
+ id: get_version
142
+ shell: bash
143
+ run: |
144
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
145
+ echo "version=$(echo '${{ github.event.inputs.fake_tag }}' | sed 's/^v//')" >> $GITHUB_OUTPUT
146
+ else
147
+ echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
148
+ fi
118
149
 
119
150
  - name: Set up Python
120
151
  uses: actions/setup-python@v6
@@ -127,52 +158,55 @@ jobs:
127
158
  pip install setuptools wheel twine mypy[mypyc] types-aiofiles
128
159
 
129
160
  - name: Build sdist
130
- run: |
131
- python setup.py sdist
161
+ env:
162
+ # Use version from git tag (stripped 'v')
163
+ SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.get_version.outputs.version }}
164
+ run: python setup.py sdist
132
165
 
133
166
  # ----------------------------------------------------
134
167
  # Download wheels built on each runner
135
168
  # ----------------------------------------------------
136
169
  - name: Download manylinux 64-bit wheels
137
- uses: actions/download-artifact@v5
170
+ uses: actions/download-artifact@v6
138
171
  with:
139
172
  name: "wheels-ubuntu-latest-manylinux-x64"
140
173
  path: wheelhouse/linux-many-x64
141
174
 
142
175
  - name: Download manylinux 32-bit wheels
143
- uses: actions/download-artifact@v5
176
+ uses: actions/download-artifact@v6
144
177
  with:
145
178
  name: "wheels-ubuntu-latest-manylinux-x86"
146
179
  path: wheelhouse/linux-many-x86
147
180
 
148
181
  - name: Download musllinux 64-bit wheels
149
- uses: actions/download-artifact@v5
182
+ uses: actions/download-artifact@v6
150
183
  with:
151
184
  name: "wheels-ubuntu-latest-musllinux-x64"
152
185
  path: wheelhouse/linux-musl-x64
153
186
 
154
187
  - name: Download macOS wheels
155
- uses: actions/download-artifact@v5
188
+ uses: actions/download-artifact@v6
156
189
  with:
157
190
  name: "wheels-macos-latest"
158
191
  path: wheelhouse/macos
159
192
 
160
193
  - name: Download Windows 64-bit wheels
161
- uses: actions/download-artifact@v5
194
+ uses: actions/download-artifact@v6
162
195
  with:
163
196
  name: "wheels-windows-latest-x64"
164
197
  path: wheelhouse/windows-x64
165
198
 
166
199
  - name: Download Windows 32-bit wheels
167
- uses: actions/download-artifact@v5
200
+ uses: actions/download-artifact@v6
168
201
  with:
169
202
  name: "wheels-windows-latest-x86"
170
203
  path: wheelhouse/windows-x86
171
204
 
172
205
  # ----------------------------------------------------
173
- # Publish all built artifacts to PyPI
206
+ # Publish sdist and wheels to PyPI
174
207
  # ----------------------------------------------------
175
208
  - name: Publish sdist and wheels to PyPI
209
+ if: ${{ github.event_name != 'workflow_dispatch' }}
176
210
  env:
177
211
  TWINE_USERNAME: __token__
178
212
  TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eth_portfolio_temp
3
- Version: 0.2.5.dev0
3
+ Version: 0.2.14
4
4
  Summary: eth-portfolio makes it easy to analyze your portfolio.
5
5
  Home-page: https://github.com/BobTheBuidler/eth-portfolio
6
6
  Author: BobTheBuidler
@@ -8,15 +8,16 @@ Author-email: bobthebuidlerdefi@gmail.com
8
8
  Requires-Python: >=3.10,<3.14
9
9
  Requires-Dist: checksum_dict>=2.1.7
10
10
  Requires-Dist: dank_mids>=4.20.154
11
- Requires-Dist: eth-brownie<1.23,>=1.21.0
11
+ Requires-Dist: eth-brownie<1.23,>=1.22.0.dev0
12
12
  Requires-Dist: eth_retry<1,>=0.3.4
13
13
  Requires-Dist: evmspec>=0.4.1
14
14
  Requires-Dist: ez-a-sync>=0.32.27
15
+ Requires-Dist: faster-async-lru==2.0.5
15
16
  Requires-Dist: faster-eth-utils
16
17
  Requires-Dist: numpy<3
17
18
  Requires-Dist: pandas<3,>=1.4.3
18
19
  Requires-Dist: typed-envs>=0.0.9
19
- Requires-Dist: ypricemagic<5,>=4.6.29.dev0
20
+ Requires-Dist: ypricemagic<5,>=4.10.0
20
21
  Dynamic: author
21
22
  Dynamic: author-email
22
23
  Dynamic: home-page
@@ -34,7 +34,7 @@ The Portfolio Exporter supports several command-line options to customize its be
34
34
  The time interval between datapoints. default: 6h
35
35
 
36
36
  - ``--concurrency <concurrency>``
37
- The max number of historical blocks to export concurrently. default: 60
37
+ The max number of historical blocks to export concurrently. default: 40
38
38
 
39
39
  - ``--first-tx-block <block>``
40
40
  The block of your portfolio's first transaction, if known. This value, if provided, allows us to speed up processing of your data by limiting the block range we need to query. If not provided, the whole blockchain will be scanned. default: 0
@@ -30,7 +30,7 @@ def cache_to_disk(fn: Callable[P, T]) -> Callable[P, T]:
30
30
  cache_path_for_fn = f"{BASE_PATH}{fn.__module__.replace('.', '/')}/{name}"
31
31
  logger = getLogger(f"eth_portfolio.cache_to_disk.{name}")
32
32
 
33
- def get_cache_file_path(args, kwargs):
33
+ def get_cache_file_path(args: tuple[Any, ...], kwargs: dict[str, Any]) -> str:
34
34
  # Create a unique filename based on the function arguments
35
35
  key = md5(dumps((args, sorted(kwargs.items())))).hexdigest()
36
36
  return join(cache_path_for_fn, f"{key}.json")
@@ -46,7 +46,7 @@ def cache_to_disk(fn: Callable[P, T]) -> Callable[P, T]:
46
46
 
47
47
  queue: PriorityQueue = PriorityQueue()
48
48
 
49
- async def cache_deco_worker_coro(func) -> NoReturn:
49
+ async def cache_deco_worker_coro(func: Callable[..., Any]) -> NoReturn:
50
50
  try:
51
51
  while True:
52
52
  _, fut, cache_path, args, kwargs = await queue.get()
@@ -7,8 +7,7 @@ import evmspec
7
7
  import y._db.common
8
8
  import y._db.config as config
9
9
  from a_sync import PruningThreadPoolExecutor, a_sync
10
- from brownie import chain
11
- from eth_typing import ChecksumAddress
10
+ from eth_typing import ChecksumAddress, HexAddress
12
11
  from evmspec.data import _decode_hook
13
12
  from logging import getLogger
14
13
  from msgspec import ValidationError, json
@@ -32,7 +31,6 @@ from eth_portfolio._db.decorators import break_locks, requery_objs_on_diff_tx_er
32
31
  from eth_portfolio._db.entities import (
33
32
  AddressExtended,
34
33
  BlockExtended,
35
- ContractExtended,
36
34
  TokenExtended,
37
35
  )
38
36
  from eth_portfolio._decimal import Decimal
@@ -42,7 +40,7 @@ from eth_portfolio.typing import _P, _T, Fn
42
40
  logger = getLogger(__name__)
43
41
 
44
42
 
45
- def __bind():
43
+ def __bind() -> None:
46
44
  try:
47
45
  db.bind(**config.connection_settings)
48
46
  except BindingError as e:
@@ -176,7 +174,7 @@ def ensure_block(block: int) -> None:
176
174
  # )
177
175
 
178
176
 
179
- def is_token(address) -> bool:
177
+ def is_token(address: ChecksumAddress) -> bool:
180
178
  if address == EEE_ADDRESS:
181
179
  return False
182
180
  # with suppress(NonStandardERC20):
@@ -188,7 +186,7 @@ def is_token(address) -> bool:
188
186
  return get_event_loop().run_until_complete(_is_token(address))
189
187
 
190
188
 
191
- async def _is_token(address) -> bool:
189
+ async def _is_token(address: HexAddress) -> bool:
192
190
  # just breaking a weird lock, dont mind me
193
191
  if retval := await get_event_loop().run_in_executor(process, __is_token, address): # type: ignore [name-defined]
194
192
  logger.debug("%s is token")
@@ -197,7 +195,7 @@ async def _is_token(address) -> bool:
197
195
  return retval
198
196
 
199
197
 
200
- def __is_token(address) -> bool:
198
+ def __is_token(address: HexAddress) -> bool:
201
199
  with suppress(NonStandardERC20):
202
200
  erc = ERC20(address, asynchronous=True)
203
201
  if all(
@@ -322,7 +320,7 @@ async def get_transaction(sender: ChecksumAddress, nonce: int) -> Optional[Trans
322
320
  _decoded = 0
323
321
 
324
322
 
325
- async def _yield_to_loop():
323
+ async def _yield_to_loop() -> None:
326
324
  """dont let the event loop get congested, let your rpc begin work asap"""
327
325
  global _decoded
328
326
  _decoded += 1
@@ -3,6 +3,7 @@ import logging
3
3
  from typing import Union
4
4
 
5
5
  from evmspec.data import Wei
6
+ from typing_extensions import Self
6
7
 
7
8
 
8
9
  logger = logging.getLogger(__name__)
@@ -69,61 +70,61 @@ class Decimal(decimal.Decimal):
69
70
 
70
71
  return string
71
72
 
72
- def __add__(self, other):
73
+ def __add__(self, other) -> Self:
73
74
  try:
74
75
  return type(self)(super().__add__(other))
75
76
  except TypeError as e:
76
77
  raise TypeError(str(e), other) from e.__cause__
77
78
 
78
- def __radd__(self, other):
79
+ def __radd__(self, other) -> Self:
79
80
  try:
80
81
  return type(self)(super().__radd__(other))
81
82
  except TypeError as e:
82
83
  raise TypeError(str(e), other) from e.__cause__
83
84
 
84
- def __sub__(self, other):
85
+ def __sub__(self, other) -> Self:
85
86
  try:
86
87
  return type(self)(super().__sub__(other))
87
88
  except TypeError as e:
88
89
  raise TypeError(str(e), other) from e.__cause__
89
90
 
90
- def __rsub__(self, other):
91
+ def __rsub__(self, other) -> Self:
91
92
  try:
92
93
  return type(self)(super().__rsub__(other))
93
94
  except TypeError as e:
94
95
  raise TypeError(str(e), other) from e.__cause__
95
96
 
96
- def __mul__(self, other):
97
+ def __mul__(self, other) -> Self:
97
98
  try:
98
99
  return type(self)(super().__mul__(other))
99
100
  except TypeError as e:
100
101
  raise TypeError(str(e), other) from e.__cause__
101
102
 
102
- def __rmul__(self, other):
103
+ def __rmul__(self, other) -> Self:
103
104
  try:
104
105
  return type(self)(super().__rmul__(other))
105
106
  except TypeError as e:
106
107
  raise TypeError(str(e), other) from e.__cause__
107
108
 
108
- def __truediv__(self, other):
109
+ def __truediv__(self, other) -> Self:
109
110
  try:
110
111
  return type(self)(super().__truediv__(other))
111
112
  except TypeError as e:
112
113
  raise TypeError(str(e), other) from e.__cause__
113
114
 
114
- def __rtruediv__(self, other):
115
+ def __rtruediv__(self, other) -> Self:
115
116
  try:
116
117
  return type(self)(super().__rtruediv__(other))
117
118
  except TypeError as e:
118
119
  raise TypeError(str(e), other) from e.__cause__
119
120
 
120
- def __floordiv__(self, other):
121
+ def __floordiv__(self, other) -> Self:
121
122
  try:
122
123
  return type(self)(super().__floordiv__(other))
123
124
  except TypeError as e:
124
125
  raise TypeError(str(e), other) from e.__cause__
125
126
 
126
- def __rfloordiv__(self, other):
127
+ def __rfloordiv__(self, other) -> Self:
127
128
  try:
128
129
  return type(self)(super().__rfloordiv__(other))
129
130
  except TypeError as e:
@@ -37,13 +37,13 @@ import dank_mids
37
37
  import eth_retry
38
38
  from a_sync.asyncio import sleep0 as yield_to_loop
39
39
  from aiohttp import ClientResponseError
40
- from async_lru import alru_cache
41
40
  from brownie import chain
42
41
  from dank_mids.eth import TraceFilterParams
43
42
  from eth_typing import BlockNumber, ChecksumAddress
44
43
  from evmspec import FilterTrace
45
44
  from evmspec.structs.receipt import Status
46
45
  from evmspec.structs.trace import call, reward
46
+ from faster_async_lru import alru_cache
47
47
  from typing_extensions import Unpack
48
48
  from pandas import DataFrame # type: ignore
49
49
  from tqdm import tqdm
@@ -7,10 +7,10 @@ from logging import getLogger
7
7
  from typing import Final, Optional, Set
8
8
 
9
9
  from a_sync import create_task, gather
10
- from async_lru import alru_cache
11
10
  from dank_mids import BlockSemaphore
12
11
  from eth_typing import ChecksumAddress
13
12
  from evmspec.data import TransactionIndex
13
+ from faster_async_lru import alru_cache
14
14
  from msgspec import Struct, ValidationError
15
15
  from msgspec.json import decode
16
16
  from pony.orm import TransactionIntegrityError, UnexpectedError
@@ -15,9 +15,9 @@ import eth_retry
15
15
  import evmspec
16
16
  import msgspec
17
17
  from a_sync import SmartProcessingQueue
18
- from async_lru import alru_cache
19
18
  from eth_typing import ChecksumAddress
20
19
  from evmspec import data
20
+ from faster_async_lru import alru_cache
21
21
  from pony.orm import TransactionIntegrityError
22
22
  from y import get_price
23
23
  from y._decorators import stuck_coro_debugger
@@ -4,8 +4,8 @@ import dank_mids
4
4
  import eth_retry
5
5
  import msgspec
6
6
  from a_sync import SmartProcessingQueue
7
- from async_lru import alru_cache
8
7
  from eth_typing import HexStr
8
+ from faster_async_lru import alru_cache
9
9
  from y._decorators import stuck_coro_debugger
10
10
 
11
11
 
@@ -97,6 +97,21 @@ shitcoins: Final = {
97
97
  "0x0e1CD6d2715432e4DBedFE969b0Eb2867FF61d5b",
98
98
  "0x9aE357521153FB07bE6F5792CE7a49752638fbb7",
99
99
  # Generally looks like shit
100
+ "0xE8ED1fca5af1c7dd46A3D5bbDFf7e99749D9e0aa",
101
+ "0x00d0F0250364C431376cC64AADd3aa13c6A8998D",
102
+ "0x256099A072ea5fd35eC134758440413095967109",
103
+ "0xe975ACEb3b61a88A355B066D9cCC910CAb8b4853",
104
+ "0x59fF00f75b49089385377c7f7D905E193c9eb5e2",
105
+ "0x99304A346F8FD562336Fd3485301c02cEbE4F0ae",
106
+ "0x74b1C36268B5dC659aEEA588cb1683E96DaaB71a",
107
+ "0x92BF340B2c67be6911095675f744F9a3aD22d8F0",
108
+ "0xa635305B4a6A1E4A55Eb6A6B54a8D2a55e914F6f",
109
+ "0xC76f77Bff99Ec269050Ca929F4d37B00f012c65F",
110
+ "0x56BcBef8f5Ca4Fc224fE58187c66EA34d3A1ef4a",
111
+ "0xdc6050Ec75Bc4692333A1C301eB799e348d0b77e",
112
+ "0x0542e502cec25bD51b4f3461f4F704807FA1A6D8",
113
+ "0xc01e807Cc73469e9983B614A96847BC01332447d",
114
+ "0x87D38d662A4aae29BB60057e71AFf923C7523DC3",
100
115
  "0xDFC01a7956C0d151ae197274B974fA7527EbAFB9",
101
116
  "0xE256CF1C7caEff4383DabafEe6Dd53910F97213D",
102
117
  "0x7CD6143B8781dC7e0667e50DB02Eb6539799722F",
@@ -171,6 +186,17 @@ shitcoins: Final = {
171
186
  "0xB4d4334eB5a251cbE5cC7Afb0Ba26119aCE62281",
172
187
  "0xE5c5AE39B98eFd9D3c9E0F2a5457D98fFA4b0b46",
173
188
  # Generally looks like shit (symbol ERC20)
189
+ "0x2adA6e459089292264133d8D7c85f6907423E444",
190
+ "0x356F680eE21c8CeFfA460c38D20A137F3D07D9af",
191
+ "0x683eAca6CD17383FA93e95f17e7DE443666160eB",
192
+ "0x7452cc6Bd1FA968dd1672FF447f3D7ff1ce210A8",
193
+ "0x773F67800a6d79C0198E8Ac798658f80cb346083",
194
+ "0xaE977D03F5A3999c762eb42a203c436dFF3Df03C",
195
+ "0xbD67D76edFD88719efD7669583258209015B0aB5",
196
+ "0xd814cd86ed2e85156d9Cf3A9319261259458f50c",
197
+ "0xd0E6420b900dE49113B3404b437ee153Bf220B36",
198
+ "0xf1D1C6ea9166bcF97A099A1388E1663933bB2E48",
199
+ "0xF8B49aEC3E356f911f86F58Ff9204242d4b0e6A5",
174
200
  "0xe37be01D1337E77aCB0b4293DDb4D410D80010a7",
175
201
  "0x7EeAcC32C81e4D78E9705fBf0b977f5A858Bf0F3",
176
202
  "0x90133FF815ade1977EA2f1454dBC1d309EAA33f6",
@@ -18,9 +18,9 @@ from typing import (
18
18
 
19
19
  import dank_mids
20
20
  from a_sync import ASyncGenericBase, ASyncIterable, ASyncIterator, as_yielded
21
- from async_lru import alru_cache
22
21
  from brownie import chain
23
22
  from brownie.exceptions import ContractNotFound
23
+ from faster_async_lru import alru_cache
24
24
  from faster_eth_abi.exceptions import InsufficientDataBytes
25
25
  from eth_typing import ChecksumAddress
26
26
  from pandas import DataFrame # type: ignore
@@ -79,10 +79,6 @@ class Decimal(_decimal.Decimal):
79
79
 
80
80
  # TODO i forget why I had this lol, should I delete?
81
81
 
82
- def __init__(self, v) -> None:
83
- # assert not isinstance(v, _decimal.Decimal)
84
- super().__init__()
85
-
86
82
 
87
83
  async def _describe_err(token: AddressOrContract, block: Optional[Block]) -> str:
88
84
  """
@@ -2,8 +2,8 @@ import logging
2
2
  from typing import Any, Final, Optional, Set
3
3
 
4
4
  from a_sync import igather
5
- from async_lru import alru_cache
6
5
  from eth_typing import ChecksumAddress
6
+ from faster_async_lru import alru_cache
7
7
  from y.constants import CHAINID, STABLECOINS, WRAPPED_GAS_COIN
8
8
  from y.convert import to_address
9
9
  from y.datatypes import Address, AnyAddressType
@@ -1,6 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
- from async_lru import alru_cache
3
+ from faster_async_lru import alru_cache
4
4
  from y import Contract, Network, get_price
5
5
  from y._decorators import stuck_coro_debugger
6
6
  from y.constants import EEE_ADDRESS
@@ -2,10 +2,10 @@ from asyncio import gather
2
2
  from typing import Final, List, Optional
3
3
 
4
4
  from a_sync import igather
5
- from async_lru import alru_cache
6
5
  from brownie import ZERO_ADDRESS
7
6
  from dank_mids.exceptions import Revert
8
7
  from eth_typing import HexStr
8
+ from faster_async_lru import alru_cache
9
9
  from faster_eth_abi import encode
10
10
  from y import Contract, Network, contract_creation_block_async, get_price
11
11
  from y._decorators import stuck_coro_debugger
@@ -80,7 +80,7 @@ class _LedgerEntryBase(DictStruct, kw_only=True, frozen=True, omit_defaults=True
80
80
  The USD value of the cryptocurrency transferred in the {cls_name}, if price is known.
81
81
  """
82
82
 
83
- def __init_subclass__(cls, **kwargs):
83
+ def __init_subclass__(cls, **kwargs: Any) -> None:
84
84
  super().__init_subclass__(**kwargs)
85
85
 
86
86
  # Replace {cls_name} in attribute-level docstrings
@@ -273,7 +273,7 @@ class _TransactionBase(
273
273
  return self.transaction.yParity
274
274
 
275
275
  @property
276
- def __db_primary_key__(self):
276
+ def __db_primary_key__(self) -> Dict[str, tuple[int, Address] | int]:
277
277
  return {"from_address": (chain.id, self.from_address), "nonce": self.nonce}
278
278
 
279
279
 
@@ -43,7 +43,7 @@ from typing import (
43
43
  )
44
44
 
45
45
  from checksum_dict import DefaultChecksumDict
46
- from eth_typing import BlockNumber
46
+ from eth_typing import BlockNumber, HexAddress
47
47
  from pandas import DataFrame, concat
48
48
  from typing_extensions import ParamSpec, Self
49
49
  from y import Contract, ERC20
@@ -159,10 +159,10 @@ class TokenBalances(DefaultChecksumDict[Balance], _SummableNonNumericMixin): #
159
159
  raise
160
160
  self[token.address] += balance
161
161
 
162
- def __getitem__(self, key) -> Balance:
162
+ def __getitem__(self, key: HexAddress) -> Balance:
163
163
  return super().__getitem__(key) if key in self else Balance(token=key, block=self.block)
164
164
 
165
- def __setitem__(self, key, value):
165
+ def __setitem__(self, key: HexAddress, value: Balance) -> None:
166
166
  """
167
167
  Sets the balance for a given token address.
168
168
 
@@ -911,7 +911,7 @@ class PortfolioBalances(DefaultChecksumDict[WalletBalances], _SummableNonNumeric
911
911
  )
912
912
  self[wallet] += balances
913
913
 
914
- def __setitem__(self, key, value):
914
+ def __setitem__(self, key: HexAddress, value: WalletBalances) -> None:
915
915
  if not isinstance(value, WalletBalances):
916
916
  raise TypeError(
917
917
  f"value must be a `WalletBalances` object. You passed {value}"
@@ -35,13 +35,18 @@ logger: Final = getLogger("eth_portfolio")
35
35
  log_debug: Final = logger.debug
36
36
  log_error: Final = logger.error
37
37
 
38
+ _block_at_timestamp_semaphore: Final = a_sync.Semaphore(
39
+ 50, name="eth-portfolio get_block_at_timestamp"
40
+ )
41
+
38
42
 
39
43
  async def get_block_at_timestamp(dt: datetime) -> BlockNumber:
40
- while True:
41
- try:
42
- return await y.get_block_at_timestamp(dt, sync=False)
43
- except NoBlockFound:
44
- await asyncio.sleep(10)
44
+ async with _block_at_timestamp_semaphore:
45
+ while True:
46
+ try:
47
+ return await y.get_block_at_timestamp(dt, sync=False)
48
+ except NoBlockFound:
49
+ await asyncio.sleep(10)
45
50
 
46
51
 
47
52
  class ExportablePortfolio(Portfolio):
@@ -53,7 +58,7 @@ class ExportablePortfolio(Portfolio):
53
58
  *,
54
59
  start_block: int = 0,
55
60
  label: str = _DEFAULT_LABEL,
56
- concurrency: int = 60,
61
+ concurrency: int = 40,
57
62
  load_prices: bool = True,
58
63
  get_bucket: Callable[[ChecksumAddress], Awaitable[str]] = get_token_bucket,
59
64
  num_workers_transactions: int = 1000,