webull-openapi-python-sdk 1.0.0__py3-none-any.whl
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.
- samples/__init__.py +1 -0
- samples/data/__init__.py +1 -0
- samples/data/data_client.py +57 -0
- samples/data/data_streaming_client.py +86 -0
- samples/data/data_streaming_client_async.py +101 -0
- samples/trade/__init__.py +0 -0
- samples/trade/trade_client.py +163 -0
- samples/trade/trade_client_v2.py +181 -0
- samples/trade/trade_event_client.py +47 -0
- webull/__init__.py +1 -0
- webull/core/__init__.py +12 -0
- webull/core/auth/__init__.py +0 -0
- webull/core/auth/algorithm/__init__.py +0 -0
- webull/core/auth/algorithm/sha_hmac1.py +65 -0
- webull/core/auth/algorithm/sha_hmac256.py +75 -0
- webull/core/auth/composer/__init__.py +0 -0
- webull/core/auth/composer/default_signature_composer.py +125 -0
- webull/core/auth/credentials.py +46 -0
- webull/core/auth/signers/__init__.py +0 -0
- webull/core/auth/signers/app_key_signer.py +72 -0
- webull/core/auth/signers/signer.py +48 -0
- webull/core/auth/signers/signer_factory.py +58 -0
- webull/core/cache/__init__.py +225 -0
- webull/core/client.py +410 -0
- webull/core/common/__init__.py +0 -0
- webull/core/common/api_type.py +19 -0
- webull/core/common/easy_enum.py +35 -0
- webull/core/common/region.py +7 -0
- webull/core/compat.py +85 -0
- webull/core/context/__init__.py +0 -0
- webull/core/context/request_context_holder.py +33 -0
- webull/core/data/endpoints.json +22 -0
- webull/core/data/retry_config.json +15 -0
- webull/core/endpoint/__init__.py +8 -0
- webull/core/endpoint/chained_endpoint_resolver.py +57 -0
- webull/core/endpoint/default_endpoint_resolver.py +60 -0
- webull/core/endpoint/local_config_regional_endpoint_resolver.py +77 -0
- webull/core/endpoint/resolver_endpoint_request.py +46 -0
- webull/core/endpoint/user_customized_endpoint_resolver.py +55 -0
- webull/core/exception/__init__.py +0 -0
- webull/core/exception/error_code.py +23 -0
- webull/core/exception/error_msg.py +21 -0
- webull/core/exception/exceptions.py +53 -0
- webull/core/headers.py +57 -0
- webull/core/http/__init__.py +0 -0
- webull/core/http/initializer/__init__.py +0 -0
- webull/core/http/initializer/client_initializer.py +79 -0
- webull/core/http/initializer/token/__init__.py +0 -0
- webull/core/http/initializer/token/bean/__init__.py +0 -0
- webull/core/http/initializer/token/bean/access_token.py +40 -0
- webull/core/http/initializer/token/bean/check_token_request.py +44 -0
- webull/core/http/initializer/token/bean/create_token_request.py +45 -0
- webull/core/http/initializer/token/bean/refresh_token_request.py +44 -0
- webull/core/http/initializer/token/token_manager.py +208 -0
- webull/core/http/initializer/token/token_operation.py +72 -0
- webull/core/http/method_type.py +43 -0
- webull/core/http/protocol_type.py +43 -0
- webull/core/http/request.py +121 -0
- webull/core/http/response.py +166 -0
- webull/core/request.py +278 -0
- webull/core/retry/__init__.py +0 -0
- webull/core/retry/backoff_strategy.py +102 -0
- webull/core/retry/retry_condition.py +214 -0
- webull/core/retry/retry_policy.py +63 -0
- webull/core/retry/retry_policy_context.py +51 -0
- webull/core/utils/__init__.py +0 -0
- webull/core/utils/common.py +62 -0
- webull/core/utils/data.py +25 -0
- webull/core/utils/desensitize.py +33 -0
- webull/core/utils/validation.py +49 -0
- webull/core/vendored/__init__.py +0 -0
- webull/core/vendored/requests/__init__.py +94 -0
- webull/core/vendored/requests/__version__.py +28 -0
- webull/core/vendored/requests/_internal_utils.py +56 -0
- webull/core/vendored/requests/adapters.py +539 -0
- webull/core/vendored/requests/api.py +166 -0
- webull/core/vendored/requests/auth.py +307 -0
- webull/core/vendored/requests/certs.py +34 -0
- webull/core/vendored/requests/compat.py +85 -0
- webull/core/vendored/requests/cookies.py +555 -0
- webull/core/vendored/requests/exceptions.py +136 -0
- webull/core/vendored/requests/help.py +134 -0
- webull/core/vendored/requests/hooks.py +48 -0
- webull/core/vendored/requests/models.py +960 -0
- webull/core/vendored/requests/packages/__init__.py +17 -0
- webull/core/vendored/requests/packages/certifi/__init__.py +17 -0
- webull/core/vendored/requests/packages/certifi/__main__.py +16 -0
- webull/core/vendored/requests/packages/certifi/cacert.pem +4433 -0
- webull/core/vendored/requests/packages/certifi/core.py +51 -0
- webull/core/vendored/requests/packages/chardet/__init__.py +53 -0
- webull/core/vendored/requests/packages/chardet/big5freq.py +400 -0
- webull/core/vendored/requests/packages/chardet/big5prober.py +61 -0
- webull/core/vendored/requests/packages/chardet/chardistribution.py +247 -0
- webull/core/vendored/requests/packages/chardet/charsetgroupprober.py +120 -0
- webull/core/vendored/requests/packages/chardet/charsetprober.py +159 -0
- webull/core/vendored/requests/packages/chardet/cli/__init__.py +1 -0
- webull/core/vendored/requests/packages/chardet/cli/chardetect.py +99 -0
- webull/core/vendored/requests/packages/chardet/codingstatemachine.py +102 -0
- webull/core/vendored/requests/packages/chardet/compat.py +48 -0
- webull/core/vendored/requests/packages/chardet/cp949prober.py +63 -0
- webull/core/vendored/requests/packages/chardet/enums.py +90 -0
- webull/core/vendored/requests/packages/chardet/escprober.py +115 -0
- webull/core/vendored/requests/packages/chardet/escsm.py +260 -0
- webull/core/vendored/requests/packages/chardet/eucjpprober.py +106 -0
- webull/core/vendored/requests/packages/chardet/euckrfreq.py +209 -0
- webull/core/vendored/requests/packages/chardet/euckrprober.py +61 -0
- webull/core/vendored/requests/packages/chardet/euctwfreq.py +401 -0
- webull/core/vendored/requests/packages/chardet/euctwprober.py +60 -0
- webull/core/vendored/requests/packages/chardet/gb2312freq.py +297 -0
- webull/core/vendored/requests/packages/chardet/gb2312prober.py +60 -0
- webull/core/vendored/requests/packages/chardet/hebrewprober.py +306 -0
- webull/core/vendored/requests/packages/chardet/jisfreq.py +339 -0
- webull/core/vendored/requests/packages/chardet/jpcntx.py +247 -0
- webull/core/vendored/requests/packages/chardet/langbulgarianmodel.py +242 -0
- webull/core/vendored/requests/packages/chardet/langcyrillicmodel.py +347 -0
- webull/core/vendored/requests/packages/chardet/langgreekmodel.py +239 -0
- webull/core/vendored/requests/packages/chardet/langhebrewmodel.py +214 -0
- webull/core/vendored/requests/packages/chardet/langhungarianmodel.py +239 -0
- webull/core/vendored/requests/packages/chardet/langthaimodel.py +213 -0
- webull/core/vendored/requests/packages/chardet/langturkishmodel.py +207 -0
- webull/core/vendored/requests/packages/chardet/latin1prober.py +159 -0
- webull/core/vendored/requests/packages/chardet/mbcharsetprober.py +105 -0
- webull/core/vendored/requests/packages/chardet/mbcsgroupprober.py +68 -0
- webull/core/vendored/requests/packages/chardet/mbcssm.py +586 -0
- webull/core/vendored/requests/packages/chardet/sbcharsetprober.py +146 -0
- webull/core/vendored/requests/packages/chardet/sbcsgroupprober.py +87 -0
- webull/core/vendored/requests/packages/chardet/sjisprober.py +106 -0
- webull/core/vendored/requests/packages/chardet/universaldetector.py +300 -0
- webull/core/vendored/requests/packages/chardet/utf8prober.py +96 -0
- webull/core/vendored/requests/packages/chardet/version.py +23 -0
- webull/core/vendored/requests/packages/urllib3/__init__.py +114 -0
- webull/core/vendored/requests/packages/urllib3/_collections.py +346 -0
- webull/core/vendored/requests/packages/urllib3/connection.py +405 -0
- webull/core/vendored/requests/packages/urllib3/connectionpool.py +910 -0
- webull/core/vendored/requests/packages/urllib3/contrib/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_appengine_environ.py +44 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/bindings.py +607 -0
- webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/low_level.py +360 -0
- webull/core/vendored/requests/packages/urllib3/contrib/appengine.py +303 -0
- webull/core/vendored/requests/packages/urllib3/contrib/ntlmpool.py +125 -0
- webull/core/vendored/requests/packages/urllib3/contrib/pyopenssl.py +484 -0
- webull/core/vendored/requests/packages/urllib3/contrib/securetransport.py +818 -0
- webull/core/vendored/requests/packages/urllib3/contrib/socks.py +206 -0
- webull/core/vendored/requests/packages/urllib3/exceptions.py +260 -0
- webull/core/vendored/requests/packages/urllib3/fields.py +192 -0
- webull/core/vendored/requests/packages/urllib3/filepost.py +112 -0
- webull/core/vendored/requests/packages/urllib3/packages/__init__.py +19 -0
- webull/core/vendored/requests/packages/urllib3/packages/backports/__init__.py +0 -0
- webull/core/vendored/requests/packages/urllib3/packages/backports/makefile.py +67 -0
- webull/core/vendored/requests/packages/urllib3/packages/ordered_dict.py +273 -0
- webull/core/vendored/requests/packages/urllib3/packages/six.py +882 -0
- webull/core/vendored/requests/packages/urllib3/packages/socks.py +887 -0
- webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +19 -0
- webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py +170 -0
- webull/core/vendored/requests/packages/urllib3/poolmanager.py +467 -0
- webull/core/vendored/requests/packages/urllib3/request.py +164 -0
- webull/core/vendored/requests/packages/urllib3/response.py +721 -0
- webull/core/vendored/requests/packages/urllib3/util/__init__.py +68 -0
- webull/core/vendored/requests/packages/urllib3/util/connection.py +148 -0
- webull/core/vendored/requests/packages/urllib3/util/queue.py +35 -0
- webull/core/vendored/requests/packages/urllib3/util/request.py +132 -0
- webull/core/vendored/requests/packages/urllib3/util/response.py +101 -0
- webull/core/vendored/requests/packages/urllib3/util/retry.py +426 -0
- webull/core/vendored/requests/packages/urllib3/util/selectors.py +601 -0
- webull/core/vendored/requests/packages/urllib3/util/ssl_.py +396 -0
- webull/core/vendored/requests/packages/urllib3/util/timeout.py +256 -0
- webull/core/vendored/requests/packages/urllib3/util/url.py +252 -0
- webull/core/vendored/requests/packages/urllib3/util/wait.py +164 -0
- webull/core/vendored/requests/packages.py +28 -0
- webull/core/vendored/requests/sessions.py +750 -0
- webull/core/vendored/requests/status_codes.py +105 -0
- webull/core/vendored/requests/structures.py +119 -0
- webull/core/vendored/requests/utils.py +916 -0
- webull/core/vendored/six.py +905 -0
- webull/data/__init__.py +3 -0
- webull/data/common/__init__.py +0 -0
- webull/data/common/category.py +26 -0
- webull/data/common/connect_ack.py +29 -0
- webull/data/common/direction.py +25 -0
- webull/data/common/exchange_code.py +33 -0
- webull/data/common/exercise_style.py +22 -0
- webull/data/common/expiration_cycle.py +26 -0
- webull/data/common/instrument_status.py +23 -0
- webull/data/common/option_type.py +20 -0
- webull/data/common/subscribe_type.py +22 -0
- webull/data/common/timespan.py +29 -0
- webull/data/data_client.py +35 -0
- webull/data/data_streaming_client.py +89 -0
- webull/data/internal/__init__.py +0 -0
- webull/data/internal/default_retry_policy.py +84 -0
- webull/data/internal/exceptions.py +60 -0
- webull/data/internal/quotes_client.py +314 -0
- webull/data/internal/quotes_decoder.py +40 -0
- webull/data/internal/quotes_payload_decoder.py +35 -0
- webull/data/internal/quotes_topic.py +36 -0
- webull/data/quotes/__init__.py +0 -0
- webull/data/quotes/instrument.py +33 -0
- webull/data/quotes/market_data.py +187 -0
- webull/data/quotes/market_streaming_data.py +66 -0
- webull/data/quotes/subscribe/__init__.py +0 -0
- webull/data/quotes/subscribe/ask_bid_result.py +49 -0
- webull/data/quotes/subscribe/basic_result.py +45 -0
- webull/data/quotes/subscribe/broker_result.py +33 -0
- webull/data/quotes/subscribe/message_pb2.py +37 -0
- webull/data/quotes/subscribe/order_result.py +30 -0
- webull/data/quotes/subscribe/payload_type.py +19 -0
- webull/data/quotes/subscribe/quote_decoder.py +28 -0
- webull/data/quotes/subscribe/quote_result.py +47 -0
- webull/data/quotes/subscribe/snapshot_decoder.py +30 -0
- webull/data/quotes/subscribe/snapshot_result.py +69 -0
- webull/data/quotes/subscribe/tick_decoder.py +29 -0
- webull/data/quotes/subscribe/tick_result.py +47 -0
- webull/data/request/__init__.py +0 -0
- webull/data/request/get_batch_historical_bars_request.py +43 -0
- webull/data/request/get_corp_action_request.py +47 -0
- webull/data/request/get_eod_bars_request.py +32 -0
- webull/data/request/get_historical_bars_request.py +43 -0
- webull/data/request/get_instruments_request.py +30 -0
- webull/data/request/get_quotes_request.py +35 -0
- webull/data/request/get_snapshot_request.py +38 -0
- webull/data/request/get_tick_request.py +37 -0
- webull/data/request/subscribe_request.py +43 -0
- webull/data/request/unsubscribe_request.py +42 -0
- webull/trade/__init__.py +2 -0
- webull/trade/common/__init__.py +0 -0
- webull/trade/common/account_type.py +22 -0
- webull/trade/common/category.py +29 -0
- webull/trade/common/combo_ticker_type.py +23 -0
- webull/trade/common/combo_type.py +31 -0
- webull/trade/common/currency.py +24 -0
- webull/trade/common/forbid_reason.py +27 -0
- webull/trade/common/instrument_type.py +27 -0
- webull/trade/common/markets.py +27 -0
- webull/trade/common/order_entrust_type.py +21 -0
- webull/trade/common/order_side.py +23 -0
- webull/trade/common/order_status.py +25 -0
- webull/trade/common/order_tif.py +24 -0
- webull/trade/common/order_type.py +30 -0
- webull/trade/common/trade_policy.py +22 -0
- webull/trade/common/trading_date_type.py +24 -0
- webull/trade/common/trailing_type.py +23 -0
- webull/trade/events/__init__.py +0 -0
- webull/trade/events/default_retry_policy.py +64 -0
- webull/trade/events/events_pb2.py +43 -0
- webull/trade/events/events_pb2_grpc.py +66 -0
- webull/trade/events/signature_composer.py +61 -0
- webull/trade/events/types.py +21 -0
- webull/trade/request/__init__.py +0 -0
- webull/trade/request/cancel_order_request.py +28 -0
- webull/trade/request/get_account_balance_request.py +28 -0
- webull/trade/request/get_account_positions_request.py +30 -0
- webull/trade/request/get_account_profile_request.py +26 -0
- webull/trade/request/get_app_subscriptions.py +28 -0
- webull/trade/request/get_open_orders_request.py +30 -0
- webull/trade/request/get_order_detail_request.py +27 -0
- webull/trade/request/get_today_orders_request.py +31 -0
- webull/trade/request/get_trade_calendar_request.py +30 -0
- webull/trade/request/get_trade_instrument_detail_request.py +24 -0
- webull/trade/request/get_trade_security_detail_request.py +42 -0
- webull/trade/request/get_tradeable_instruments_request.py +27 -0
- webull/trade/request/palce_order_request.py +91 -0
- webull/trade/request/place_order_request_v2.py +58 -0
- webull/trade/request/replace_order_request.py +73 -0
- webull/trade/request/replace_order_request_v2.py +38 -0
- webull/trade/request/v2/__init__.py +0 -0
- webull/trade/request/v2/cancel_option_request.py +28 -0
- webull/trade/request/v2/cancel_order_request.py +28 -0
- webull/trade/request/v2/get_account_balance_request.py +28 -0
- webull/trade/request/v2/get_account_list.py +23 -0
- webull/trade/request/v2/get_account_positions_request.py +24 -0
- webull/trade/request/v2/get_order_detail_request.py +26 -0
- webull/trade/request/v2/get_order_history_request.py +35 -0
- webull/trade/request/v2/palce_order_request.py +87 -0
- webull/trade/request/v2/place_option_request.py +64 -0
- webull/trade/request/v2/preview_option_request.py +28 -0
- webull/trade/request/v2/preview_order_request.py +59 -0
- webull/trade/request/v2/replace_option_request.py +28 -0
- webull/trade/request/v2/replace_order_request.py +57 -0
- webull/trade/trade/__init__.py +0 -0
- webull/trade/trade/account_info.py +83 -0
- webull/trade/trade/order_operation.py +246 -0
- webull/trade/trade/trade_calendar.py +37 -0
- webull/trade/trade/trade_instrument.py +72 -0
- webull/trade/trade/v2/__init__.py +0 -0
- webull/trade/trade/v2/account_info_v2.py +55 -0
- webull/trade/trade/v2/order_operation_v2.py +206 -0
- webull/trade/trade_client.py +43 -0
- webull/trade/trade_events_client.py +233 -0
- webull_openapi_python_sdk-1.0.0.dist-info/METADATA +28 -0
- webull_openapi_python_sdk-1.0.0.dist-info/RECORD +295 -0
- webull_openapi_python_sdk-1.0.0.dist-info/WHEEL +5 -0
- webull_openapi_python_sdk-1.0.0.dist-info/licenses/LICENSE +202 -0
- webull_openapi_python_sdk-1.0.0.dist-info/licenses/NOTICE +56 -0
- webull_openapi_python_sdk-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
# Unless required by applicable law or agreed to in writing,
|
|
26
|
+
# software distributed under the License is distributed on an
|
|
27
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
28
|
+
# KIND, either express or implied. See the License for the
|
|
29
|
+
# specific language governing permissions and limitations
|
|
30
|
+
# under the License.
|
|
31
|
+
|
|
32
|
+
# coding=utf-8
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
This file borrowed some of its methods from a modified fork of the
|
|
36
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/algorithm/sha_hmac1.py
|
|
37
|
+
which was part of Alibaba Group.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
import hashlib
|
|
41
|
+
import hmac
|
|
42
|
+
|
|
43
|
+
from webull.core.compat import ensure_string
|
|
44
|
+
from webull.core.compat import ensure_bytes
|
|
45
|
+
from webull.core.compat import b64_encode_bytes
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_sign_string(source, secret):
|
|
49
|
+
source = ensure_bytes(source)
|
|
50
|
+
secret = ensure_bytes(secret)
|
|
51
|
+
h = hmac.new(secret, source, hashlib.sha1)
|
|
52
|
+
signature = ensure_string(b64_encode_bytes(h.digest()).strip())
|
|
53
|
+
return signature
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_signer_name():
|
|
57
|
+
return "HMAC-SHA1"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_signer_version():
|
|
61
|
+
return "1.0"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get_signer_type():
|
|
65
|
+
return ""
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
# Unless required by applicable law or agreed to in writing,
|
|
26
|
+
# software distributed under the License is distributed on an
|
|
27
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
28
|
+
# KIND, either express or implied. See the License for the
|
|
29
|
+
# specific language governing permissions and limitations
|
|
30
|
+
# under the License.
|
|
31
|
+
|
|
32
|
+
# coding=utf-8
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
This file borrowed some of its methods from a modified fork of the
|
|
36
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/algorithm/sha_hmac256.py
|
|
37
|
+
which was part of Alibaba Group.
|
|
38
|
+
"""
|
|
39
|
+
from cryptography.hazmat.backends import default_backend
|
|
40
|
+
from cryptography.hazmat.primitives import hashes
|
|
41
|
+
from cryptography.hazmat.primitives.asymmetric import padding
|
|
42
|
+
from cryptography.hazmat.primitives.serialization import load_der_private_key
|
|
43
|
+
|
|
44
|
+
from webull.core.compat import ensure_string
|
|
45
|
+
from webull.core.compat import ensure_bytes
|
|
46
|
+
from webull.core.compat import b64_encode_bytes
|
|
47
|
+
from webull.core.compat import b64_decode_bytes
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_sign_string(source, access_secret):
|
|
51
|
+
key = load_der_private_key(
|
|
52
|
+
b64_decode_bytes(ensure_bytes(access_secret)),
|
|
53
|
+
password=None,
|
|
54
|
+
backend=default_backend()
|
|
55
|
+
)
|
|
56
|
+
signed_bytes = key.sign(
|
|
57
|
+
ensure_bytes(source),
|
|
58
|
+
padding.PKCS1v15(),
|
|
59
|
+
hashes.SHA256()
|
|
60
|
+
)
|
|
61
|
+
signed_base64 = b64_encode_bytes(signed_bytes)
|
|
62
|
+
signature = ensure_string(signed_base64).replace('\n', '')
|
|
63
|
+
return signature
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_signer_name():
|
|
67
|
+
return "SHA256withRSA"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_signer_version():
|
|
71
|
+
return "1.0"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_signer_type():
|
|
75
|
+
return "PRIVATEKEY"
|
|
File without changes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
# Unless required by applicable law or agreed to in writing,
|
|
26
|
+
# software distributed under the License is distributed on an
|
|
27
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
28
|
+
# KIND, either express or implied. See the License for the
|
|
29
|
+
# specific language governing permissions and limitations
|
|
30
|
+
# under the License.
|
|
31
|
+
|
|
32
|
+
# coding=utf-8
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
This file borrowed some of its methods from a modified fork of the
|
|
36
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/composer/rpc_signature_composer.py
|
|
37
|
+
which was part of Alibaba Group.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from webull.core.auth.algorithm import sha_hmac1
|
|
41
|
+
from webull.core.exception import error_code
|
|
42
|
+
from webull.core.exception.exceptions import ClientException
|
|
43
|
+
from webull.core.utils import common
|
|
44
|
+
import webull.core.headers as hd
|
|
45
|
+
from webull.core.vendored.six import iteritems
|
|
46
|
+
from webull.core.vendored.six.moves.urllib.parse import quote
|
|
47
|
+
import logging
|
|
48
|
+
logger = logging.getLogger(__name__)
|
|
49
|
+
|
|
50
|
+
PARAM_KV_JOIN = "="
|
|
51
|
+
PARAMS_JOIN = "&"
|
|
52
|
+
SECRET_TAILER = "&"
|
|
53
|
+
|
|
54
|
+
def _refresh_sign_headers(host, headers, app_key_id, signer_spec=sha_hmac1):
|
|
55
|
+
if not host:
|
|
56
|
+
raise ClientException(error_code.SDK_INVALID_PARAMETER)
|
|
57
|
+
sign_headers = {}
|
|
58
|
+
sign_headers[hd.APP_KEY] = app_key_id
|
|
59
|
+
sign_headers[hd.TIMESTAMP] = common.get_iso_8601_date()
|
|
60
|
+
sign_headers[hd.SIGN_VERSION] = signer_spec.get_signer_version()
|
|
61
|
+
sign_headers[hd.SIGN_ALGORITHM] = signer_spec.get_signer_name()
|
|
62
|
+
sign_headers[hd.NONCE] = common.get_uuid()
|
|
63
|
+
headers.update(sign_headers)
|
|
64
|
+
# DO NOT PUT Host Header in headers object, just put into sign_headers
|
|
65
|
+
sign_headers[hd.NATIVE_HOST] = host
|
|
66
|
+
return sign_headers
|
|
67
|
+
|
|
68
|
+
def _gen_signature(string_to_sign, secret, signer_spec=sha_hmac1):
|
|
69
|
+
return signer_spec.get_sign_string(string_to_sign, secret + SECRET_TAILER)
|
|
70
|
+
|
|
71
|
+
def _get_body_string(body_params):
|
|
72
|
+
if body_params is not None:
|
|
73
|
+
raw_str = common.json_dumps_compact(body_params)
|
|
74
|
+
hex_digest = common.md5_hex(raw_str)
|
|
75
|
+
return hex_digest.upper()
|
|
76
|
+
else:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
def _build_sign_string(sign_params, uri, body_string):
|
|
80
|
+
string_to_sign = ""
|
|
81
|
+
if uri:
|
|
82
|
+
string_to_sign = uri
|
|
83
|
+
sorted_map = sorted(iteritems(sign_params), key=lambda item: item[0])
|
|
84
|
+
sorted_array = []
|
|
85
|
+
for (k, v) in sorted_map:
|
|
86
|
+
sorted_array.append(str(k) + PARAM_KV_JOIN + v)
|
|
87
|
+
if string_to_sign:
|
|
88
|
+
string_to_sign = string_to_sign + PARAMS_JOIN + PARAMS_JOIN.join(sorted_array)
|
|
89
|
+
else:
|
|
90
|
+
string_to_sign = PARAM_KV_JOIN.join(sorted_array)
|
|
91
|
+
if body_string:
|
|
92
|
+
string_to_sign = string_to_sign + PARAMS_JOIN + body_string
|
|
93
|
+
# All characters except alphabetic characters, digits, -, ., _, ~ will be encoded as %XX.
|
|
94
|
+
# So remove the default safe char '/' which should be quoted as %20F
|
|
95
|
+
return quote(string_to_sign, safe='')
|
|
96
|
+
|
|
97
|
+
def _lower_key_dict(od):
|
|
98
|
+
lower_key_dict = {}
|
|
99
|
+
for (k, v) in iteritems(od):
|
|
100
|
+
lower_key_dict[k.lower()] = v
|
|
101
|
+
return lower_key_dict
|
|
102
|
+
|
|
103
|
+
def calc_signature(headers, host, uri, queries, body_params, app_key_id, app_key_secret, signer_spec=sha_hmac1):
|
|
104
|
+
sign_headers = _refresh_sign_headers(host, headers, app_key_id, signer_spec)
|
|
105
|
+
logger.debug("sign_headers:%s", sign_headers)
|
|
106
|
+
sign_params = _lower_key_dict(sign_headers)
|
|
107
|
+
logger.debug("sign_queries:%s", queries)
|
|
108
|
+
if queries :
|
|
109
|
+
for (k, v) in iteritems(queries):
|
|
110
|
+
cv = sign_params.get(k)
|
|
111
|
+
if cv is not None:
|
|
112
|
+
cv = str(cv) + PARAMS_JOIN + str(v)
|
|
113
|
+
else:
|
|
114
|
+
cv = str(v)
|
|
115
|
+
sign_params[k] = cv
|
|
116
|
+
logger.debug("body:%s", body_params)
|
|
117
|
+
body_string = _get_body_string(body_params)
|
|
118
|
+
logger.debug("body_string:%s" % body_string)
|
|
119
|
+
string_to_sign = _build_sign_string(sign_params, uri, body_string)
|
|
120
|
+
logger.debug("string_to_sign:%s" % string_to_sign)
|
|
121
|
+
signature = _gen_signature(string_to_sign, app_key_secret, signer_spec)
|
|
122
|
+
headers[hd.SIGNATURE] = signature
|
|
123
|
+
logger.debug("signature:%s", signature)
|
|
124
|
+
return signature
|
|
125
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
#
|
|
27
|
+
# Unless required by applicable law or agreed to in writing,
|
|
28
|
+
# software distributed under the License is distributed on an
|
|
29
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
30
|
+
# KIND, either express or implied. See the License for the
|
|
31
|
+
# specific language governing permissions and limitations
|
|
32
|
+
# under the License.
|
|
33
|
+
|
|
34
|
+
# coding=utf-8
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
This file borrowed some of its methods from a modified fork of the
|
|
38
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/credentials.py
|
|
39
|
+
which was part of Alibaba Group.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AppKeyCredential:
|
|
44
|
+
def __init__(self, app_key_id, app_key_secret):
|
|
45
|
+
self.app_key_id = app_key_id
|
|
46
|
+
self.app_key_secret = app_key_secret
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
# Unless required by applicable law or agreed to in writing,
|
|
26
|
+
# software distributed under the License is distributed on an
|
|
27
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
28
|
+
# KIND, either express or implied. See the License for the
|
|
29
|
+
# specific language governing permissions and limitations
|
|
30
|
+
# under the License.
|
|
31
|
+
|
|
32
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
33
|
+
# or more contributor license agreements. See the NOTICE file
|
|
34
|
+
# distributed with this work for additional information
|
|
35
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
36
|
+
# to you under the Apache License, Version 2.0 (the
|
|
37
|
+
# "License"); you may not use this file except in compliance
|
|
38
|
+
# with the License. You may obtain a copy of the License at
|
|
39
|
+
#
|
|
40
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
41
|
+
#
|
|
42
|
+
#
|
|
43
|
+
#
|
|
44
|
+
# Unless required by applicable law or agreed to in writing,
|
|
45
|
+
# software distributed under the License is distributed on an
|
|
46
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
47
|
+
# KIND, either express or implied. See the License for the
|
|
48
|
+
# specific language governing permissions and limitations
|
|
49
|
+
# under the License.
|
|
50
|
+
|
|
51
|
+
# coding=utf-8
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
This file borrowed some of its methods from a modified fork of the
|
|
55
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/signers/access_key_signer.py
|
|
56
|
+
which was part of Alibaba Group.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
import logging
|
|
60
|
+
from webull.core.auth.signers.signer import Signer
|
|
61
|
+
|
|
62
|
+
logger = logging.getLogger(__name__)
|
|
63
|
+
|
|
64
|
+
class AppKeySigner(Signer):
|
|
65
|
+
def __init__(self, app_key_credential):
|
|
66
|
+
self._credential = app_key_credential
|
|
67
|
+
|
|
68
|
+
def sign(self, request):
|
|
69
|
+
cred = self._credential
|
|
70
|
+
host = request.get_endpoint()
|
|
71
|
+
header = request.get_signed_header(host, cred.app_key_id, cred.app_key_secret)
|
|
72
|
+
return header
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
#
|
|
27
|
+
# Unless required by applicable law or agreed to in writing,
|
|
28
|
+
# software distributed under the License is distributed on an
|
|
29
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
30
|
+
# KIND, either express or implied. See the License for the
|
|
31
|
+
# specific language governing permissions and limitations
|
|
32
|
+
# under the License.
|
|
33
|
+
|
|
34
|
+
# coding=utf-8
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
This file borrowed some of its methods from a modified fork of the
|
|
38
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/signers/signer.py
|
|
39
|
+
which was part of Alibaba Group.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from abc import ABCMeta, abstractmethod
|
|
43
|
+
from webull.core.vendored.six import with_metaclass
|
|
44
|
+
|
|
45
|
+
class Signer(with_metaclass(ABCMeta, object)):
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def sign(self, request):
|
|
48
|
+
pass
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright 2022 Webull
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
16
|
+
# or more contributor license agreements. See the NOTICE file
|
|
17
|
+
# distributed with this work for additional information
|
|
18
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
19
|
+
# to you under the Apache License, Version 2.0 (the
|
|
20
|
+
# "License"); you may not use this file except in compliance
|
|
21
|
+
# with the License. You may obtain a copy of the License at
|
|
22
|
+
#
|
|
23
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
#
|
|
27
|
+
# Unless required by applicable law or agreed to in writing,
|
|
28
|
+
# software distributed under the License is distributed on an
|
|
29
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
30
|
+
# KIND, either express or implied. See the License for the
|
|
31
|
+
# specific language governing permissions and limitations
|
|
32
|
+
# under the License.
|
|
33
|
+
|
|
34
|
+
# coding=utf-8
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
This file borrowed some of its methods from a modified fork of the
|
|
38
|
+
https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/auth/signers/signer_factory.py
|
|
39
|
+
which was part of Alibaba Group.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
import os
|
|
43
|
+
from webull.core.auth import credentials
|
|
44
|
+
from webull.core.auth.signers import app_key_signer
|
|
45
|
+
from webull.core.exception import exceptions, error_code
|
|
46
|
+
|
|
47
|
+
class SignerFactory(object):
|
|
48
|
+
@staticmethod
|
|
49
|
+
def get_signer(credential):
|
|
50
|
+
if credential.get('app_key') is not None and credential.get('app_secret') is not None:
|
|
51
|
+
ak_cred = credentials.AppKeyCredential(credential.get('app_key'), credential.get('app_secret'))
|
|
52
|
+
return app_key_signer.AppKeySigner(ak_cred)
|
|
53
|
+
elif os.environ.get('WEBULL_APP_KEY_ID') is not None \
|
|
54
|
+
and os.environ.get('WEBULL_APP_KEY_SECRET') is not None:
|
|
55
|
+
ak_cred = credentials.AppKeyCredential(os.environ.get('WEBULL_APP_KEY_ID'), os.environ.get('WEBULL_APP_KEY_SECRET'))
|
|
56
|
+
return app_key_signer.AppKeySigner(ak_cred)
|
|
57
|
+
else:
|
|
58
|
+
raise exceptions.ClientException(error_code.SDK_INVALID_CREDENTIAL)
|