bitvavo-api-upgraded 1.17.0__tar.gz → 1.17.2__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 (33) hide show
  1. bitvavo_api_upgraded-1.17.2/.github/copilot-instructions.md +109 -0
  2. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/.gitignore +1 -0
  3. bitvavo_api_upgraded-1.17.2/.python-version +5 -0
  4. bitvavo_api_upgraded-1.17.2/.vscode/settings.json +22 -0
  5. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/CHANGELOG.md +60 -0
  6. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/PKG-INFO +5 -4
  7. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/README.pypi.md +4 -0
  8. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/pyproject.toml +54 -53
  9. bitvavo_api_upgraded-1.17.2/src/bitvavo_api_upgraded/__init__.py +8 -0
  10. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/src/bitvavo_api_upgraded/bitvavo.py +8 -9
  11. bitvavo_api_upgraded-1.17.2/src/bitvavo_api_upgraded/settings.py +70 -0
  12. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/tests/conftest.py +7 -32
  13. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/tests/test_bitvavo.py +83 -66
  14. bitvavo_api_upgraded-1.17.2/tests/test_settings.py +36 -0
  15. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/tox.ini +7 -2
  16. bitvavo_api_upgraded-1.17.2/uv.lock +1444 -0
  17. bitvavo_api_upgraded-1.17.0/.python-version +0 -5
  18. bitvavo_api_upgraded-1.17.0/src/bitvavo_api_upgraded/__init__.py +0 -3
  19. bitvavo_api_upgraded-1.17.0/src/bitvavo_api_upgraded/settings.py +0 -47
  20. bitvavo_api_upgraded-1.17.0/uv.lock +0 -1266
  21. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/.github/README.md +0 -0
  22. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/.github/workflows/release.yml +0 -0
  23. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/.pre-commit-config.yaml +0 -0
  24. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/LICENSE.txt +0 -0
  25. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/README.md +0 -0
  26. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/docs/assets/bitvavo-mark-square-blue.svg +0 -0
  27. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/docs/rest.md +0 -0
  28. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/scripts/bootstrap.sh +0 -0
  29. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/src/bitvavo_api_upgraded/helper_funcs.py +0 -0
  30. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/src/bitvavo_api_upgraded/py.typed +0 -0
  31. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/src/bitvavo_api_upgraded/type_aliases.py +0 -0
  32. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/tests/__init__.py +0 -0
  33. {bitvavo_api_upgraded-1.17.0 → bitvavo_api_upgraded-1.17.2}/tests/test_helper_funcs.py +0 -0
