jumptech-sdk 0.1.0__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.
- jumptech_sdk-0.1.0/.gitignore +16 -0
- jumptech_sdk-0.1.0/PKG-INFO +306 -0
- jumptech_sdk-0.1.0/README.md +295 -0
- jumptech_sdk-0.1.0/jumptech_sdk/__init__.py +61 -0
- jumptech_sdk-0.1.0/jumptech_sdk/__main__.py +7 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_call.py +54 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/__init__.py +8 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/__init__.py +1 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/account_state.py +225 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/close_account.py +216 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/get_account.py +169 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/get_ledger.py +352 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/ledger_summary.py +239 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/list_accounts.py +525 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/reopen_account.py +216 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/accounts/update_account.py +276 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/change_my_password.py +231 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/create_role.py +203 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/create_user.py +177 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/create_view.py +175 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/delete_view.py +168 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/disable_my_2fa.py +195 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/force_disable_user_2fa.py +200 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/get_my_profile.py +171 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/get_role.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/get_user.py +170 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_audit_log.py +387 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_my_sessions.py +171 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_roles.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_settings.py +159 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_user_sessions.py +194 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_users.py +282 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/list_views.py +209 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/put_setting.py +234 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/reset_user_password.py +200 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/revoke_my_other_sessions.py +149 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/revoke_my_session.py +187 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/revoke_user_session.py +198 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/setup_my_2fa.py +165 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/update_my_profile.py +183 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/update_role.py +214 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/update_user.py +193 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/update_view.py +191 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/administration/verify_my_2fa.py +195 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/api_keys/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/api_keys/create_api_key.py +183 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/api_keys/list_api_keys.py +138 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/api_keys/revoke_api_key.py +188 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/branding.py +173 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/confirm_password_reset.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/customer_2fa.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/customer_autologin.py +193 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/customer_login.py +219 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/forgot_password.py +263 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/refresh.py +169 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/register.py +227 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/staff_login.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/staff_logout.py +161 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/auth/verify_reset_token.py +185 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/create_group.py +191 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/deactivate_group.py +180 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/get_group.py +168 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/get_instrument.py +191 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/get_instrument_profile.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/group_impact.py +180 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/list_group_instruments.py +202 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/list_groups.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/patch_group_instruments.py +275 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/stream_accounts.py +206 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/stream_positions.py +178 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/configuration/update_group.py +191 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/create_customer.py +213 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/dedupe_check.py +241 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/freeze_customer.py +221 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/get_customer.py +170 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/issue_password_reset.py +234 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/list_customer_accounts.py +226 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/list_customers.py +530 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/mint_autologin_token.py +214 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/open_account.py +221 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/reset_customer_2fa.py +194 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/unfreeze_customer.py +217 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/customers/update_customer.py +221 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/default/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/default/calendar_feed.py +256 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/events/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/events/list_events.py +255 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/events/stream_events.py +217 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/acknowledge_alert.py +210 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/delete_limit.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/exposure_history.py +235 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/exposure_stream.py +165 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/list_alerts.py +250 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/list_limits.py +155 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/live_exposure.py +161 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/symbol_concentration.py +222 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/symbol_exposure.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/exposure/upsert_limit.py +214 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/instruments/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/instruments/list_asset_classes.py +211 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/instruments/list_instruments.py +293 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/instruments/update_instrument.py +238 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/cancel_my_pending.py +167 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/cancel_withdrawal.py +168 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/change_password.py +239 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/close_my_position.py +213 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/get_me.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/logout.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/mark_all_read.py +178 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/mark_read.py +168 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/max_withdrawable.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/modify_my_pending.py +190 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/modify_my_position.py +198 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_accounts.py +171 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_history.py +190 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_instruments.py +273 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_kyc.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_notifications.py +245 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_pending.py +205 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_positions.py +221 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_prices.py +249 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_transactions.py +250 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_transfer.py +223 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_transfer_preview.py +223 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/my_unread_count.py +165 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/place_my_pending.py +191 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/place_my_position.py +203 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/request_deposit.py +255 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/request_password_reset.py +189 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/request_support.py +259 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/select_account.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/set_language.py +175 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/totp_backup_codes.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/totp_disable.py +175 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/totp_setup.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/totp_verify.py +187 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/update_me.py +141 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/me/withdraw.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/cancel_pending.py +202 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/close_all_positions.py +227 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/close_position.py +234 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/correct_open_price.py +268 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/get_history_item.py +194 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/get_position.py +194 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/get_request_status.py +189 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/list_history.py +490 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/list_pending.py +454 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/list_positions.py +490 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/modify_pending.py +236 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/modify_position.py +228 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/place_pending.py +201 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/positions/place_position.py +217 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/presence/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/presence/online_accounts.py +163 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/presence/ping.py +173 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/presence/user_presence.py +188 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/cashier_report.py +169 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/customers_report.py +173 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/orders_report.py +289 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/simulate.py +238 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/reports/transactions_report.py +197 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/stopouts/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/stopouts/list_stopout_events.py +285 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/approve.py +249 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/chargeback.py +229 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/create_transaction.py +205 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/create_transfer.py +205 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/decline.py +205 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/get_transaction.py +170 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/list_transactions.py +569 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/transactions/transfer_preview.py +225 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/__init__.py +0 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/create_webhook.py +189 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/delete_webhook.py +168 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/get_webhook.py +170 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/list_failures.py +216 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/list_webhooks.py +227 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/rotate_secret.py +190 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/api/webhooks/update_webhook.py +201 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/client.py +286 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/errors.py +16 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/__init__.py +287 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_create.py +102 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_detail.py +513 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_exposure_entry.py +95 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_row.py +445 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_state_response.py +199 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_summary.py +185 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/account_update.py +124 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/acknowledge_alert_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/api_key_create.py +81 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/autologin_token_response.py +95 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/bulk_close_failure.py +79 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/bulk_close_response.py +104 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/cancel_pending_order_response.py +87 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/chargeback_request.py +104 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/chargeback_response.py +103 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/close_account_request.py +81 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/close_account_response.py +95 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/confirm_password_reset_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/correct_open_price_request.py +91 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/correct_open_price_response.py +193 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/create_group_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/create_role_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/create_user_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/create_view_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_2fa_reset_response.py +87 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_create.py +159 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_login_request.py +79 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_register_request.py +170 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_summary.py +404 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_summary_trading_accounts_item.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/customer_update.py +213 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/dedupe_check_request.py +123 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/dedupe_check_response.py +88 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/dedupe_match.py +151 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/deposit_request.py +103 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/disable_my_2_fa_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/economic_event_response.py +211 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/event_row.py +149 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/event_row_data.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/execution_status_response.py +254 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/execution_status_response_detail_type_0.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/exposure_alert_response.py +230 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/exposure_limit_response.py +122 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/exposure_snapshot_response.py +105 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/failure_row.py +138 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/filter_view_response.py +109 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/filter_view_response_filter_state.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/forgot_password_request.py +71 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/freeze_request.py +71 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/group_instrument_response.py +275 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/group_response.py +251 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/http_validation_error.py +89 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/instrument_row.py +761 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/ledger_entry.py +346 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/ledger_summary_response.py +151 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/list_history_pnl_type_0.py +9 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/list_positions_pnl_type_0.py +9 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/list_views_page.py +11 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/modify_my_pending_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/modify_my_position_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/modify_pending_order_request.py +164 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/modify_sltp_request.py +123 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/modify_sltp_response.py +96 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/my_transfer_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/open_order_response.py +327 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/order_history_response.py +374 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/order_queued_response.py +82 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_account_exposure_entry.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_account_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_customer_summary.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_economic_event_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_event_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_exposure_alert_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_exposure_limit_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_exposure_snapshot_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_failure_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_filter_view_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_group_instrument_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_group_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_instrument_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_ledger_entry.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_role_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_stopout_event_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_transaction_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_user_response.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/page_webhook_row.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/pagedict.py +125 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/pagedict_data_item.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/pagestr.py +109 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/password_change.py +86 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/password_reset_issued_response.py +103 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/patch_group_instruments_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/pending_order_response.py +291 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/place_my_pending_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/place_my_position_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/place_order_request.py +177 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/place_pending_order_request.py +237 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/put_setting_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/reopen_account_response.py +87 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/role_response.py +145 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/rotate_secret_response.py +83 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/select_account_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/set_language_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/simulate_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/staff_password_change.py +85 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/stopout_event_row.py +190 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/support_request.py +85 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/totp_disable_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/totp_verify_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_approve_request.py +84 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_create_manual.py +321 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_create_manual_payment_data_type_0.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_create_manual_status.py +9 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_create_manual_type.py +22 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_response.py +614 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_response_payment_data_type_0.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transaction_row.py +531 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transfer_create_crm.py +115 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transfer_preview_response.py +143 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/transfer_response.py +165 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/two_fa_login_verify_request.py +79 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/unfreeze_request.py +93 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/update_group_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/update_instrument_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/update_role_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/update_user_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/update_view_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/upsert_limit_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/user_login_request.py +101 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/user_response.py +180 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/v1_error_detail.py +102 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/v1_error_envelope.py +84 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/validation_error.py +102 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/verify_my_2_fa_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/webhook_create.py +122 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/webhook_created_response.py +207 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/webhook_row.py +196 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/webhook_update.py +176 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/models/withdraw_body.py +56 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_generated/types.py +54 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_spec.py +8 -0
- jumptech_sdk-0.1.0/jumptech_sdk/_transport.py +166 -0
- jumptech_sdk-0.1.0/jumptech_sdk/aio.py +498 -0
- jumptech_sdk-0.1.0/jumptech_sdk/client.py +294 -0
- jumptech_sdk-0.1.0/jumptech_sdk/doctor.py +201 -0
- jumptech_sdk-0.1.0/jumptech_sdk/errors.py +211 -0
- jumptech_sdk-0.1.0/jumptech_sdk/events.py +245 -0
- jumptech_sdk-0.1.0/jumptech_sdk/idempotency.py +268 -0
- jumptech_sdk-0.1.0/jumptech_sdk/models.py +17 -0
- jumptech_sdk-0.1.0/jumptech_sdk/resources/__init__.py +6 -0
- jumptech_sdk-0.1.0/jumptech_sdk/resources/positions.py +288 -0
- jumptech_sdk-0.1.0/jumptech_sdk/resources/transactions.py +160 -0
- jumptech_sdk-0.1.0/jumptech_sdk/signing.py +61 -0
- jumptech_sdk-0.1.0/jumptech_sdk/stores.py +217 -0
- jumptech_sdk-0.1.0/jumptech_sdk/webhooks.py +161 -0
- jumptech_sdk-0.1.0/pyproject.toml +55 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Local to sdk/python, so hatchling's sdist build finds THIS file rather than
|
|
2
|
+
# walking up to the repo root's — otherwise the whole repo .gitignore (worktree
|
|
3
|
+
# notes, deployment paths, credential-dump warnings) gets force-included
|
|
4
|
+
# verbatim into every `jumptech-sdk` sdist. See pyproject.toml's sdist `include`.
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.coverage
|
|
10
|
+
htmlcov/
|
|
11
|
+
dist/
|
|
12
|
+
build/
|
|
13
|
+
.venv*/
|
|
14
|
+
# SqliteStore's default store_path — created the moment a JumpTech() client is
|
|
15
|
+
# constructed without an explicit path, holds no committable state.
|
|
16
|
+
jumptech.db
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jumptech-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the JumpTech engine /v1 API
|
|
5
|
+
License: Proprietary
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: attrs>=22.2
|
|
8
|
+
Requires-Dist: httpx>=0.27
|
|
9
|
+
Requires-Dist: python-dateutil>=2.8.1
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# jumptech-sdk
|
|
13
|
+
|
|
14
|
+
Python client for the JumpTech engine `/v1` API.
|
|
15
|
+
|
|
16
|
+
Money mutations are the reason this exists rather than a bare generated client:
|
|
17
|
+
a retry here is a **replay**, not a second deposit, and it stays a replay across
|
|
18
|
+
a process crash.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install jumptech-sdk
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Python 3.11+. Three dependencies (`httpx`, `attrs`, `python-dateutil`) — the
|
|
25
|
+
durable store and the webhook verifier use only the standard library.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Before you write any code
|
|
30
|
+
|
|
31
|
+
Two credentials come from the broker you are integrating with. Neither is
|
|
32
|
+
self-service; a broker operator issues them.
|
|
33
|
+
|
|
34
|
+
| You need | Looks like | Notes |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| **API key** | `jt_demo_…` / `jt_live_…` | Ask for a **`jt_demo_`** key first. Same API, same code path, no real money. |
|
|
37
|
+
| **Webhook secret** | `whsec_…` | Only if you want events pushed to you. Polling works without it. |
|
|
38
|
+
|
|
39
|
+
Also ask **which base URL** — each broker runs its own engine, so a partner
|
|
40
|
+
serving three brokers holds three keys against three URLs.
|
|
41
|
+
|
|
42
|
+
Your key may be **read-only**, in which case every non-`GET` returns
|
|
43
|
+
`403 readonly_key`. Worth confirming up front rather than discovering it on your
|
|
44
|
+
first deposit.
|
|
45
|
+
|
|
46
|
+
## Check the connection first
|
|
47
|
+
|
|
48
|
+
Before writing anything, prove the credential and the network work:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python -m jumptech_sdk doctor --base-url https://api.yourbroker.com --api-key jt_demo_...
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
It names the actual problem — an unknown key, a read-only key, or an engine that
|
|
55
|
+
could not reach its own auth service (which is *not* a bad key, and rotating it
|
|
56
|
+
will not help). If you are receiving webhooks, point it at your own endpoint and
|
|
57
|
+
it will send one correctly-signed delivery:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m jumptech_sdk doctor --base-url https://api.yourbroker.com --api-key jt_demo_... \
|
|
61
|
+
--probe https://crm.example/jt --secret whsec_...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Rejected means the fault is in your verifier. Accepted means it is upstream.
|
|
65
|
+
That distinction is the classic first-day afternoon, and this answers it in a
|
|
66
|
+
second.
|
|
67
|
+
|
|
68
|
+
## Your first call
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from jumptech_sdk import JumpTech
|
|
72
|
+
|
|
73
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_demo_...")
|
|
74
|
+
|
|
75
|
+
page = jt.transactions.list(page_size=5)
|
|
76
|
+
for tx in page.data:
|
|
77
|
+
print(tx.id, tx.type, tx.amount, tx.account_currency)
|
|
78
|
+
|
|
79
|
+
jt.close()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Every list returns the same envelope: `.data`, `.total`, and `.next_cursor` on
|
|
83
|
+
the append-only logs. Money values always arrive with their currency beside
|
|
84
|
+
them — read `account_currency`, never assume.
|
|
85
|
+
|
|
86
|
+
Use it as a context manager and you can forget `close()`:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
with JumpTech("https://api.yourbroker.com", api_key="jt_demo_...") as jt:
|
|
90
|
+
print(jt.transactions.list(page_size=1).total)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## What is typed in v0.1
|
|
96
|
+
|
|
97
|
+
Hand-written, typed wrappers: **`jt.transactions`** (create, get, list, approve,
|
|
98
|
+
decline, chargeback) and **`jt.positions`** (place, place_async, request_status,
|
|
99
|
+
list, get, close). Plus **`jt.events`** for the event log and **`jt.webhooks`**
|
|
100
|
+
for inbound deliveries.
|
|
101
|
+
|
|
102
|
+
Everything else on `/v1` — customers, accounts, transfers, pending orders,
|
|
103
|
+
groups, instruments, the audit log — is reachable but **untyped**: the generated
|
|
104
|
+
client under `jumptech_sdk._generated` covers the whole spec, and calls made
|
|
105
|
+
through it get **no** retry, idempotency-key or crash-recovery help from the
|
|
106
|
+
layer above. If you are moving money through one of those, mint and reuse a key
|
|
107
|
+
yourself, or wait for a typed wrapper.
|
|
108
|
+
|
|
109
|
+
Retries, the idempotency key, the event dedupe store, `recover()` and the webhook
|
|
110
|
+
verifier work identically for whichever resource you call.
|
|
111
|
+
|
|
112
|
+
## Money in
|
|
113
|
+
|
|
114
|
+
Mutations carry an `Idempotency-Key` automatically, and a retry reuses it — so a
|
|
115
|
+
retried deposit is a replay, not a second deposit.
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import uuid
|
|
119
|
+
|
|
120
|
+
from jumptech_sdk import JumpTech
|
|
121
|
+
from jumptech_sdk.models import TransactionCreateManual, TransactionCreateManualType
|
|
122
|
+
|
|
123
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...")
|
|
124
|
+
|
|
125
|
+
tx = jt.transactions.create(TransactionCreateManual(
|
|
126
|
+
type=TransactionCreateManualType.DEPOSIT, # an UPPERCASE enum, not a string
|
|
127
|
+
account_id=uuid.UUID("3f7c0d1e-2b4a-4c8e-9a71-2d1f6b3e5c40"), # the account's
|
|
128
|
+
# UUID, not the login
|
|
129
|
+
amount="100.00",
|
|
130
|
+
account_amount="100.00", # deposits must be in the account's currency
|
|
131
|
+
currency="USD",
|
|
132
|
+
))
|
|
133
|
+
jt.transactions.approve(tx.id)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Two rules the API enforces and the SDK cannot guess for you: a deposit or
|
|
137
|
+
withdrawal **must** be in the account's own currency, and `account_id` is the
|
|
138
|
+
account's UUID — not its numeric login.
|
|
139
|
+
|
|
140
|
+
## Handling failures
|
|
141
|
+
|
|
142
|
+
Catch the specific class when you can act on it, `JumpTechError` when you cannot.
|
|
143
|
+
Every one carries `.code`, `.message`, `.status` and `.request_id` — quote
|
|
144
|
+
`request_id` when you ask the broker about a call.
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from jumptech_sdk import (
|
|
148
|
+
InsufficientMargin, JumpTechError, NotFound, RateLimited,
|
|
149
|
+
UnknownOutcome, ValidationError,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
jt.transactions.approve(tx_id)
|
|
154
|
+
except ValidationError as e:
|
|
155
|
+
print("the request was malformed:", e.fields) # per-field, from the API
|
|
156
|
+
except NotFound:
|
|
157
|
+
print("no such transaction")
|
|
158
|
+
except InsufficientMargin as e:
|
|
159
|
+
print("shortfall:", e.details) # {required, available, ...}
|
|
160
|
+
except RateLimited as e:
|
|
161
|
+
print("slow down for", e.retry_after, "seconds") # already honoured on retry
|
|
162
|
+
except UnknownOutcome as e:
|
|
163
|
+
print("MAY have committed — reconcile, do not retry:", e)
|
|
164
|
+
except JumpTechError as e:
|
|
165
|
+
print(e.status, e.code, e.message, e.request_id)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**`UnknownOutcome` is the one to read twice.** It means the request left your
|
|
169
|
+
process and no answer came back, so the mutation may or may not have committed.
|
|
170
|
+
The SDK deliberately does **not** retry it — see *After a crash*.
|
|
171
|
+
|
|
172
|
+
Retries are automatic and already done by the time an exception reaches you:
|
|
173
|
+
5 attempts, exponential backoff from 0.5s capped at 8s, on `429`, `502` and
|
|
174
|
+
`503` only. Tune it if you must:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from jumptech_sdk import JumpTech, RetryPolicy
|
|
178
|
+
|
|
179
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...",
|
|
180
|
+
policy=RetryPolicy(max_attempts=3, base_delay=1.0))
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Orders
|
|
184
|
+
|
|
185
|
+
Placement is asynchronous — a 202 and a request id. `place()` polls it to a
|
|
186
|
+
terminal state; `place_async()` hands you the id.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from jumptech_sdk.models import PlaceOrderRequest
|
|
190
|
+
|
|
191
|
+
fill = jt.positions.place(PlaceOrderRequest(
|
|
192
|
+
symbol="EURUSD", cmd=0, volume=0.10, login=5001
|
|
193
|
+
))
|
|
194
|
+
print(fill.order, fill.open_price) # cmd: 0=buy, 1=sell. Ticket is `order`.
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
A rejection raises rather than returning a status: `MarginRejected` for
|
|
198
|
+
insufficient margin, `OrderRejected` otherwise, and `OrderRequestExpired` if the
|
|
199
|
+
request id aged out — which says nothing about whether the order executed, so
|
|
200
|
+
check the book before retrying.
|
|
201
|
+
|
|
202
|
+
## Events
|
|
203
|
+
|
|
204
|
+
One handler, two delivery routes, deduped against each other because both share
|
|
205
|
+
the same store:
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from fastapi import FastAPI
|
|
209
|
+
|
|
210
|
+
from jumptech_sdk import JumpTech
|
|
211
|
+
|
|
212
|
+
app = FastAPI()
|
|
213
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...",
|
|
214
|
+
webhook_secret="whsec_...") # jt.webhooks is None without this
|
|
215
|
+
|
|
216
|
+
@jt.on_event
|
|
217
|
+
def handle(event):
|
|
218
|
+
print(event["type"], event["event_id"])
|
|
219
|
+
|
|
220
|
+
jt.webhooks.mount(app, "/jt") # push: verifies, dedupes, dispatches
|
|
221
|
+
jt.events.reconcile() # pull: same handler, same dedupe store
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Flask and Django get `jt.webhooks.flask_view()` and `jt.webhooks.django_view()`.
|
|
225
|
+
Use an adapter rather than verifying by hand: the signature is computed over the
|
|
226
|
+
**raw bytes**, and a handler that verifies against a re-serialised object rejects
|
|
227
|
+
every delivery.
|
|
228
|
+
|
|
229
|
+
Your handler runs **at most once per event** across both routes, and only counts
|
|
230
|
+
as handled once it returns — if it raises, nothing is recorded and the event is
|
|
231
|
+
redelivered.
|
|
232
|
+
|
|
233
|
+
Reconcile is one pass — schedule it with whatever you already use. Treat
|
|
234
|
+
`GET /v1/events` as the system of record and webhooks as an optimisation, not the
|
|
235
|
+
other way round.
|
|
236
|
+
|
|
237
|
+
## After a crash
|
|
238
|
+
|
|
239
|
+
`recover()` finishes every pending intent with its ORIGINAL key, so each returns
|
|
240
|
+
the original answer instead of booking a second one. It hands back one
|
|
241
|
+
`(key, outcome)` per intent — the response, or the exception if that one did not
|
|
242
|
+
complete. An intent whose last outcome was unknown (a 5xx, or a read timeout: the
|
|
243
|
+
handler may have committed and the API does not cache either) is refused, and its
|
|
244
|
+
outcome says so. Reconcile those, then resolve them by hand.
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
for key, intent in jt.unresolved():
|
|
248
|
+
... # reconcile against GET /v1/events or the
|
|
249
|
+
# resource itself, then:
|
|
250
|
+
jt.store.resolve_intent(key, "done")
|
|
251
|
+
|
|
252
|
+
for key, outcome in jt.recover():
|
|
253
|
+
if isinstance(outcome, Exception):
|
|
254
|
+
... # this one did not finish; the others still ran
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Call `recover()` on startup. It is the payoff for the store being on disk.
|
|
258
|
+
|
|
259
|
+
## Async
|
|
260
|
+
|
|
261
|
+
`AsyncJumpTech` in `jumptech_sdk.aio` is the same API with `await`, and
|
|
262
|
+
`jt.events.stream()` becomes an async generator:
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
from jumptech_sdk.aio import AsyncJumpTech
|
|
266
|
+
|
|
267
|
+
jt = AsyncJumpTech("https://api.yourbroker.com", api_key="jt_live_...")
|
|
268
|
+
|
|
269
|
+
async def consume():
|
|
270
|
+
async for event in jt.events.stream():
|
|
271
|
+
...
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`stream()` yields **per event, not per page**, so persisting after each one costs
|
|
275
|
+
one duplicate on a crash instead of a page. It does not stop at the end of the
|
|
276
|
+
backlog — it keeps polling, so catch-up and live tail are the same loop.
|
|
277
|
+
|
|
278
|
+
## State
|
|
279
|
+
|
|
280
|
+
A local sqlite file (`jumptech.db` by default) holds pending idempotency intents
|
|
281
|
+
and handled event ids. Point it somewhere durable in production:
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
jt = JumpTech(
|
|
285
|
+
"https://api.yourbroker.com", api_key="jt_live_...",
|
|
286
|
+
store_path="/var/lib/yourapp/jumptech.db",
|
|
287
|
+
)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
An in-memory store does not survive the crash it exists to protect against, so
|
|
291
|
+
`InMemoryStore` is for tests only. Implement the `Store` protocol to put this in
|
|
292
|
+
your own database instead.
|
|
293
|
+
|
|
294
|
+
Both clients close their connection pool and their store — `jt.close()`, or
|
|
295
|
+
`with JumpTech(...) as jt:` (`await jt.aclose()` / `async with` on the async
|
|
296
|
+
one).
|
|
297
|
+
|
|
298
|
+
## Going to production
|
|
299
|
+
|
|
300
|
+
- [ ] Swap the `jt_demo_` key for `jt_live_`.
|
|
301
|
+
- [ ] Point `store_path` at durable, writable disk that survives a redeploy.
|
|
302
|
+
- [ ] Call `jt.recover()` on startup.
|
|
303
|
+
- [ ] Schedule `jt.events.reconcile()` — webhooks alone will miss events.
|
|
304
|
+
- [ ] Decide what `UnknownOutcome` does in your system. It is the only outcome
|
|
305
|
+
that needs a human or a reconciliation, and it will happen.
|
|
306
|
+
- [ ] Log `request_id` from every `JumpTechError`.
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# jumptech-sdk
|
|
2
|
+
|
|
3
|
+
Python client for the JumpTech engine `/v1` API.
|
|
4
|
+
|
|
5
|
+
Money mutations are the reason this exists rather than a bare generated client:
|
|
6
|
+
a retry here is a **replay**, not a second deposit, and it stays a replay across
|
|
7
|
+
a process crash.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install jumptech-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Python 3.11+. Three dependencies (`httpx`, `attrs`, `python-dateutil`) — the
|
|
14
|
+
durable store and the webhook verifier use only the standard library.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Before you write any code
|
|
19
|
+
|
|
20
|
+
Two credentials come from the broker you are integrating with. Neither is
|
|
21
|
+
self-service; a broker operator issues them.
|
|
22
|
+
|
|
23
|
+
| You need | Looks like | Notes |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| **API key** | `jt_demo_…` / `jt_live_…` | Ask for a **`jt_demo_`** key first. Same API, same code path, no real money. |
|
|
26
|
+
| **Webhook secret** | `whsec_…` | Only if you want events pushed to you. Polling works without it. |
|
|
27
|
+
|
|
28
|
+
Also ask **which base URL** — each broker runs its own engine, so a partner
|
|
29
|
+
serving three brokers holds three keys against three URLs.
|
|
30
|
+
|
|
31
|
+
Your key may be **read-only**, in which case every non-`GET` returns
|
|
32
|
+
`403 readonly_key`. Worth confirming up front rather than discovering it on your
|
|
33
|
+
first deposit.
|
|
34
|
+
|
|
35
|
+
## Check the connection first
|
|
36
|
+
|
|
37
|
+
Before writing anything, prove the credential and the network work:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python -m jumptech_sdk doctor --base-url https://api.yourbroker.com --api-key jt_demo_...
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
It names the actual problem — an unknown key, a read-only key, or an engine that
|
|
44
|
+
could not reach its own auth service (which is *not* a bad key, and rotating it
|
|
45
|
+
will not help). If you are receiving webhooks, point it at your own endpoint and
|
|
46
|
+
it will send one correctly-signed delivery:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python -m jumptech_sdk doctor --base-url https://api.yourbroker.com --api-key jt_demo_... \
|
|
50
|
+
--probe https://crm.example/jt --secret whsec_...
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Rejected means the fault is in your verifier. Accepted means it is upstream.
|
|
54
|
+
That distinction is the classic first-day afternoon, and this answers it in a
|
|
55
|
+
second.
|
|
56
|
+
|
|
57
|
+
## Your first call
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from jumptech_sdk import JumpTech
|
|
61
|
+
|
|
62
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_demo_...")
|
|
63
|
+
|
|
64
|
+
page = jt.transactions.list(page_size=5)
|
|
65
|
+
for tx in page.data:
|
|
66
|
+
print(tx.id, tx.type, tx.amount, tx.account_currency)
|
|
67
|
+
|
|
68
|
+
jt.close()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Every list returns the same envelope: `.data`, `.total`, and `.next_cursor` on
|
|
72
|
+
the append-only logs. Money values always arrive with their currency beside
|
|
73
|
+
them — read `account_currency`, never assume.
|
|
74
|
+
|
|
75
|
+
Use it as a context manager and you can forget `close()`:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
with JumpTech("https://api.yourbroker.com", api_key="jt_demo_...") as jt:
|
|
79
|
+
print(jt.transactions.list(page_size=1).total)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## What is typed in v0.1
|
|
85
|
+
|
|
86
|
+
Hand-written, typed wrappers: **`jt.transactions`** (create, get, list, approve,
|
|
87
|
+
decline, chargeback) and **`jt.positions`** (place, place_async, request_status,
|
|
88
|
+
list, get, close). Plus **`jt.events`** for the event log and **`jt.webhooks`**
|
|
89
|
+
for inbound deliveries.
|
|
90
|
+
|
|
91
|
+
Everything else on `/v1` — customers, accounts, transfers, pending orders,
|
|
92
|
+
groups, instruments, the audit log — is reachable but **untyped**: the generated
|
|
93
|
+
client under `jumptech_sdk._generated` covers the whole spec, and calls made
|
|
94
|
+
through it get **no** retry, idempotency-key or crash-recovery help from the
|
|
95
|
+
layer above. If you are moving money through one of those, mint and reuse a key
|
|
96
|
+
yourself, or wait for a typed wrapper.
|
|
97
|
+
|
|
98
|
+
Retries, the idempotency key, the event dedupe store, `recover()` and the webhook
|
|
99
|
+
verifier work identically for whichever resource you call.
|
|
100
|
+
|
|
101
|
+
## Money in
|
|
102
|
+
|
|
103
|
+
Mutations carry an `Idempotency-Key` automatically, and a retry reuses it — so a
|
|
104
|
+
retried deposit is a replay, not a second deposit.
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import uuid
|
|
108
|
+
|
|
109
|
+
from jumptech_sdk import JumpTech
|
|
110
|
+
from jumptech_sdk.models import TransactionCreateManual, TransactionCreateManualType
|
|
111
|
+
|
|
112
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...")
|
|
113
|
+
|
|
114
|
+
tx = jt.transactions.create(TransactionCreateManual(
|
|
115
|
+
type=TransactionCreateManualType.DEPOSIT, # an UPPERCASE enum, not a string
|
|
116
|
+
account_id=uuid.UUID("3f7c0d1e-2b4a-4c8e-9a71-2d1f6b3e5c40"), # the account's
|
|
117
|
+
# UUID, not the login
|
|
118
|
+
amount="100.00",
|
|
119
|
+
account_amount="100.00", # deposits must be in the account's currency
|
|
120
|
+
currency="USD",
|
|
121
|
+
))
|
|
122
|
+
jt.transactions.approve(tx.id)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Two rules the API enforces and the SDK cannot guess for you: a deposit or
|
|
126
|
+
withdrawal **must** be in the account's own currency, and `account_id` is the
|
|
127
|
+
account's UUID — not its numeric login.
|
|
128
|
+
|
|
129
|
+
## Handling failures
|
|
130
|
+
|
|
131
|
+
Catch the specific class when you can act on it, `JumpTechError` when you cannot.
|
|
132
|
+
Every one carries `.code`, `.message`, `.status` and `.request_id` — quote
|
|
133
|
+
`request_id` when you ask the broker about a call.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from jumptech_sdk import (
|
|
137
|
+
InsufficientMargin, JumpTechError, NotFound, RateLimited,
|
|
138
|
+
UnknownOutcome, ValidationError,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
jt.transactions.approve(tx_id)
|
|
143
|
+
except ValidationError as e:
|
|
144
|
+
print("the request was malformed:", e.fields) # per-field, from the API
|
|
145
|
+
except NotFound:
|
|
146
|
+
print("no such transaction")
|
|
147
|
+
except InsufficientMargin as e:
|
|
148
|
+
print("shortfall:", e.details) # {required, available, ...}
|
|
149
|
+
except RateLimited as e:
|
|
150
|
+
print("slow down for", e.retry_after, "seconds") # already honoured on retry
|
|
151
|
+
except UnknownOutcome as e:
|
|
152
|
+
print("MAY have committed — reconcile, do not retry:", e)
|
|
153
|
+
except JumpTechError as e:
|
|
154
|
+
print(e.status, e.code, e.message, e.request_id)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**`UnknownOutcome` is the one to read twice.** It means the request left your
|
|
158
|
+
process and no answer came back, so the mutation may or may not have committed.
|
|
159
|
+
The SDK deliberately does **not** retry it — see *After a crash*.
|
|
160
|
+
|
|
161
|
+
Retries are automatic and already done by the time an exception reaches you:
|
|
162
|
+
5 attempts, exponential backoff from 0.5s capped at 8s, on `429`, `502` and
|
|
163
|
+
`503` only. Tune it if you must:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from jumptech_sdk import JumpTech, RetryPolicy
|
|
167
|
+
|
|
168
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...",
|
|
169
|
+
policy=RetryPolicy(max_attempts=3, base_delay=1.0))
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Orders
|
|
173
|
+
|
|
174
|
+
Placement is asynchronous — a 202 and a request id. `place()` polls it to a
|
|
175
|
+
terminal state; `place_async()` hands you the id.
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from jumptech_sdk.models import PlaceOrderRequest
|
|
179
|
+
|
|
180
|
+
fill = jt.positions.place(PlaceOrderRequest(
|
|
181
|
+
symbol="EURUSD", cmd=0, volume=0.10, login=5001
|
|
182
|
+
))
|
|
183
|
+
print(fill.order, fill.open_price) # cmd: 0=buy, 1=sell. Ticket is `order`.
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A rejection raises rather than returning a status: `MarginRejected` for
|
|
187
|
+
insufficient margin, `OrderRejected` otherwise, and `OrderRequestExpired` if the
|
|
188
|
+
request id aged out — which says nothing about whether the order executed, so
|
|
189
|
+
check the book before retrying.
|
|
190
|
+
|
|
191
|
+
## Events
|
|
192
|
+
|
|
193
|
+
One handler, two delivery routes, deduped against each other because both share
|
|
194
|
+
the same store:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from fastapi import FastAPI
|
|
198
|
+
|
|
199
|
+
from jumptech_sdk import JumpTech
|
|
200
|
+
|
|
201
|
+
app = FastAPI()
|
|
202
|
+
jt = JumpTech("https://api.yourbroker.com", api_key="jt_live_...",
|
|
203
|
+
webhook_secret="whsec_...") # jt.webhooks is None without this
|
|
204
|
+
|
|
205
|
+
@jt.on_event
|
|
206
|
+
def handle(event):
|
|
207
|
+
print(event["type"], event["event_id"])
|
|
208
|
+
|
|
209
|
+
jt.webhooks.mount(app, "/jt") # push: verifies, dedupes, dispatches
|
|
210
|
+
jt.events.reconcile() # pull: same handler, same dedupe store
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Flask and Django get `jt.webhooks.flask_view()` and `jt.webhooks.django_view()`.
|
|
214
|
+
Use an adapter rather than verifying by hand: the signature is computed over the
|
|
215
|
+
**raw bytes**, and a handler that verifies against a re-serialised object rejects
|
|
216
|
+
every delivery.
|
|
217
|
+
|
|
218
|
+
Your handler runs **at most once per event** across both routes, and only counts
|
|
219
|
+
as handled once it returns — if it raises, nothing is recorded and the event is
|
|
220
|
+
redelivered.
|
|
221
|
+
|
|
222
|
+
Reconcile is one pass — schedule it with whatever you already use. Treat
|
|
223
|
+
`GET /v1/events` as the system of record and webhooks as an optimisation, not the
|
|
224
|
+
other way round.
|
|
225
|
+
|
|
226
|
+
## After a crash
|
|
227
|
+
|
|
228
|
+
`recover()` finishes every pending intent with its ORIGINAL key, so each returns
|
|
229
|
+
the original answer instead of booking a second one. It hands back one
|
|
230
|
+
`(key, outcome)` per intent — the response, or the exception if that one did not
|
|
231
|
+
complete. An intent whose last outcome was unknown (a 5xx, or a read timeout: the
|
|
232
|
+
handler may have committed and the API does not cache either) is refused, and its
|
|
233
|
+
outcome says so. Reconcile those, then resolve them by hand.
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
for key, intent in jt.unresolved():
|
|
237
|
+
... # reconcile against GET /v1/events or the
|
|
238
|
+
# resource itself, then:
|
|
239
|
+
jt.store.resolve_intent(key, "done")
|
|
240
|
+
|
|
241
|
+
for key, outcome in jt.recover():
|
|
242
|
+
if isinstance(outcome, Exception):
|
|
243
|
+
... # this one did not finish; the others still ran
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Call `recover()` on startup. It is the payoff for the store being on disk.
|
|
247
|
+
|
|
248
|
+
## Async
|
|
249
|
+
|
|
250
|
+
`AsyncJumpTech` in `jumptech_sdk.aio` is the same API with `await`, and
|
|
251
|
+
`jt.events.stream()` becomes an async generator:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
from jumptech_sdk.aio import AsyncJumpTech
|
|
255
|
+
|
|
256
|
+
jt = AsyncJumpTech("https://api.yourbroker.com", api_key="jt_live_...")
|
|
257
|
+
|
|
258
|
+
async def consume():
|
|
259
|
+
async for event in jt.events.stream():
|
|
260
|
+
...
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`stream()` yields **per event, not per page**, so persisting after each one costs
|
|
264
|
+
one duplicate on a crash instead of a page. It does not stop at the end of the
|
|
265
|
+
backlog — it keeps polling, so catch-up and live tail are the same loop.
|
|
266
|
+
|
|
267
|
+
## State
|
|
268
|
+
|
|
269
|
+
A local sqlite file (`jumptech.db` by default) holds pending idempotency intents
|
|
270
|
+
and handled event ids. Point it somewhere durable in production:
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
jt = JumpTech(
|
|
274
|
+
"https://api.yourbroker.com", api_key="jt_live_...",
|
|
275
|
+
store_path="/var/lib/yourapp/jumptech.db",
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
An in-memory store does not survive the crash it exists to protect against, so
|
|
280
|
+
`InMemoryStore` is for tests only. Implement the `Store` protocol to put this in
|
|
281
|
+
your own database instead.
|
|
282
|
+
|
|
283
|
+
Both clients close their connection pool and their store — `jt.close()`, or
|
|
284
|
+
`with JumpTech(...) as jt:` (`await jt.aclose()` / `async with` on the async
|
|
285
|
+
one).
|
|
286
|
+
|
|
287
|
+
## Going to production
|
|
288
|
+
|
|
289
|
+
- [ ] Swap the `jt_demo_` key for `jt_live_`.
|
|
290
|
+
- [ ] Point `store_path` at durable, writable disk that survives a redeploy.
|
|
291
|
+
- [ ] Call `jt.recover()` on startup.
|
|
292
|
+
- [ ] Schedule `jt.events.reconcile()` — webhooks alone will miss events.
|
|
293
|
+
- [ ] Decide what `UnknownOutcome` does in your system. It is the only outcome
|
|
294
|
+
that needs a human or a reconciliation, and it will happen.
|
|
295
|
+
- [ ] Log `request_id` from every `JumpTechError`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Python client for the JumpTech engine /v1 API."""
|
|
2
|
+
|
|
3
|
+
from jumptech_sdk.aio import AsyncJumpTech
|
|
4
|
+
from jumptech_sdk.client import JumpTech, __version__
|
|
5
|
+
from jumptech_sdk.errors import (
|
|
6
|
+
AuthError,
|
|
7
|
+
Conflict,
|
|
8
|
+
InsufficientMargin,
|
|
9
|
+
JumpTechError,
|
|
10
|
+
MissingIdempotencyKey,
|
|
11
|
+
NotFound,
|
|
12
|
+
RateLimited,
|
|
13
|
+
Unavailable,
|
|
14
|
+
UnknownOutcome,
|
|
15
|
+
ValidationError,
|
|
16
|
+
)
|
|
17
|
+
from jumptech_sdk.idempotency import RetryPolicy
|
|
18
|
+
from jumptech_sdk.resources.positions import (
|
|
19
|
+
MarginRejected,
|
|
20
|
+
OrderRejected,
|
|
21
|
+
OrderRequestExpired,
|
|
22
|
+
)
|
|
23
|
+
from jumptech_sdk.signing import MAX_SKEW_S, verify
|
|
24
|
+
from jumptech_sdk.stores import InMemoryStore, SqliteStore, Store
|
|
25
|
+
from jumptech_sdk.webhooks import SignatureError
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
# The two clients.
|
|
29
|
+
"JumpTech",
|
|
30
|
+
"AsyncJumpTech",
|
|
31
|
+
# The taxonomy an integrator writes `except` clauses against.
|
|
32
|
+
"AuthError",
|
|
33
|
+
"Conflict",
|
|
34
|
+
"InsufficientMargin",
|
|
35
|
+
"JumpTechError",
|
|
36
|
+
"MissingIdempotencyKey",
|
|
37
|
+
"NotFound",
|
|
38
|
+
"RateLimited",
|
|
39
|
+
"Unavailable",
|
|
40
|
+
"UnknownOutcome",
|
|
41
|
+
"ValidationError",
|
|
42
|
+
# Order rejections, including MarginRejected — the class `place()` raises
|
|
43
|
+
# for an async `insufficient_margin`, which was reachable but unexported.
|
|
44
|
+
"OrderRejected",
|
|
45
|
+
"MarginRejected",
|
|
46
|
+
"OrderRequestExpired",
|
|
47
|
+
"SignatureError",
|
|
48
|
+
# Stores, and the Protocol to implement a custom one against.
|
|
49
|
+
"InMemoryStore",
|
|
50
|
+
"SqliteStore",
|
|
51
|
+
"Store",
|
|
52
|
+
# `RetryPolicy` is a constructor argument, so it belongs on the front door.
|
|
53
|
+
"RetryPolicy",
|
|
54
|
+
# For a receiver that is not using `Webhooks` — the executable verifier
|
|
55
|
+
# docs/v1-api.md publishes, and the skew window it must enforce.
|
|
56
|
+
"verify",
|
|
57
|
+
"MAX_SKEW_S",
|
|
58
|
+
# On the front door because a bug report starts with it, and because
|
|
59
|
+
# `doctor` prints it. `client.py` derives it from installed metadata.
|
|
60
|
+
"__version__",
|
|
61
|
+
]
|