crypticorn 2.5.0rc4__tar.gz → 2.5.1__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.
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/PKG-INFO +7 -5
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/README.md +5 -4
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/main.py +2 -0
- crypticorn-2.5.1/crypticorn/client.py +122 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/__init__.py +2 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/auth.py +38 -20
- crypticorn-2.5.1/crypticorn/common/enums.py +27 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/errors.py +33 -14
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/exceptions.py +42 -25
- crypticorn-2.5.0rc4/crypticorn/common/enums.py → crypticorn-2.5.1/crypticorn/common/mixins.py +8 -28
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/urls.py +2 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/utils.py +4 -2
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/main.py +2 -0
- crypticorn-2.5.1/crypticorn/klines/client/__init__.py +55 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/__init__.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/change_in_timeframe_api.py +8 -22
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/funding_rates_api.py +8 -22
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/ohlcv_data_api.py +13 -33
- crypticorn-2.5.1/crypticorn/klines/client/api/status_api.py +260 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/symbols_api.py +14 -29
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/udf_api.py +48 -59
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api_client.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/configuration.py +1 -1
- crypticorn-2.5.1/crypticorn/klines/client/exceptions.py +220 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/__init__.py +33 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/api_error_identifier.py +108 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/api_error_level.py +37 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/api_error_type.py +37 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/change_in_timeframe.py +86 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/exception_detail.py +117 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/funding_rate.py +92 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/internal_exchange.py +39 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/market_type.py +35 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/ohlcv_history.py +105 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/resolution.py +1 -1
- crypticorn-2.5.1/crypticorn/klines/client/models/search_symbol.py +94 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/sort_direction.py +35 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/symbol_group.py +83 -0
- crypticorn-2.5.1/crypticorn/klines/client/models/symbol_info.py +131 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/symbol_type.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/timeframe.py +1 -1
- crypticorn-2.5.1/crypticorn/klines/client/models/udf_config.py +149 -0
- crypticorn-2.5.1/crypticorn/klines/client/rest.py +198 -0
- crypticorn-2.5.1/crypticorn/klines/main.py +91 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/__init__.py +7 -21
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/__init__.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/exchanges_api.py +36 -78
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/indicators_api.py +12 -37
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/logs_api.py +8 -23
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/marketcap_api.py +22 -73
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/markets_api.py +12 -40
- crypticorn-2.5.1/crypticorn/metrics/client/api/status_api.py +260 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/tokens_api.py +7 -21
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api_client.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/configuration.py +5 -3
- crypticorn-2.5.1/crypticorn/metrics/client/exceptions.py +220 -0
- crypticorn-2.5.1/crypticorn/metrics/client/models/__init__.py +25 -0
- {crypticorn-2.5.0rc4/crypticorn/trade → crypticorn-2.5.1/crypticorn/metrics}/client/models/api_error_identifier.py +6 -2
- {crypticorn-2.5.0rc4/crypticorn/trade → crypticorn-2.5.1/crypticorn/metrics}/client/models/api_error_level.py +2 -2
- {crypticorn-2.5.0rc4/crypticorn/trade → crypticorn-2.5.1/crypticorn/metrics}/client/models/api_error_type.py +2 -2
- crypticorn-2.5.1/crypticorn/metrics/client/models/exception_detail.py +117 -0
- crypticorn-2.5.1/crypticorn/metrics/client/models/internal_exchange.py +39 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/market_type.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/severity.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/time_interval.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/trading_status.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/rest.py +1 -1
- crypticorn-2.5.1/crypticorn/metrics/main.py +113 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/main.py +2 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/__init__.py +0 -3
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/configuration.py +2 -2
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/__init__.py +0 -3
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/bot_model.py +3 -7
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/execution_ids.py +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/notification_model.py +3 -12
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/order_model.py +3 -7
- crypticorn-2.5.1/crypticorn/trade/client/models/spot_trading_action.py +231 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/main.py +2 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/PKG-INFO +7 -5
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/SOURCES.txt +22 -5
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/requires.txt +1 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/pyproject.toml +1 -1
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/requirements/test.txt +1 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/tests/test_auth_client.py +14 -23
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/tests/test_config.py +2 -2
- crypticorn-2.5.1/tests/test_errors.py +54 -0
- crypticorn-2.5.0rc4/crypticorn/client.py +0 -131
- crypticorn-2.5.0rc4/crypticorn/common/sorter.py +0 -40
- crypticorn-2.5.0rc4/crypticorn/klines/client/__init__.py +0 -83
- crypticorn-2.5.0rc4/crypticorn/klines/client/exceptions.py +0 -220
- crypticorn-2.5.0rc4/crypticorn/klines/client/models/__init__.py +0 -61
- crypticorn-2.5.0rc4/crypticorn/klines/client/models/market_type.py +0 -35
- crypticorn-2.5.0rc4/crypticorn/klines/client/models/sort_direction.py +0 -35
- crypticorn-2.5.0rc4/crypticorn/klines/client/rest.py +0 -198
- crypticorn-2.5.0rc4/crypticorn/klines/main.py +0 -74
- crypticorn-2.5.0rc4/crypticorn/metrics/client/exceptions.py +0 -220
- crypticorn-2.5.0rc4/crypticorn/metrics/client/models/__init__.py +0 -39
- crypticorn-2.5.0rc4/crypticorn/metrics/main.py +0 -105
- crypticorn-2.5.0rc4/tests/test_errors.py +0 -39
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/admin_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/auth_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/service_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/user_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api/wallet_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api_client.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/configuration.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/exceptions.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/add_wallet200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/add_wallet_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/authorize_user200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/authorize_user200_response_auth.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/authorize_user_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/create_api_key200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/create_api_key_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/create_user_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/get_api_keys200_response_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_balances_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_balances_inner_sale_round.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_balances_inner_wallet.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_balances_inner_wallet_vesting_wallets_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_data_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/list_wallets200_response_user_value.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/logout_default_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/logout_default_response_issues_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/oauth_callback200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/oauth_callback200_response_user.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/refresh_token_info200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/refresh_token_info200_response_user_session.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/resend_verification_email_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/revoke_user_tokens_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/rotate_tokens200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/token_info200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/unlink_wallet_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/update_user_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/user_reset_password_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/user_set_password_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify_email200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify_email200_response_auth.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify_email200_response_auth_auth.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify_email_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/verify_wallet_request.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/wallet_verified200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/models/whoami200_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/auth/client/rest.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/cli/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/cli/__main__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/cli/init.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/cli/templates/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/cli/templates/auth.py +0 -0
- /crypticorn-2.5.0rc4/crypticorn/common/pydantic.py → /crypticorn-2.5.1/crypticorn/common/decorators.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/common/scopes.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api/data_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api/models_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api/status_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api_client.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/configuration.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/exceptions.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/coins.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/data_download_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/data_info.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/data_value_value_value_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/data_version.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/download_links.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/evaluation.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/evaluation_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/feature_size.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/http_validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/model_create.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/model_status.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/model_update.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/target.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/target_type.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/models/validation_error_loc_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/hive/client/rest.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api/health_check_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/base_response_health_check_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/base_response_list_change_in_timeframe_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/base_response_list_funding_rate_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/base_response_list_str.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/base_response_ohlcv_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/change_in_timeframe_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/error_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/exchange.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/funding_rate_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/health_check_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/history_error_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/history_no_data_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/history_success_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/http_validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/market.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/ohlcv_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/response_get_history_udf_history_get.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/response_get_udf_history.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/search_symbol_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/symbol_group_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/symbol_info_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/udf_config_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/models/validation_error_loc_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/klines/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api/health_check_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/base_response_dict.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/base_response_health_check_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/base_response_list_dict.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/base_response_list_exchange_mapping.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/base_response_list_str.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/error_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/exchange_mapping.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/health_check_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/http_validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/market.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/models/validation_error_loc_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/metrics/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api/now_payments_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api/payments_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api/products_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api/status_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api_client.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/configuration.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/exceptions.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/api_status_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/body_create_now_invoice.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/body_create_product.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/body_get_products.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/body_handle_now_webhook.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/body_update_product.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/combined_payment_history.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/create_invoice_req.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/create_invoice_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/currency.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/estimate_price_req.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/estimate_price_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/get_currencies_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/get_payment_status_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/get_payments_list_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/http_validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/min_amount_req.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/min_amount_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_api_status_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_create_invoice_req.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_create_invoice_res.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_fee_structure.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_payment_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_payment_status.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/now_webhook_payload.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/partial_product_update_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/payment.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/payment_status.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_create.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_read.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_sub_read.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_subs_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_update.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/product_update_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/scope.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/services.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/unified_payment_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/models/validation_error_loc_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/pay/client/rest.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/__init__.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/api_keys_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/bots_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/exchanges_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/futures_trading_panel_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/notifications_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/orders_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/status_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/strategies_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api/trading_actions_api.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api_client.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/api_response.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/exceptions.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/action_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/api_key_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/bot_status.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/exchange.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/exchange_key_model.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/futures_balance.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/futures_trading_action.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/http_validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/margin_mode.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/market_type.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/order_status.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/post_futures_action.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/strategy_exchange_info.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/strategy_model_input.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/strategy_model_output.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/tpsl.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/trading_action_type.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/validation_error.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/models/validation_error_loc_inner.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/py.typed +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn/trade/client/rest.py +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/dependency_links.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/entry_points.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/crypticorn.egg-info/top_level.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/requirements/dev.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/requirements/extra.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/requirements/main.txt +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/setup.cfg +0 -0
- {crypticorn-2.5.0rc4 → crypticorn-2.5.1}/tests/test_enums.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: crypticorn
|
3
|
-
Version: 2.5.
|
3
|
+
Version: 2.5.1
|
4
4
|
Summary: Maximise Your Crypto Trading Profits with AI Predictions
|
5
5
|
Author-email: Crypticorn <timon@crypticorn.com>
|
6
6
|
Project-URL: Homepage, https://crypticorn.com
|
@@ -36,6 +36,7 @@ Requires-Dist: pytest==8.3.5; extra == "test"
|
|
36
36
|
Requires-Dist: pytest-asyncio==0.26.0; extra == "test"
|
37
37
|
Requires-Dist: pytest-cov==6.1.1; extra == "test"
|
38
38
|
Requires-Dist: python-dotenv==1.0.1; extra == "test"
|
39
|
+
Requires-Dist: PyJWT==2.10.0; extra == "test"
|
39
40
|
Provides-Extra: extra
|
40
41
|
Requires-Dist: pandas<3.0.0,>=2.2.0; extra == "extra"
|
41
42
|
|
@@ -86,7 +87,7 @@ The `common` submodule contains shared classes not bound to a specific API.
|
|
86
87
|
from crypticorn.common import Scope, Exchange
|
87
88
|
```
|
88
89
|
|
89
|
-
## Usage
|
90
|
+
## Basic Usage
|
90
91
|
|
91
92
|
### With Async Context Protocol
|
92
93
|
```python
|
@@ -107,6 +108,7 @@ async def main():
|
|
107
108
|
|
108
109
|
asyncio.run(main())
|
109
110
|
asyncio.run(client.close())
|
111
|
+
|
110
112
|
## Response Types
|
111
113
|
|
112
114
|
There are three different available output formats you can choose from:
|
@@ -155,12 +157,12 @@ The output would look like this:
|
|
155
157
|
|
156
158
|
## Advanced Usage
|
157
159
|
|
158
|
-
You can override some configuration for specific
|
160
|
+
You can override some configuration for specific services. If you just want to use the API as is, you don't need to configure anything.
|
159
161
|
This might be of use if you are testing a specific API locally.
|
160
162
|
|
161
|
-
To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default
|
163
|
+
To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default proxy, you would do:
|
162
164
|
```python
|
163
165
|
from crypticorn.hive import Configuration as Hiveconfig
|
164
166
|
async with ApiClient(base_url=BaseUrl.DEV) as client:
|
165
|
-
client.configure(config=HiveConfig(host="http://localhost:8000"),
|
167
|
+
client.configure(config=HiveConfig(host="http://localhost:8000"), client=client.hive)
|
166
168
|
```
|
@@ -45,7 +45,7 @@ The `common` submodule contains shared classes not bound to a specific API.
|
|
45
45
|
from crypticorn.common import Scope, Exchange
|
46
46
|
```
|
47
47
|
|
48
|
-
## Usage
|
48
|
+
## Basic Usage
|
49
49
|
|
50
50
|
### With Async Context Protocol
|
51
51
|
```python
|
@@ -66,6 +66,7 @@ async def main():
|
|
66
66
|
|
67
67
|
asyncio.run(main())
|
68
68
|
asyncio.run(client.close())
|
69
|
+
|
69
70
|
## Response Types
|
70
71
|
|
71
72
|
There are three different available output formats you can choose from:
|
@@ -114,12 +115,12 @@ The output would look like this:
|
|
114
115
|
|
115
116
|
## Advanced Usage
|
116
117
|
|
117
|
-
You can override some configuration for specific
|
118
|
+
You can override some configuration for specific services. If you just want to use the API as is, you don't need to configure anything.
|
118
119
|
This might be of use if you are testing a specific API locally.
|
119
120
|
|
120
|
-
To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default
|
121
|
+
To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default proxy, you would do:
|
121
122
|
```python
|
122
123
|
from crypticorn.hive import Configuration as Hiveconfig
|
123
124
|
async with ApiClient(base_url=BaseUrl.DEV) as client:
|
124
|
-
client.configure(config=HiveConfig(host="http://localhost:8000"),
|
125
|
+
client.configure(config=HiveConfig(host="http://localhost:8000"), client=client.hive)
|
125
126
|
```
|
@@ -0,0 +1,122 @@
|
|
1
|
+
from typing import TypeVar
|
2
|
+
from crypticorn.hive import HiveClient
|
3
|
+
from crypticorn.klines import KlinesClient
|
4
|
+
from crypticorn.pay import PayClient
|
5
|
+
from crypticorn.trade import TradeClient
|
6
|
+
from crypticorn.metrics import MetricsClient
|
7
|
+
from crypticorn.auth import AuthClient
|
8
|
+
from crypticorn.common import BaseUrl, ApiVersion, Service, apikey_header as aph
|
9
|
+
|
10
|
+
ConfigT = TypeVar("ConfigT")
|
11
|
+
SubClient = TypeVar("SubClient")
|
12
|
+
|
13
|
+
|
14
|
+
class ApiClient:
|
15
|
+
"""
|
16
|
+
The official client for interacting with the Crypticorn API.
|
17
|
+
|
18
|
+
It is consisting of multiple microservices covering the whole stack of the Crypticorn project.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
api_key: str = None,
|
24
|
+
jwt: str = None,
|
25
|
+
base_url: BaseUrl = BaseUrl.PROD,
|
26
|
+
):
|
27
|
+
self.base_url = base_url
|
28
|
+
"""The base URL the client will use to connect to the API."""
|
29
|
+
self.api_key = api_key
|
30
|
+
"""The API key to use for authentication."""
|
31
|
+
self.jwt = jwt
|
32
|
+
"""The JWT to use for authentication."""
|
33
|
+
|
34
|
+
self.service_classes: dict[Service, type[SubClient]] = {
|
35
|
+
Service.HIVE: HiveClient,
|
36
|
+
Service.TRADE: TradeClient,
|
37
|
+
Service.KLINES: KlinesClient,
|
38
|
+
Service.PAY: PayClient,
|
39
|
+
Service.METRICS: MetricsClient,
|
40
|
+
Service.AUTH: AuthClient,
|
41
|
+
}
|
42
|
+
|
43
|
+
self.services: dict[Service, SubClient] = {
|
44
|
+
service: client_class(self._get_default_config(service))
|
45
|
+
for service, client_class in self.service_classes.items()
|
46
|
+
}
|
47
|
+
|
48
|
+
@property
|
49
|
+
def hive(self) -> HiveClient:
|
50
|
+
return self.services[Service.HIVE]
|
51
|
+
|
52
|
+
@property
|
53
|
+
def trade(self) -> TradeClient:
|
54
|
+
return self.services[Service.TRADE]
|
55
|
+
|
56
|
+
@property
|
57
|
+
def klines(self) -> KlinesClient:
|
58
|
+
return self.services[Service.KLINES]
|
59
|
+
|
60
|
+
@property
|
61
|
+
def metrics(self) -> MetricsClient:
|
62
|
+
return self.services[Service.METRICS]
|
63
|
+
|
64
|
+
@property
|
65
|
+
def pay(self) -> PayClient:
|
66
|
+
return self.services[Service.PAY]
|
67
|
+
|
68
|
+
@property
|
69
|
+
def auth(self) -> AuthClient:
|
70
|
+
return self.services[Service.AUTH]
|
71
|
+
|
72
|
+
async def close(self):
|
73
|
+
"""Close all client sessions."""
|
74
|
+
for service in self.services.values():
|
75
|
+
if hasattr(service.base_client, "close"):
|
76
|
+
await service.base_client.close()
|
77
|
+
|
78
|
+
def _get_default_config(
|
79
|
+
self, service: Service, version: ApiVersion = ApiVersion.V1
|
80
|
+
):
|
81
|
+
"""
|
82
|
+
Get the default configuration for a given service.
|
83
|
+
"""
|
84
|
+
config_class = self.service_classes[service].config_class
|
85
|
+
return config_class(
|
86
|
+
host=f"{self.base_url}/{version}/{service}",
|
87
|
+
access_token=self.jwt,
|
88
|
+
api_key={aph.scheme_name: self.api_key} if self.api_key else None,
|
89
|
+
)
|
90
|
+
|
91
|
+
def configure(
|
92
|
+
self,
|
93
|
+
config: ConfigT,
|
94
|
+
service: Service,
|
95
|
+
):
|
96
|
+
"""
|
97
|
+
Update a sub-client's configuration by overriding with the values set in the new config.
|
98
|
+
Useful for testing a specific service against a local server instead of the default proxy.
|
99
|
+
|
100
|
+
:param config: The new configuration to use for the sub-client.
|
101
|
+
:param service: The service to configure.
|
102
|
+
|
103
|
+
Example:
|
104
|
+
>>> async with ApiClient(base_url=BaseUrl.DEV, jwt=jwt) as client:
|
105
|
+
>>> client.configure(config=HiveConfig(host="http://localhost:8000"), client=client.hive)
|
106
|
+
"""
|
107
|
+
assert Service.validate(service), f"Invalid service: {service}"
|
108
|
+
client = self.services[service]
|
109
|
+
new_config = client.config
|
110
|
+
|
111
|
+
for attr in vars(config):
|
112
|
+
new_value = getattr(config, attr)
|
113
|
+
if new_value:
|
114
|
+
setattr(new_config, attr, new_value)
|
115
|
+
|
116
|
+
self.services[service] = type(client)(new_config)
|
117
|
+
|
118
|
+
async def __aenter__(self):
|
119
|
+
return self
|
120
|
+
|
121
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
122
|
+
await self.close()
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from crypticorn.common.errors import *
|
2
2
|
from crypticorn.common.scopes import *
|
3
3
|
from crypticorn.common.urls import *
|
4
|
-
from crypticorn.common.
|
4
|
+
from crypticorn.common.decorators import *
|
5
|
+
from crypticorn.common.mixins import *
|
5
6
|
from crypticorn.common.auth import *
|
6
7
|
from crypticorn.common.enums import *
|
7
8
|
from crypticorn.common.utils import *
|
@@ -2,14 +2,10 @@ import json
|
|
2
2
|
|
3
3
|
from crypticorn.auth import Verify200Response, AuthClient, Configuration
|
4
4
|
from crypticorn.auth.client.exceptions import ApiException
|
5
|
-
from crypticorn.common import
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
Scope,
|
10
|
-
Service,
|
11
|
-
)
|
12
|
-
from fastapi import Depends, HTTPException, Query, status, WebSocketException
|
5
|
+
from crypticorn.common.scopes import Scope
|
6
|
+
from crypticorn.common.exceptions import ApiError, HTTPException, ExceptionContent
|
7
|
+
from crypticorn.common.urls import BaseUrl, Service, ApiVersion
|
8
|
+
from fastapi import Depends, Query, status, WebSocketException
|
13
9
|
from fastapi.security import (
|
14
10
|
HTTPAuthorizationCredentials,
|
15
11
|
SecurityScopes,
|
@@ -48,11 +44,6 @@ class AuthHandler:
|
|
48
44
|
self.url = f"{base_url}/{ApiVersion.V1}/{Service.AUTH}"
|
49
45
|
self.client = AuthClient(Configuration(host=self.url))
|
50
46
|
|
51
|
-
self.no_credentials_exception = HTTPException(
|
52
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
53
|
-
detail=ApiError.NO_CREDENTIALS.identifier,
|
54
|
-
)
|
55
|
-
|
56
47
|
async def _verify_api_key(self, api_key: str) -> Verify200Response:
|
57
48
|
"""
|
58
49
|
Verifies the API key.
|
@@ -76,8 +67,10 @@ class AuthHandler:
|
|
76
67
|
"""
|
77
68
|
if not set(api_scopes).issubset(user_scopes):
|
78
69
|
raise HTTPException(
|
79
|
-
|
80
|
-
|
70
|
+
content=ExceptionContent(
|
71
|
+
error=ApiError.INSUFFICIENT_SCOPES,
|
72
|
+
message="Insufficient scopes to access this resource",
|
73
|
+
),
|
81
74
|
)
|
82
75
|
|
83
76
|
async def _extract_message(self, e: ApiException) -> str:
|
@@ -100,16 +93,33 @@ class AuthHandler:
|
|
100
93
|
Handles exceptions and returns a HTTPException with the appropriate status code and detail.
|
101
94
|
"""
|
102
95
|
if isinstance(e, ApiException):
|
96
|
+
# handle the TRPC Zod errors from auth-service
|
97
|
+
# Unfortunately, we cannot share the error messages defined in python/crypticorn/common/errors.py with the typescript client
|
98
|
+
message = await self._extract_message(e)
|
99
|
+
if message == "Invalid API key":
|
100
|
+
error = ApiError.INVALID_API_KEY
|
101
|
+
elif message == "API key expired":
|
102
|
+
error = ApiError.EXPIRED_API_KEY
|
103
|
+
elif message == "jwt expired":
|
104
|
+
error = ApiError.EXPIRED_BEARER
|
105
|
+
else:
|
106
|
+
error = (
|
107
|
+
ApiError.INVALID_BEARER
|
108
|
+
) # jwt malformed, jwt not active (https://www.npmjs.com/package/jsonwebtoken#errors--codes)
|
103
109
|
return HTTPException(
|
104
|
-
|
105
|
-
|
110
|
+
content=ExceptionContent(
|
111
|
+
error=error,
|
112
|
+
message=message,
|
113
|
+
),
|
106
114
|
)
|
107
115
|
elif isinstance(e, HTTPException):
|
108
116
|
return e
|
109
117
|
else:
|
110
118
|
return HTTPException(
|
111
|
-
|
112
|
-
|
119
|
+
content=ExceptionContent(
|
120
|
+
error=ApiError.UNKNOWN_ERROR,
|
121
|
+
message=str(e),
|
122
|
+
),
|
113
123
|
)
|
114
124
|
|
115
125
|
async def api_key_auth(
|
@@ -172,7 +182,15 @@ class AuthHandler:
|
|
172
182
|
last_error = await self._handle_exception(e)
|
173
183
|
continue
|
174
184
|
|
175
|
-
|
185
|
+
if last_error:
|
186
|
+
raise last_error
|
187
|
+
else:
|
188
|
+
raise HTTPException(
|
189
|
+
content=ExceptionContent(
|
190
|
+
error=ApiError.NO_CREDENTIALS,
|
191
|
+
message="No credentials provided",
|
192
|
+
),
|
193
|
+
)
|
176
194
|
|
177
195
|
async def ws_api_key_auth(
|
178
196
|
self,
|
@@ -0,0 +1,27 @@
|
|
1
|
+
from enum import StrEnum
|
2
|
+
from crypticorn.common.mixins import ValidateEnumMixin, ExcludeEnumMixin
|
3
|
+
class Exchange(ValidateEnumMixin, ExcludeEnumMixin, StrEnum):
|
4
|
+
"""Supported exchanges for trading"""
|
5
|
+
|
6
|
+
KUCOIN = "kucoin"
|
7
|
+
BINGX = "bingx"
|
8
|
+
|
9
|
+
|
10
|
+
class InternalExchange(ValidateEnumMixin, ExcludeEnumMixin, StrEnum):
|
11
|
+
"""All exchanges we are using, including public (Exchange)"""
|
12
|
+
|
13
|
+
KUCOIN = "kucoin"
|
14
|
+
BINGX = "bingx"
|
15
|
+
BINANCE = "binance"
|
16
|
+
BYBIT = "bybit"
|
17
|
+
HYPERLIQUID = "hyperliquid"
|
18
|
+
BITGET = "bitget"
|
19
|
+
|
20
|
+
|
21
|
+
class MarketType(ValidateEnumMixin, ExcludeEnumMixin, StrEnum):
|
22
|
+
"""
|
23
|
+
Market types
|
24
|
+
"""
|
25
|
+
|
26
|
+
SPOT = "spot"
|
27
|
+
FUTURES = "futures"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from enum import Enum, EnumMeta, StrEnum
|
2
2
|
import logging
|
3
3
|
from fastapi import status
|
4
|
+
from crypticorn.common.mixins import ExcludeEnumMixin
|
4
5
|
|
5
6
|
logger = logging.getLogger(__name__)
|
6
7
|
|
@@ -18,7 +19,7 @@ class Fallback(EnumMeta):
|
|
18
19
|
return cls.UNKNOWN_ERROR
|
19
20
|
|
20
21
|
|
21
|
-
class ApiErrorType(StrEnum):
|
22
|
+
class ApiErrorType(ExcludeEnumMixin, StrEnum):
|
22
23
|
"""Type of API error"""
|
23
24
|
|
24
25
|
USER_ERROR = "user error"
|
@@ -31,11 +32,12 @@ class ApiErrorType(StrEnum):
|
|
31
32
|
"""error that does not need to be handled or does not affect the program or is a placeholder."""
|
32
33
|
|
33
34
|
|
34
|
-
class ApiErrorIdentifier(StrEnum):
|
35
|
+
class ApiErrorIdentifier(ExcludeEnumMixin, StrEnum):
|
35
36
|
"""API error identifiers"""
|
36
37
|
|
37
38
|
ALLOCATION_BELOW_EXPOSURE = "allocation_below_current_exposure"
|
38
39
|
ALLOCATION_BELOW_MINIMUM = "allocation_below_min_amount"
|
40
|
+
ALPHANUMERIC_CHARACTERS_ONLY = "alphanumeric_characters_only"
|
39
41
|
BLACK_SWAN = "black_swan"
|
40
42
|
BOT_ALREADY_DELETED = "bot_already_deleted"
|
41
43
|
BOT_DISABLED = "bot_disabled"
|
@@ -56,6 +58,9 @@ class ApiErrorIdentifier(StrEnum):
|
|
56
58
|
EXCHANGE_SYSTEM_CONFIG_ERROR = "exchange_system_configuration_error"
|
57
59
|
EXCHANGE_SYSTEM_ERROR = "exchange_internal_system_error"
|
58
60
|
EXCHANGE_USER_FROZEN = "exchange_user_account_is_frozen"
|
61
|
+
EXPIRED_API_KEY = "api_key_expired"
|
62
|
+
EXPIRED_BEARER = "bearer_token_expired"
|
63
|
+
FORBIDDEN = "forbidden"
|
59
64
|
HEDGE_MODE_NOT_ACTIVE = "hedge_mode_not_active"
|
60
65
|
HTTP_ERROR = "http_request_error"
|
61
66
|
INSUFFICIENT_BALANCE = "insufficient_balance"
|
@@ -68,7 +73,6 @@ class ApiErrorIdentifier(StrEnum):
|
|
68
73
|
INVALID_EXCHANGE_KEY = "invalid_exchange_key"
|
69
74
|
INVALID_MARGIN_MODE = "invalid_margin_mode"
|
70
75
|
INVALID_PARAMETER = "invalid_parameter_provided"
|
71
|
-
JWT_EXPIRED = "jwt_expired"
|
72
76
|
LEVERAGE_EXCEEDED = "leverage_limit_exceeded"
|
73
77
|
LIQUIDATION_PRICE_VIOLATION = "order_violates_liquidation_price_constraints"
|
74
78
|
NO_CREDENTIALS = "no_credentials"
|
@@ -108,7 +112,7 @@ class ApiErrorIdentifier(StrEnum):
|
|
108
112
|
return ApiError[self.value]
|
109
113
|
|
110
114
|
|
111
|
-
class ApiErrorLevel(StrEnum):
|
115
|
+
class ApiErrorLevel(ExcludeEnumMixin, StrEnum):
|
112
116
|
"""API error levels"""
|
113
117
|
|
114
118
|
ERROR = "error"
|
@@ -117,7 +121,7 @@ class ApiErrorLevel(StrEnum):
|
|
117
121
|
WARNING = "warning"
|
118
122
|
|
119
123
|
|
120
|
-
class ApiError(Enum, metaclass=Fallback):
|
124
|
+
class ApiError(ExcludeEnumMixin, Enum, metaclass=Fallback):
|
121
125
|
"""API error codes. Fallback to UNKNOWN_ERROR for error codes not yet published to PyPI."""
|
122
126
|
|
123
127
|
ALLOCATION_BELOW_EXPOSURE = (
|
@@ -130,6 +134,11 @@ class ApiError(Enum, metaclass=Fallback):
|
|
130
134
|
ApiErrorType.USER_ERROR,
|
131
135
|
ApiErrorLevel.ERROR,
|
132
136
|
)
|
137
|
+
ALPHANUMERIC_CHARACTERS_ONLY = (
|
138
|
+
ApiErrorIdentifier.ALPHANUMERIC_CHARACTERS_ONLY,
|
139
|
+
ApiErrorType.USER_ERROR,
|
140
|
+
ApiErrorLevel.ERROR,
|
141
|
+
)
|
133
142
|
BLACK_SWAN = (
|
134
143
|
ApiErrorIdentifier.BLACK_SWAN,
|
135
144
|
ApiErrorType.USER_ERROR,
|
@@ -230,6 +239,21 @@ class ApiError(Enum, metaclass=Fallback):
|
|
230
239
|
ApiErrorType.USER_ERROR,
|
231
240
|
ApiErrorLevel.ERROR,
|
232
241
|
)
|
242
|
+
EXPIRED_API_KEY = (
|
243
|
+
ApiErrorIdentifier.EXPIRED_API_KEY,
|
244
|
+
ApiErrorType.USER_ERROR,
|
245
|
+
ApiErrorLevel.ERROR,
|
246
|
+
)
|
247
|
+
EXPIRED_BEARER = (
|
248
|
+
ApiErrorIdentifier.EXPIRED_BEARER,
|
249
|
+
ApiErrorType.USER_ERROR,
|
250
|
+
ApiErrorLevel.ERROR,
|
251
|
+
)
|
252
|
+
FORBIDDEN = (
|
253
|
+
ApiErrorIdentifier.FORBIDDEN,
|
254
|
+
ApiErrorType.USER_ERROR,
|
255
|
+
ApiErrorLevel.ERROR,
|
256
|
+
)
|
233
257
|
HEDGE_MODE_NOT_ACTIVE = (
|
234
258
|
ApiErrorIdentifier.HEDGE_MODE_NOT_ACTIVE,
|
235
259
|
ApiErrorType.USER_ERROR,
|
@@ -290,11 +314,6 @@ class ApiError(Enum, metaclass=Fallback):
|
|
290
314
|
ApiErrorType.SERVER_ERROR,
|
291
315
|
ApiErrorLevel.ERROR,
|
292
316
|
)
|
293
|
-
JWT_EXPIRED = (
|
294
|
-
ApiErrorIdentifier.JWT_EXPIRED,
|
295
|
-
ApiErrorType.SERVER_ERROR,
|
296
|
-
ApiErrorLevel.ERROR,
|
297
|
-
)
|
298
317
|
LEVERAGE_EXCEEDED = (
|
299
318
|
ApiErrorIdentifier.LEVERAGE_EXCEEDED,
|
300
319
|
ApiErrorType.SERVER_ERROR,
|
@@ -475,19 +494,18 @@ class ApiError(Enum, metaclass=Fallback):
|
|
475
494
|
|
476
495
|
class HttpStatusMapper:
|
477
496
|
"""Map API errors to HTTP status codes."""
|
478
|
-
|
479
|
-
# TODO: decide if we need all of these mappings, since most errors are not exposed to the client via HTTP
|
480
|
-
# in case we remove some, update the pytest length check
|
481
497
|
_mapping = {
|
482
498
|
# Authentication/Authorization
|
483
|
-
ApiError.
|
499
|
+
ApiError.EXPIRED_BEARER: status.HTTP_401_UNAUTHORIZED,
|
484
500
|
ApiError.INVALID_BEARER: status.HTTP_401_UNAUTHORIZED,
|
501
|
+
ApiError.EXPIRED_API_KEY: status.HTTP_401_UNAUTHORIZED,
|
485
502
|
ApiError.INVALID_API_KEY: status.HTTP_401_UNAUTHORIZED,
|
486
503
|
ApiError.NO_CREDENTIALS: status.HTTP_401_UNAUTHORIZED,
|
487
504
|
ApiError.INSUFFICIENT_SCOPES: status.HTTP_403_FORBIDDEN,
|
488
505
|
ApiError.EXCHANGE_PERMISSION_DENIED: status.HTTP_403_FORBIDDEN,
|
489
506
|
ApiError.EXCHANGE_USER_FROZEN: status.HTTP_403_FORBIDDEN,
|
490
507
|
ApiError.TRADING_LOCKED: status.HTTP_403_FORBIDDEN,
|
508
|
+
ApiError.FORBIDDEN: status.HTTP_403_FORBIDDEN,
|
491
509
|
# Not Found
|
492
510
|
ApiError.URL_NOT_FOUND: status.HTTP_404_NOT_FOUND,
|
493
511
|
ApiError.OBJECT_NOT_FOUND: status.HTTP_404_NOT_FOUND,
|
@@ -519,6 +537,7 @@ class HttpStatusMapper:
|
|
519
537
|
ApiError.POSITION_SUSPENDED: status.HTTP_503_SERVICE_UNAVAILABLE,
|
520
538
|
ApiError.TRADING_SUSPENDED: status.HTTP_503_SERVICE_UNAVAILABLE,
|
521
539
|
# Bad Requests (400) - Invalid parameters or states
|
540
|
+
ApiError.ALPHANUMERIC_CHARACTERS_ONLY: status.HTTP_400_BAD_REQUEST,
|
522
541
|
ApiError.ALLOCATION_BELOW_EXPOSURE: status.HTTP_400_BAD_REQUEST,
|
523
542
|
ApiError.ALLOCATION_BELOW_MINIMUM: status.HTTP_400_BAD_REQUEST,
|
524
543
|
ApiError.BLACK_SWAN: status.HTTP_400_BAD_REQUEST,
|
@@ -1,35 +1,40 @@
|
|
1
|
-
from
|
2
|
-
from typing import Optional, Dict, Type
|
1
|
+
from typing import Optional, Dict, Any
|
3
2
|
from pydantic import BaseModel, Field
|
4
3
|
from fastapi import HTTPException as FastAPIHTTPException, Request, FastAPI
|
5
4
|
from fastapi.exceptions import RequestValidationError, ResponseValidationError
|
6
|
-
from fastapi.openapi.utils import get_openapi
|
7
5
|
from fastapi.responses import JSONResponse
|
8
6
|
from crypticorn.common import ApiError, ApiErrorIdentifier, ApiErrorType, ApiErrorLevel
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
|
9
|
+
class ExceptionDetail(BaseModel):
|
10
|
+
"""This is the detail of the exception. It is used to enrich the exception with additional information by unwrapping the ApiError into its components."""
|
11
|
+
|
12
12
|
message: Optional[str] = Field(None, description="An additional error message")
|
13
13
|
code: ApiErrorIdentifier = Field(..., description="The unique error code")
|
14
14
|
type: ApiErrorType = Field(..., description="The type of error")
|
15
15
|
level: ApiErrorLevel = Field(..., description="The level of the error")
|
16
16
|
status_code: int = Field(..., description="The HTTP status code")
|
17
|
+
details: Any = Field(None, description="Additional details about the error")
|
17
18
|
|
18
19
|
|
19
|
-
class
|
20
|
-
|
20
|
+
class ExceptionContent(BaseModel):
|
21
|
+
"""This is the detail of the exception. Pass an ApiError to the constructor and an optional human readable message."""
|
22
|
+
|
21
23
|
error: ApiError = Field(..., description="The unique error code")
|
22
24
|
message: Optional[str] = Field(None, description="An additional error message")
|
25
|
+
details: Any = Field(None, description="Additional details about the error")
|
23
26
|
|
24
|
-
def enrich(self) ->
|
25
|
-
return
|
27
|
+
def enrich(self) -> ExceptionDetail:
|
28
|
+
return ExceptionDetail(
|
26
29
|
message=self.message,
|
27
30
|
code=self.error.identifier,
|
28
31
|
type=self.error.type,
|
29
32
|
level=self.error.level,
|
30
33
|
status_code=self.error.status_code,
|
34
|
+
details=self.details,
|
31
35
|
)
|
32
36
|
|
37
|
+
|
33
38
|
class HTTPException(FastAPIHTTPException):
|
34
39
|
"""A custom HTTP exception wrapper around FastAPI's HTTPException.
|
35
40
|
It allows for a more structured way to handle errors, with a message and an error code. The status code is being derived from the detail's error.
|
@@ -38,43 +43,55 @@ class HTTPException(FastAPIHTTPException):
|
|
38
43
|
|
39
44
|
def __init__(
|
40
45
|
self,
|
41
|
-
|
46
|
+
content: ExceptionContent,
|
42
47
|
headers: Optional[Dict[str, str]] = None,
|
43
48
|
):
|
44
|
-
assert isinstance(
|
45
|
-
body =
|
49
|
+
assert isinstance(content, ExceptionContent)
|
50
|
+
body = content.enrich()
|
46
51
|
super().__init__(
|
47
52
|
status_code=body.status_code,
|
48
53
|
detail=body.model_dump(mode="json"),
|
49
54
|
headers=headers,
|
50
55
|
)
|
51
56
|
|
57
|
+
|
52
58
|
async def general_handler(request: Request, exc: Exception):
|
53
|
-
|
54
|
-
body =
|
55
|
-
return JSONResponse(
|
59
|
+
"""This is the default exception handler for all exceptions."""
|
60
|
+
body = ExceptionContent(message=str(exc), error=ApiError.UNKNOWN_ERROR)
|
61
|
+
return JSONResponse(
|
62
|
+
status_code=body.error.status_code, content=HTTPException(content=body).detail
|
63
|
+
)
|
64
|
+
|
56
65
|
|
57
66
|
async def request_validation_handler(request: Request, exc: RequestValidationError):
|
58
|
-
|
59
|
-
body =
|
60
|
-
return JSONResponse(
|
67
|
+
"""This is the exception handler for all request validation errors."""
|
68
|
+
body = ExceptionContent(message=str(exc), error=ApiError.INVALID_DATA_REQUEST)
|
69
|
+
return JSONResponse(
|
70
|
+
status_code=body.error.status_code, content=HTTPException(content=body).detail
|
71
|
+
)
|
72
|
+
|
61
73
|
|
62
74
|
async def response_validation_handler(request: Request, exc: ResponseValidationError):
|
63
|
-
|
64
|
-
body =
|
65
|
-
return JSONResponse(
|
75
|
+
"""This is the exception handler for all response validation errors."""
|
76
|
+
body = ExceptionContent(message=str(exc), error=ApiError.INVALID_DATA_RESPONSE)
|
77
|
+
return JSONResponse(
|
78
|
+
status_code=body.error.status_code, content=HTTPException(content=body).detail
|
79
|
+
)
|
80
|
+
|
66
81
|
|
67
82
|
async def http_handler(request: Request, exc: HTTPException):
|
68
|
-
|
83
|
+
"""This is the exception handler for HTTPExceptions. It unwraps the HTTPException and returns the detail in a flat JSON response."""
|
69
84
|
return JSONResponse(status_code=exc.status_code, content=exc.detail)
|
70
85
|
|
86
|
+
|
71
87
|
def register_exception_handlers(app: FastAPI):
|
72
|
-
|
88
|
+
"""Utility to register serveral exception handlers in one go. Catches Exception, HTTPException and Data Validation errors and responds with a unified json body."""
|
73
89
|
app.add_exception_handler(Exception, general_handler)
|
74
90
|
app.add_exception_handler(FastAPIHTTPException, http_handler)
|
75
91
|
app.add_exception_handler(RequestValidationError, request_validation_handler)
|
76
92
|
app.add_exception_handler(ResponseValidationError, response_validation_handler)
|
77
93
|
|
94
|
+
|
78
95
|
exception_response = {
|
79
|
-
"default": {"model":
|
80
|
-
}
|
96
|
+
"default": {"model": ExceptionDetail, "description": "Error response"}
|
97
|
+
}
|
crypticorn-2.5.0rc4/crypticorn/common/enums.py → crypticorn-2.5.1/crypticorn/common/mixins.py
RENAMED
@@ -1,6 +1,3 @@
|
|
1
|
-
from enum import StrEnum
|
2
|
-
|
3
|
-
|
4
1
|
class ValidateEnumMixin:
|
5
2
|
"""
|
6
3
|
Mixin for validating enum values manually.
|
@@ -22,35 +19,18 @@ class ValidateEnumMixin:
|
|
22
19
|
|
23
20
|
@classmethod
|
24
21
|
def validate(cls, value) -> bool:
|
22
|
+
"""Validate if a value is in the enum. True if so, False otherwise."""
|
25
23
|
try:
|
26
24
|
cls(value)
|
27
25
|
return True
|
28
26
|
except ValueError:
|
29
27
|
return False
|
30
28
|
|
29
|
+
class ExcludeEnumMixin:
|
30
|
+
"""Mixin to exclude enum from OpenAPI schema. We use this to avoid duplicating enums when generating client code from the openapi spec."""
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
class InternalExchange(ValidateEnumMixin, StrEnum):
|
40
|
-
"""All exchanges we are using, including public (Exchange)"""
|
41
|
-
|
42
|
-
KUCOIN = "kucoin"
|
43
|
-
BINGX = "bingx"
|
44
|
-
BINANCE = "binance"
|
45
|
-
BYBIT = "bybit"
|
46
|
-
HYPERLIQUID = "hyperliquid"
|
47
|
-
BITGET = "bitget"
|
48
|
-
|
49
|
-
|
50
|
-
class MarketType(ValidateEnumMixin, StrEnum):
|
51
|
-
"""
|
52
|
-
Market types
|
53
|
-
"""
|
54
|
-
|
55
|
-
SPOT = "spot"
|
56
|
-
FUTURES = "futures"
|
32
|
+
@classmethod
|
33
|
+
def __get_pydantic_json_schema__(cls, core_schema, handler):
|
34
|
+
schema = handler(core_schema)
|
35
|
+
schema.pop("enum", None)
|
36
|
+
return schema
|