@@ -0,0 +1,109 @@
1
+ # Bitvavo API Upgraded - AI Coding Assistant Instructions
2
+
3
+ ## Project Overview
4
+ This is a **typed, tested, and enhanced** Python wrapper for the Bitvavo cryptocurrency exchange API. It's an "upgraded" fork of the official Bitvavo SDK with comprehensive type hints, unit tests, and improved developer experience.
5
+
6
+ ## Architecture & Key Components
7
+
8
+ ### Core API Structure
9
+ - **Main class**: `Bitvavo` in `src/bitvavo_api_upgraded/bitvavo.py` - handles both REST and WebSocket operations
10
+ - **Dual API pattern**: REST methods return dict/list data directly; WebSocket methods use callbacks
11
+ - **WebSocket facade**: `WebSocketAppFacade` nested class provides WebSocket functionality with reconnection logic
12
+ - **Settings system**: Pydantic-based configuration in `src/bitvavo_api_upgraded/settings.py`
13
+
14
+ ### Project Layout (src-layout)
15
+ ```
16
+ src/bitvavo_api_upgraded/ # Source code
17
+ ├── __init__.py # Main exports
18
+ ├── bitvavo.py # Core API class (~3600 lines)
19
+ ├── settings.py # Pydantic settings
20
+ ├── helper_funcs.py # Utility functions
21
+ └── type_aliases.py # Type definitions
22
+ tests/ # Comprehensive test suite
23
+ ```
24
+
25
+ ## Development Workflows
26
+
27
+ ### Essential Commands
28
+ ```bash
29
+ # Development setup
30
+ uv sync # Install all dependencies
31
+ uv run tox # Run full test suite across Python versions
32
+
33
+ # Testing & Coverage
34
+ uv run pytest # Run tests with debugging support
35
+ uv run coverage run --source=src --module pytest # Coverage with proper src-layout
36
+ uv run coverage report # View coverage results
37
+
38
+ # Code Quality
39
+ uv run ruff format # Format code
40
+ uv run ruff check # Lint code
41
+ uv run mypy src/ # Type checking
42
+ ```
43
+
44
+ ### Coverage Configuration Notes
45
+ - Uses `coverage.py` instead of `pytest-cov` (breaks VS Code debugging)
46
+ - Requires `--source=src` for src-layout projects
47
+ - `tox.ini` sets `PYTHONPATH={toxinidir}/src` for proper module resolution
48
+
49
+ ## Project-Specific Patterns
50
+
51
+ ### Testing Strategy
52
+ - **Defensive testing**: Many tests skip risky operations (`@pytest.mark.skipif` for trading methods)
53
+ - **API flakiness**: Tests handle inconsistent Bitvavo API responses (see `conftest.py` market filtering)
54
+ - **WebSocket challenges**: Entire `TestWebsocket` class skipped due to freezing issues
55
+ - **Mock patterns**: Use `pytest-mock` for time functions and external dependencies
56
+
57
+ ### Type System & Error Handling
58
+ - **Strict typing**: `mypy` configured with `disallow_untyped_defs=true`
59
+ - **Return types**: Methods return `dict | list` for success, `errordict` for API errors
60
+ - **Type aliases**: Custom types like `ms` (milliseconds), `anydict` in `type_aliases.py`
61
+
62
+ ### Rate Limiting & Authentication
63
+ - **Weight-based limits**: Bitvavo uses 1000 points/minute, tracked in `rateLimitRemaining`
64
+ - **Settings pattern**: Use `BitvavoSettings` for API config, `BitvavoApiUpgradedSettings` for extras
65
+ - **Environment variables**: Load via `.env` file with `BITVAVO_APIKEY`/`BITVAVO_APISECRET`
66
+
67
+ ### Versioning & Release
68
+ - **Semantic versioning**: Automated with `bump-my-version`
69
+ - **Changelog-first**: Update `CHANGELOG.md` with `$UNRELEASED` token before version bumps
70
+ - **GitHub Actions**: Automated publishing on tag creation
71
+
72
+ ## Code Quality Standards
73
+
74
+ ### Linting Configuration
75
+ - **Ruff**: Replaces black, isort, flake8 with `select = ["ALL"]` and specific ignores
76
+ - **Line length**: 120 characters consistently across tools
77
+ - **Test exemptions**: Tests ignore safety checks (`S101`), magic values (`PLR2004`)
78
+
79
+ ### Documentation Patterns
80
+ - **Extensive docstrings**: WebSocket methods include JSON response examples
81
+ - **Rate limit documentation**: Each method documents its weight cost
82
+ - **API mirroring**: Maintains parity with official Bitvavo API documentation
83
+
84
+ ## Integration Points
85
+
86
+ ### External Dependencies
87
+ - **Bitvavo API**: REST at `api.bitvavo.com/v2`, WebSocket at `ws.bitvavo.com/v2/`
88
+ - **Key libraries**: `requests` (REST), `websocket-client` (WS), `pydantic-settings` (config)
89
+ - **Development tools**: `tox` (multi-version testing), `uv` (dependency management)
90
+
91
+ ### Configuration Management
92
+ - **Pydantic settings**: Type-safe config loading from environment/`.env`
93
+ - **Dual settings classes**: Separate original vs. enhanced functionality
94
+ - **Validation**: Custom validators for log levels, rate limits
95
+
96
+ ## Common Gotchas
97
+
98
+ 1. **Coverage setup**: Must use `--source=src` and set `PYTHONPATH` for src-layout
99
+ 2. **WebSocket testing**: Currently unreliable, most WS tests are skipped
100
+ 3. **Market filtering**: Some API responses include broken markets that tests filter out
101
+ 4. **VS Code debugging**: Disable `pytest-cov` extension to avoid conflicts with `coverage.py`
102
+ 5. **Rate limiting**: Always check `getRemainingLimit()` before making API calls
103
+
104
+ ## When Making Changes
105
+
106
+ - **Add tests**: Follow the defensive testing pattern, skip risky operations
107
+ - **Update types**: Maintain strict typing, update `type_aliases.py` if needed
108
+ - **Consider API changes**: This wrapper mirrors Bitvavo's API structure closely
109
+ - **Version bumps**: Update `CHANGELOG.md` first, then use `bump-my-version`
@@ -1,6 +1,7 @@
1
1
  /*
2
2
 
3
3
  # dirs
4
+ !.vscode/
4
5
  !.github/
5
6
  !requirements/
6
7
  !scripts/
@@ -0,0 +1,5 @@
1
+ 3.9.23
2
+ 3.10.18
3
+ 3.11.13
4
+ 3.12.11
5
+ 3.13.5
@@ -0,0 +1,22 @@
1
+ {
2
+ "workbench.colorCustomizations": {
3
+ "activityBar.activeBackground": "#05808b",
4
+ "activityBar.background": "#05808b",
5
+ "activityBar.foreground": "#e7e7e7",
6
+ "activityBar.inactiveForeground": "#e7e7e799",
7
+ "activityBarBadge.background": "#7b0471",
8
+ "activityBarBadge.foreground": "#e7e7e7",
9
+ "commandCenter.border": "#e7e7e799",
10
+ "sash.hoverBorder": "#05808b",
11
+ "statusBar.background": "#03535a",
12
+ "statusBar.foreground": "#e7e7e7",
13
+ "statusBarItem.hoverBackground": "#05808b",
14
+ "statusBarItem.remoteBackground": "#03535a",
15
+ "statusBarItem.remoteForeground": "#e7e7e7",
16
+ "titleBar.activeBackground": "#03535a",
17
+ "titleBar.activeForeground": "#e7e7e7",
18
+ "titleBar.inactiveBackground": "#03535a99",
19
+ "titleBar.inactiveForeground": "#e7e7e799"
20
+ },
21
+ "peacock.color": "#03535a"
22
+ }
@@ -1,5 +1,65 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.17.2 - 2025-08-01
4
+
5
+ Maintenance release, no functional changes. At least not from my side. I do note
6
+ the API has changed on Bitvavo's side, but I'll need to cover that soon enough.
7
+
8
+ ### Added
9
+
10
+ - `copilot-instructions.md`
11
+
12
+ ### Changed
13
+
14
+ - `structlog` v25 can now be used
15
+ - fixed `coverage` reporting
16
+ - it broke; don't know why; solution was to add `coverage combine` to
17
+ `tox.ini`
18
+
19
+ ## v1.17.1 - 2024-12-24
20
+
21
+ Turns out the settings weren't working as expected, so I switched
22
+ `python-decouple` out from `pydantic-settings`, which (once setup) works a lot
23
+ smoother. Keywords being "once setup", because holy smokes is it a paint to do
24
+ the initial setup - figure out how the hell you need to validate values before
25
+ or after, etc.
26
+
27
+ Just don't forget to create a local `.env` with `BITVAVO_APIKEY` and
28
+ `BITVAVO_APISECRET` keys.
29
+
30
+ ### Added
31
+
32
+ - `pydantic-settings`: a powerful and modern way of loading your settings.
33
+ - we're using `.env` here, but it can be setup for `.json` or `.yaml` -
34
+ whatever you fancy.
35
+ - because of `pydantic-settings` you can now also do
36
+ `Bitvavo(bitvavo_settings.model_dump())`, and import bitvavo_settings from
37
+ `settings.py`
38
+ - add pydantic plugin for mypy, so mypy stops complaining about pydantic.
39
+ - vscode settings to disable `pytest-cov` during debugging. If you do not
40
+ disable `pytest-cov` during debugging, it still silently break your debugging
41
+ system...
42
+ - you can now import BitvavoApiUpgradedSettings and BitvavoSettings directly
43
+ from `bitvavo_api_upgraded`
44
+
45
+ ### Changed
46
+
47
+ - `python-decouple` replaced by `pydantic-settings` - see Added and Removed
48
+ - `pytest-cov` relegated to enable coverage via vscode - friendship with
49
+ `pytest-cov` ended. `coverage.py` is my best friend.
50
+ - reason for this is because `pytest-cov` fucked with the ability to debug
51
+ within vscode.
52
+ - bump minor Python versions
53
+
54
+ ### Removed
55
+
56
+ - `python-decouple` - this lacked type hinting since forever, not to mention it
57
+ didn't throw errors if missing...
58
+
59
+ ### Fixed
60
+
61
+ - a bunch of tests that have VERY flaky output from the API >:(
62
+
3
63
  ## v1.17.0 - 2024-11-24
4
64
 
5
65
  Integrate all changes from Bitvavo's `v1.1.1` to `v1.4.2` lib versions,
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: bitvavo-api-upgraded
3
- Version: 1.17.0
3
+ Version: 1.17.2
4
4
  Summary: A unit-tested fork of the Bitvavo API
5
5
  Project-URL: homepage, https://github.com/Thaumatorium/bitvavo-api-upgraded
6
6
  Project-URL: repository, https://github.com/Thaumatorium/bitvavo-api-upgraded
@@ -9,6 +9,7 @@ Author: Bitvavo BV (original code)
9
9
  Author-email: NostraDavid <55331731+NostraDavid@users.noreply.github.com>
10
10
  Maintainer-email: NostraDavid <55331731+NostraDavid@users.noreply.github.com>
11
11
  License: ISC License
12
+ License-File: LICENSE.txt
12
13
  Classifier: Development Status :: 5 - Production/Stable
13
14
  Classifier: Environment :: Console
14
15
  Classifier: Framework :: Pytest
@@ -27,9 +28,9 @@ Classifier: Programming Language :: Python :: 3.12
27
28
  Classifier: Programming Language :: Python :: 3.13
28
29
  Classifier: Typing :: Typed
29
30
  Requires-Python: >=3.9
30
- Requires-Dist: python-decouple==3.*,>=3.5
31
+ Requires-Dist: pydantic-settings==2.*,>=2.6
31
32
  Requires-Dist: requests==2.*,>=2.26
32
- Requires-Dist: structlog==24.*,>=21.5
33
+ Requires-Dist: structlog==25.*,>=21.5
33
34
  Requires-Dist: websocket-client==1.*,>=1.2
34
35
  Description-Content-Type: text/markdown
35
36
 
@@ -41,6 +41,10 @@ some handy settings there.
41
41
  Here is an example list of the settings for this lib:
42
42
 
43
43
  ```ini
44
+ # needed for the private part of the API
45
+ BITVAVO_APIKEY=
46
+ BITVAVO_APISECRET=
47
+
44
48
  BITVAVO_API_UPGRADED_LOG_LEVEL=INFO # Set the lib's log level
45
49
  BITVAVO_API_UPGRADED_LOG_EXTERNAL_LEVEL=WARNING # Set the libs that are used by *this* lib's log level
46
50
  BITVAVO_API_UPGRADED_LAG=50 # the time difference between the server and your local time (you'll have to calculate this yourself - tip: use the bitvavo.time() functionality in a separate script)
@@ -1,7 +1,7 @@
1
1
  # https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html
2
2
  [project]
3
3
  name = "bitvavo-api-upgraded"
4
- version = "1.17.0"
4
+ version = "1.17.2"
5
5
  description = "A unit-tested fork of the Bitvavo API"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.9"
@@ -33,10 +33,10 @@ classifiers = [
33
33
  "Typing :: Typed",
34
34
  ]
35
35
  dependencies = [
36
- "python-decouple==3.*, >=3.5", # to handle sematic versioning
37
- "requests==2.*, >=2.26", # to make http requests
38
- "structlog==24.*, >=21.5", # for logging
39
- "websocket-client==1.*, >=1.2", # something something websocket
36
+ "pydantic-settings==2.*, >=2.6", # to handle settings
37
+ "requests==2.*, >=2.26", # to make http requests
38
+ "structlog==25.*, >=21.5", # for logging
39
+ "websocket-client==1.*, >=1.2", # something something websocket
40
40
  ]
41
41
 
42
42
  [project.urls]
@@ -44,18 +44,16 @@ homepage = "https://github.com/Thaumatorium/bitvavo-api-upgraded"
44
44
  repository = "https://github.com/Thaumatorium/bitvavo-api-upgraded"
45
45
  changelog = "https://github.com/Thaumatorium/bitvavo-api-upgraded/blob/master/CHANGELOG.md"
46
46
 
47
- [build-system]
48
- requires = ["hatchling"]
49
- build-backend = "hatchling.build"
50
-
51
- [dependency-groups]
52
- dev = [
47
+ # https://docs.astral.sh/uv/
48
+ [tool.uv]
49
+ dev-dependencies = [
53
50
  "bump-my-version>=0.28.1", # for version management of the lib
54
51
  "mdformat>=0.7.11", # for formatting markdown (.md) documents
55
52
  "mkdocs>=1.2.3", # for markdown documentation
56
53
  "mypy>=1.13", # amazing linter
57
54
  "pre-commit>=2.15.0", # for running hooks before committing code
58
- "pytest-cov>=1", # vscode has native coverage, but when using pytest, vscode will presume you'll use pytest-cov
55
+ "coverage[toml]>=7.6.9", # for checking coverage; use this in tox vs pytest-cov, since pytest-cov does NOT play well with vscode
56
+ "pytest-cov>=1", # though this was the initial choice over coverage.py, turns out it fucks with vscode debugging, so now it only exists so we can still run tests with coverage within vscode
59
57
  "pytest-integration>=0.2.2", # for @mark additions
60
58
  "pytest-mock>=3.6.1", # for the `mocker` MockerFixture fixture
61
59
  "pytest>=6.2.4", # you can run `pytest` to run the unit tests; will also be run by `tox` :)
@@ -65,8 +63,12 @@ dev = [
65
63
  "types-requests>=2.26.2", # typing for mypy
66
64
  ]
67
65
 
66
+ [build-system]
67
+ requires = ["hatchling"]
68
+ build-backend = "hatchling.build"
69
+
68
70
  [tool.bumpversion]
69
- current_version = "1.17.0"
71
+ current_version = "1.17.2"
70
72
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
71
73
  serialize = ["{major}.{minor}.{patch}"]
72
74
  search = "{current_version}"
@@ -96,7 +98,34 @@ filename = "CHANGELOG.md"
96
98
  search = "$UNRELEASED"
97
99
  replace = "v{new_version} - {now:%Y-%m-%d}"
98
100
 
99
- # https://mypy.readthedocs.io/en/stable/config_file.html#confval-exclude
101
+ [tool.coverage.run]
102
+ branch = true
103
+ source = ["bitvavo_api_upgraded"]
104
+ parallel = true
105
+ relative_files = true
106
+ omit = [
107
+ "docs/*",
108
+ "scripts/*",
109
+ "tests/*",
110
+ ]
111
+
112
+ [tool.coverage.paths]
113
+ omit = [
114
+ "*/__init__.py", # Optionally omit __init__ files
115
+ ]
116
+ [tool.coverage.report]
117
+ fail_under = 30
118
+ precision = 0
119
+ show_missing = true
120
+ skip_covered = true
121
+ skip_empty = true
122
+ sort = "Cover"
123
+ exclude_lines = [
124
+ "pragma: no cover", # Common usage for excluding lines from coverage
125
+ "if __name__ == .__main__.:", # Skip lines commonly used in scripts
126
+ ]
127
+
128
+ # https://mypy.readthedocs.io/en/stable/config_file.html
100
129
  [tool.mypy]
101
130
  # created for mypy 1.13
102
131
 
@@ -188,7 +217,7 @@ skip_version_check = false
188
217
  skip_cache_mtime_checks = false
189
218
 
190
219
  # Advanced options
191
- plugins = []
220
+ plugins = ["pydantic.mypy"]
192
221
  pdb = false
193
222
  show_traceback = false
194
223
  raise_exceptions = false
@@ -228,31 +257,6 @@ verbosity = 0
228
257
  # ]
229
258
  # ignore_missing_imports = true
230
259
 
231
- # PROGRAM SETTINGS
232
- [tool.coverage.run]
233
- branch = true
234
- source = ["bitvavo_api_upgraded"]
235
- parallel = true
236
- relative_files = true
237
-
238
- [tool.coverage.paths]
239
- source = [
240
- "src/bitvavo_api_upgraded",
241
- ".tox/py3*/lib/python3.*/site-packages/bitvavo_api_upgraded",
242
- ]
243
-
244
- [tool.coverage.report]
245
- fail_under = 50
246
- precision = 0
247
- show_missing = true
248
- skip_covered = true
249
- skip_empty = true
250
- sort = "Cover"
251
- exclude_lines = [
252
- "pragma: no cover", # Common usage for excluding lines from coverage
253
- "if __name__ == .__main__.:", # Skip lines commonly used in scripts
254
- ]
255
-
256
260
  [tool.black]
257
261
  line-length = 120
258
262
  include = "(src|tests)/.*.py"
@@ -263,19 +267,16 @@ profile = "black"
263
267
  src_paths = ["src", "tests"]
264
268
 
265
269
  [tool.pytest.ini_options]
266
- addopts = """
267
- --cov=bitvavo_api_upgraded
268
- --cov-branch
269
- --cov-report=term
270
- --cov-report=html
271
- --durations-min=1
272
- --verbosity=2
273
- --no-header
274
- --show-capture=all
275
- """
276
- # addopts = "--durations-min=1 --stepwise --verbosity=2 --no-header --show-capture=all"
277
- # addopts = "--durations=10 --durations-min=1 --stepwise --verbosity=1 --no-header"
278
- testpaths = ["tests"]
270
+ minversion = "8.0"
271
+ addopts = [
272
+ "--durations-min=1",
273
+ "--verbosity=2",
274
+ "--no-header",
275
+ "--show-capture=all",
276
+ ]
277
+
278
+ testpaths = ["tests/"]
279
+ pythonpath = ["src"]
279
280
  markers = ["no_cover: some pytest-integration default mark that's not known?."]
280
281
  python_classes = "Test*"
281
282
  python_files = "test_*.py"
@@ -0,0 +1,8 @@
1
+ from bitvavo_api_upgraded.bitvavo import Bitvavo
2
+ from bitvavo_api_upgraded.settings import BitvavoApiUpgradedSettings, BitvavoSettings
3
+
4
+ __all__ = [
5
+ "Bitvavo",
6
+ "BitvavoApiUpgradedSettings",
7
+ "BitvavoSettings",
8
+ ]
@@ -5,6 +5,7 @@ import hashlib
5
5
  import hmac
6
6
  import json
7
7
  import time
8
+ from pathlib import Path
8
9
  from threading import Thread
9
10
  from typing import Any, Callable
10
11
 
@@ -14,7 +15,7 @@ from structlog.stdlib import get_logger
14
15
  from websocket import WebSocketApp # missing stubs for WebSocketApp
15
16
 
16
17
  from bitvavo_api_upgraded.helper_funcs import configure_loggers, time_ms, time_to_wait
17
- from bitvavo_api_upgraded.settings import BITVAVO_API_UPGRADED
18
+ from bitvavo_api_upgraded.settings import bitvavo_upgraded_settings
18
19
  from bitvavo_api_upgraded.type_aliases import anydict, errordict, intdict, ms, s_f, strdict, strintdict
19
20
 
20
21
  configure_loggers()
@@ -158,9 +159,6 @@ def callback_example(response: Any) -> None:
158
159
  """
159
160
  if isinstance(response, dict):
160
161
  # instead of printing, you could save the object to a file:
161
- import json
162
- from pathlib import Path
163
-
164
162
  HERE = Path.cwd() # root of your project folder
165
163
  filepath = HERE / "your_output.json"
166
164
  # a = append; figure out yourself to create multiple callback functions, probably one for each type of call that
@@ -332,7 +330,7 @@ class Bitvavo:
332
330
  list[list[str]]
333
331
  ```
334
332
  """
335
- if (self.rateLimitRemaining - rateLimitingWeight) <= BITVAVO_API_UPGRADED.RATE_LIMITING_BUFFER:
333
+ if (self.rateLimitRemaining - rateLimitingWeight) <= bitvavo_upgraded_settings.RATE_LIMITING_BUFFER:
336
334
  self.sleep_until_can_continue()
337
335
  if self.debugging:
338
336
  logger.debug(
@@ -344,7 +342,7 @@ class Bitvavo:
344
342
  },
345
343
  )
346
344
  if self.APIKEY != "":
347
- now = time_ms() + BITVAVO_API_UPGRADED.LAG
345
+ now = time_ms() + bitvavo_upgraded_settings.LAG
348
346
  sig = createSignature(now, "GET", url.replace(self.base, ""), None, self.APISECRET)
349
347
  headers = {
350
348
  "bitvavo-access-key": self.APIKEY,
@@ -391,10 +389,10 @@ class Bitvavo:
391
389
  list[list[str]]
392
390
  ```
393
391
  """
394
- if (self.rateLimitRemaining - rateLimitingWeight) <= BITVAVO_API_UPGRADED.RATE_LIMITING_BUFFER:
392
+ if (self.rateLimitRemaining - rateLimitingWeight) <= bitvavo_upgraded_settings.RATE_LIMITING_BUFFER:
395
393
  self.sleep_until_can_continue()
396
394
  # if this method breaks: add `= {}` after `body: dict`
397
- now = time_ms() + BITVAVO_API_UPGRADED.LAG
395
+ now = time_ms() + bitvavo_upgraded_settings.LAG
398
396
  sig = createSignature(now, method, (endpoint + postfix), body, self.APISECRET)
399
397
  url = self.base + endpoint + postfix
400
398
  headers = {
@@ -591,6 +589,7 @@ class Bitvavo:
591
589
  "nonce": 10378032,
592
590
  "bids": [["1.1908", "600"], ["1.1902", "4091.359809"], ["1.1898", "7563"]],
593
591
  "asks": [["1.1917", "2382.166997"], ["1.1919", "440.7"], ["1.192", "600"]],
592
+ "timestamp": 1700000000000,
594
593
  }
595
594
 
596
595
  # Notice how each bid and ask is also a list
@@ -1832,7 +1831,7 @@ class Bitvavo:
1832
1831
  self.subscriptionBook(market, self.callbacks["subscriptionBookUser"][market])
1833
1832
 
1834
1833
  def on_open(self, ws: Any) -> None: # noqa: ARG002
1835
- now = time_ms() + BITVAVO_API_UPGRADED.LAG
1834
+ now = time_ms() + bitvavo_upgraded_settings.LAG
1836
1835
  self.open = True
1837
1836
  self.reconnectTimer = 0.5
1838
1837
  if self.APIKEY != "":
@@ -0,0 +1,70 @@
1
+ import logging
2
+ from pathlib import Path
3
+
4
+ from pydantic import Field, field_validator, model_validator
5
+ from pydantic_settings import BaseSettings, SettingsConfigDict
6
+
7
+ from bitvavo_api_upgraded.type_aliases import ms
8
+
9
+
10
+ class BitvavoApiUpgradedSettings(BaseSettings):
11
+ """
12
+ These settings provide extra functionality. Originally I wanted to combine
13
+ then, but I figured that would be a bad idea.
14
+ """
15
+
16
+ LOG_LEVEL: str = Field("INFO")
17
+ LOG_EXTERNAL_LEVEL: str = Field("WARNING")
18
+ LAG: ms = Field(ms(50))
19
+ RATE_LIMITING_BUFFER: int = Field(25)
20
+
21
+ # Configuration for Pydantic Settings
22
+ model_config = SettingsConfigDict(
23
+ env_file=Path.cwd() / ".env",
24
+ env_file_encoding="utf-8",
25
+ env_prefix="BITVAVO_API_UPGRADED_",
26
+ extra="ignore",
27
+ )
28
+
29
+ @classmethod
30
+ @field_validator("LOG_LEVEL", "LOG_EXTERNAL_LEVEL", mode="before")
31
+ def validate_log_level(cls, v: str) -> str:
32
+ if v not in logging._nameToLevel: # noqa: SLF001
33
+ msg = f"Invalid log level: {v}"
34
+ raise ValueError(msg)
35
+ return v
36
+
37
+
38
+ class BitvavoSettings(BaseSettings):
39
+ """
40
+ These are the base settings from the original library.
41
+ """
42
+
43
+ ACCESSWINDOW: int = Field(10_000)
44
+ API_RATING_LIMIT_PER_MINUTE: int = Field(default=1000)
45
+ API_RATING_LIMIT_PER_SECOND: int = Field(default=1000)
46
+ APIKEY: str = Field(default="BITVAVO_APIKEY is missing")
47
+ APISECRET: str = Field(default="BITVAVO_APISECRET is missing")
48
+ DEBUGGING: bool = Field(default=False)
49
+ RESTURL: str = Field(default="https://api.bitvavo.com/v2")
50
+ WSURL: str = Field(default="wss://ws.bitvavo.com/v2/")
51
+
52
+ # Configuration for Pydantic Settings
53
+ model_config = SettingsConfigDict(
54
+ env_file=Path.cwd() / ".env",
55
+ env_file_encoding="utf-8",
56
+ env_prefix="BITVAVO_",
57
+ extra="ignore",
58
+ )
59
+
60
+ @model_validator(mode="after")
61
+ def set_api_rating_limit_per_second(self) -> "BitvavoSettings":
62
+ self.API_RATING_LIMIT_PER_SECOND = self.API_RATING_LIMIT_PER_SECOND // 60
63
+ return self
64
+
65
+
66
+ # Initialize the settings
67
+ bitvavo_upgraded_settings = BitvavoApiUpgradedSettings()
68
+ BITVAVO_API_UPGRADED = bitvavo_upgraded_settings
69
+ bitvavo_settings = BitvavoSettings()
70
+ BITVAVO = bitvavo_settings
@@ -8,24 +8,14 @@ from typing import Any
8
8
  import pytest
9
9
 
10
10
  from bitvavo_api_upgraded.bitvavo import Bitvavo
11
- from bitvavo_api_upgraded.settings import BITVAVO
11
+ from bitvavo_api_upgraded.settings import bitvavo_settings
12
12
 
13
13
  logger = logging.getLogger("conftest")
14
14
 
15
15
 
16
16
  @pytest.fixture(scope="session")
17
17
  def bitvavo() -> Bitvavo:
18
- return Bitvavo(
19
- {
20
- # create a file called .env and put the keys there
21
- "APIKEY": BITVAVO.APIKEY,
22
- "APISECRET": BITVAVO.APISECRET,
23
- "RESTURL": BITVAVO.RESTURL,
24
- "WSURL": BITVAVO.WSURL,
25
- "ACCESSWINDOW": BITVAVO.ACCESSWINDOW,
26
- "DEBUGGING": BITVAVO.DEBUGGING,
27
- },
28
- )
18
+ return Bitvavo(bitvavo_settings.model_dump())
29
19
 
30
20
 
31
21
  @pytest.fixture(scope="session")
@@ -34,17 +24,7 @@ def websocket(bitvavo: Bitvavo) -> Bitvavo.WebSocketAppFacade:
34
24
  msg = f"Error callback: {error}"
35
25
  logger.error(msg)
36
26
 
37
- bitvavo = Bitvavo(
38
- {
39
- # create a file called .env and put the keys there
40
- "APIKEY": BITVAVO.APIKEY,
41
- "APISECRET": BITVAVO.APISECRET,
42
- "RESTURL": BITVAVO.RESTURL,
43
- "WSURL": BITVAVO.WSURL,
44
- "ACCESSWINDOW": BITVAVO.ACCESSWINDOW,
45
- "DEBUGGING": BITVAVO.DEBUGGING,
46
- },
47
- )
27
+ bitvavo = Bitvavo(bitvavo_settings.model_dump())
48
28
 
49
29
  websocket: Bitvavo.WebSocketAppFacade = bitvavo.newWebsocket()
50
30
  websocket.setErrorCallback(errorCallback)
@@ -58,18 +38,13 @@ def wrap_public_request(monkeypatch: pytest.MonkeyPatch, bitvavo: Bitvavo) -> No
58
38
  bit and is now generating output that doesn't conform to my tests, but since
59
39
  I presume that this output does not matter - typically it contains markets
60
40
  that are not in use anymore - I can remove them.
41
+
42
+ 2024-12-24: I kinda fixed the tests, so this may not be necessary anymore.
43
+ Maybe.
61
44
  """
62
45
  # Market exceptions to remove, as of 2024-11-11
63
46
  market_exceptions = [
64
- "BABYDOGE-EUR",
65
- "PEAQ-EUR",
66
- "UXLINK-EUR",
67
- "KLAY-EUR",
68
- "ORN-EUR",
69
- "DEGEN-EUR",
70
- "EUROC-USDC",
71
- "PNUT-EUR",
72
- "SYS-EUR",
47
+ "BABYDOGE-EUR", # left as example
73
48
  ]
74
49
  original_public_request = bitvavo.publicRequest
75
50