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.
Files changed (295) hide show
  1. samples/__init__.py +1 -0
  2. samples/data/__init__.py +1 -0
  3. samples/data/data_client.py +57 -0
  4. samples/data/data_streaming_client.py +86 -0
  5. samples/data/data_streaming_client_async.py +101 -0
  6. samples/trade/__init__.py +0 -0
  7. samples/trade/trade_client.py +163 -0
  8. samples/trade/trade_client_v2.py +181 -0
  9. samples/trade/trade_event_client.py +47 -0
  10. webull/__init__.py +1 -0
  11. webull/core/__init__.py +12 -0
  12. webull/core/auth/__init__.py +0 -0
  13. webull/core/auth/algorithm/__init__.py +0 -0
  14. webull/core/auth/algorithm/sha_hmac1.py +65 -0
  15. webull/core/auth/algorithm/sha_hmac256.py +75 -0
  16. webull/core/auth/composer/__init__.py +0 -0
  17. webull/core/auth/composer/default_signature_composer.py +125 -0
  18. webull/core/auth/credentials.py +46 -0
  19. webull/core/auth/signers/__init__.py +0 -0
  20. webull/core/auth/signers/app_key_signer.py +72 -0
  21. webull/core/auth/signers/signer.py +48 -0
  22. webull/core/auth/signers/signer_factory.py +58 -0
  23. webull/core/cache/__init__.py +225 -0
  24. webull/core/client.py +410 -0
  25. webull/core/common/__init__.py +0 -0
  26. webull/core/common/api_type.py +19 -0
  27. webull/core/common/easy_enum.py +35 -0
  28. webull/core/common/region.py +7 -0
  29. webull/core/compat.py +85 -0
  30. webull/core/context/__init__.py +0 -0
  31. webull/core/context/request_context_holder.py +33 -0
  32. webull/core/data/endpoints.json +22 -0
  33. webull/core/data/retry_config.json +15 -0
  34. webull/core/endpoint/__init__.py +8 -0
  35. webull/core/endpoint/chained_endpoint_resolver.py +57 -0
  36. webull/core/endpoint/default_endpoint_resolver.py +60 -0
  37. webull/core/endpoint/local_config_regional_endpoint_resolver.py +77 -0
  38. webull/core/endpoint/resolver_endpoint_request.py +46 -0
  39. webull/core/endpoint/user_customized_endpoint_resolver.py +55 -0
  40. webull/core/exception/__init__.py +0 -0
  41. webull/core/exception/error_code.py +23 -0
  42. webull/core/exception/error_msg.py +21 -0
  43. webull/core/exception/exceptions.py +53 -0
  44. webull/core/headers.py +57 -0
  45. webull/core/http/__init__.py +0 -0
  46. webull/core/http/initializer/__init__.py +0 -0
  47. webull/core/http/initializer/client_initializer.py +79 -0
  48. webull/core/http/initializer/token/__init__.py +0 -0
  49. webull/core/http/initializer/token/bean/__init__.py +0 -0
  50. webull/core/http/initializer/token/bean/access_token.py +40 -0
  51. webull/core/http/initializer/token/bean/check_token_request.py +44 -0
  52. webull/core/http/initializer/token/bean/create_token_request.py +45 -0
  53. webull/core/http/initializer/token/bean/refresh_token_request.py +44 -0
  54. webull/core/http/initializer/token/token_manager.py +208 -0
  55. webull/core/http/initializer/token/token_operation.py +72 -0
  56. webull/core/http/method_type.py +43 -0
  57. webull/core/http/protocol_type.py +43 -0
  58. webull/core/http/request.py +121 -0
  59. webull/core/http/response.py +166 -0
  60. webull/core/request.py +278 -0
  61. webull/core/retry/__init__.py +0 -0
  62. webull/core/retry/backoff_strategy.py +102 -0
  63. webull/core/retry/retry_condition.py +214 -0
  64. webull/core/retry/retry_policy.py +63 -0
  65. webull/core/retry/retry_policy_context.py +51 -0
  66. webull/core/utils/__init__.py +0 -0
  67. webull/core/utils/common.py +62 -0
  68. webull/core/utils/data.py +25 -0
  69. webull/core/utils/desensitize.py +33 -0
  70. webull/core/utils/validation.py +49 -0
  71. webull/core/vendored/__init__.py +0 -0
  72. webull/core/vendored/requests/__init__.py +94 -0
  73. webull/core/vendored/requests/__version__.py +28 -0
  74. webull/core/vendored/requests/_internal_utils.py +56 -0
  75. webull/core/vendored/requests/adapters.py +539 -0
  76. webull/core/vendored/requests/api.py +166 -0
  77. webull/core/vendored/requests/auth.py +307 -0
  78. webull/core/vendored/requests/certs.py +34 -0
  79. webull/core/vendored/requests/compat.py +85 -0
  80. webull/core/vendored/requests/cookies.py +555 -0
  81. webull/core/vendored/requests/exceptions.py +136 -0
  82. webull/core/vendored/requests/help.py +134 -0
  83. webull/core/vendored/requests/hooks.py +48 -0
  84. webull/core/vendored/requests/models.py +960 -0
  85. webull/core/vendored/requests/packages/__init__.py +17 -0
  86. webull/core/vendored/requests/packages/certifi/__init__.py +17 -0
  87. webull/core/vendored/requests/packages/certifi/__main__.py +16 -0
  88. webull/core/vendored/requests/packages/certifi/cacert.pem +4433 -0
  89. webull/core/vendored/requests/packages/certifi/core.py +51 -0
  90. webull/core/vendored/requests/packages/chardet/__init__.py +53 -0
  91. webull/core/vendored/requests/packages/chardet/big5freq.py +400 -0
  92. webull/core/vendored/requests/packages/chardet/big5prober.py +61 -0
  93. webull/core/vendored/requests/packages/chardet/chardistribution.py +247 -0
  94. webull/core/vendored/requests/packages/chardet/charsetgroupprober.py +120 -0
  95. webull/core/vendored/requests/packages/chardet/charsetprober.py +159 -0
  96. webull/core/vendored/requests/packages/chardet/cli/__init__.py +1 -0
  97. webull/core/vendored/requests/packages/chardet/cli/chardetect.py +99 -0
  98. webull/core/vendored/requests/packages/chardet/codingstatemachine.py +102 -0
  99. webull/core/vendored/requests/packages/chardet/compat.py +48 -0
  100. webull/core/vendored/requests/packages/chardet/cp949prober.py +63 -0
  101. webull/core/vendored/requests/packages/chardet/enums.py +90 -0
  102. webull/core/vendored/requests/packages/chardet/escprober.py +115 -0
  103. webull/core/vendored/requests/packages/chardet/escsm.py +260 -0
  104. webull/core/vendored/requests/packages/chardet/eucjpprober.py +106 -0
  105. webull/core/vendored/requests/packages/chardet/euckrfreq.py +209 -0
  106. webull/core/vendored/requests/packages/chardet/euckrprober.py +61 -0
  107. webull/core/vendored/requests/packages/chardet/euctwfreq.py +401 -0
  108. webull/core/vendored/requests/packages/chardet/euctwprober.py +60 -0
  109. webull/core/vendored/requests/packages/chardet/gb2312freq.py +297 -0
  110. webull/core/vendored/requests/packages/chardet/gb2312prober.py +60 -0
  111. webull/core/vendored/requests/packages/chardet/hebrewprober.py +306 -0
  112. webull/core/vendored/requests/packages/chardet/jisfreq.py +339 -0
  113. webull/core/vendored/requests/packages/chardet/jpcntx.py +247 -0
  114. webull/core/vendored/requests/packages/chardet/langbulgarianmodel.py +242 -0
  115. webull/core/vendored/requests/packages/chardet/langcyrillicmodel.py +347 -0
  116. webull/core/vendored/requests/packages/chardet/langgreekmodel.py +239 -0
  117. webull/core/vendored/requests/packages/chardet/langhebrewmodel.py +214 -0
  118. webull/core/vendored/requests/packages/chardet/langhungarianmodel.py +239 -0
  119. webull/core/vendored/requests/packages/chardet/langthaimodel.py +213 -0
  120. webull/core/vendored/requests/packages/chardet/langturkishmodel.py +207 -0
  121. webull/core/vendored/requests/packages/chardet/latin1prober.py +159 -0
  122. webull/core/vendored/requests/packages/chardet/mbcharsetprober.py +105 -0
  123. webull/core/vendored/requests/packages/chardet/mbcsgroupprober.py +68 -0
  124. webull/core/vendored/requests/packages/chardet/mbcssm.py +586 -0
  125. webull/core/vendored/requests/packages/chardet/sbcharsetprober.py +146 -0
  126. webull/core/vendored/requests/packages/chardet/sbcsgroupprober.py +87 -0
  127. webull/core/vendored/requests/packages/chardet/sjisprober.py +106 -0
  128. webull/core/vendored/requests/packages/chardet/universaldetector.py +300 -0
  129. webull/core/vendored/requests/packages/chardet/utf8prober.py +96 -0
  130. webull/core/vendored/requests/packages/chardet/version.py +23 -0
  131. webull/core/vendored/requests/packages/urllib3/__init__.py +114 -0
  132. webull/core/vendored/requests/packages/urllib3/_collections.py +346 -0
  133. webull/core/vendored/requests/packages/urllib3/connection.py +405 -0
  134. webull/core/vendored/requests/packages/urllib3/connectionpool.py +910 -0
  135. webull/core/vendored/requests/packages/urllib3/contrib/__init__.py +0 -0
  136. webull/core/vendored/requests/packages/urllib3/contrib/_appengine_environ.py +44 -0
  137. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/__init__.py +0 -0
  138. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/bindings.py +607 -0
  139. webull/core/vendored/requests/packages/urllib3/contrib/_securetransport/low_level.py +360 -0
  140. webull/core/vendored/requests/packages/urllib3/contrib/appengine.py +303 -0
  141. webull/core/vendored/requests/packages/urllib3/contrib/ntlmpool.py +125 -0
  142. webull/core/vendored/requests/packages/urllib3/contrib/pyopenssl.py +484 -0
  143. webull/core/vendored/requests/packages/urllib3/contrib/securetransport.py +818 -0
  144. webull/core/vendored/requests/packages/urllib3/contrib/socks.py +206 -0
  145. webull/core/vendored/requests/packages/urllib3/exceptions.py +260 -0
  146. webull/core/vendored/requests/packages/urllib3/fields.py +192 -0
  147. webull/core/vendored/requests/packages/urllib3/filepost.py +112 -0
  148. webull/core/vendored/requests/packages/urllib3/packages/__init__.py +19 -0
  149. webull/core/vendored/requests/packages/urllib3/packages/backports/__init__.py +0 -0
  150. webull/core/vendored/requests/packages/urllib3/packages/backports/makefile.py +67 -0
  151. webull/core/vendored/requests/packages/urllib3/packages/ordered_dict.py +273 -0
  152. webull/core/vendored/requests/packages/urllib3/packages/six.py +882 -0
  153. webull/core/vendored/requests/packages/urllib3/packages/socks.py +887 -0
  154. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +19 -0
  155. webull/core/vendored/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py +170 -0
  156. webull/core/vendored/requests/packages/urllib3/poolmanager.py +467 -0
  157. webull/core/vendored/requests/packages/urllib3/request.py +164 -0
  158. webull/core/vendored/requests/packages/urllib3/response.py +721 -0
  159. webull/core/vendored/requests/packages/urllib3/util/__init__.py +68 -0
  160. webull/core/vendored/requests/packages/urllib3/util/connection.py +148 -0
  161. webull/core/vendored/requests/packages/urllib3/util/queue.py +35 -0
  162. webull/core/vendored/requests/packages/urllib3/util/request.py +132 -0
  163. webull/core/vendored/requests/packages/urllib3/util/response.py +101 -0
  164. webull/core/vendored/requests/packages/urllib3/util/retry.py +426 -0
  165. webull/core/vendored/requests/packages/urllib3/util/selectors.py +601 -0
  166. webull/core/vendored/requests/packages/urllib3/util/ssl_.py +396 -0
  167. webull/core/vendored/requests/packages/urllib3/util/timeout.py +256 -0
  168. webull/core/vendored/requests/packages/urllib3/util/url.py +252 -0
  169. webull/core/vendored/requests/packages/urllib3/util/wait.py +164 -0
  170. webull/core/vendored/requests/packages.py +28 -0
  171. webull/core/vendored/requests/sessions.py +750 -0
  172. webull/core/vendored/requests/status_codes.py +105 -0
  173. webull/core/vendored/requests/structures.py +119 -0
  174. webull/core/vendored/requests/utils.py +916 -0
  175. webull/core/vendored/six.py +905 -0
  176. webull/data/__init__.py +3 -0
  177. webull/data/common/__init__.py +0 -0
  178. webull/data/common/category.py +26 -0
  179. webull/data/common/connect_ack.py +29 -0
  180. webull/data/common/direction.py +25 -0
  181. webull/data/common/exchange_code.py +33 -0
  182. webull/data/common/exercise_style.py +22 -0
  183. webull/data/common/expiration_cycle.py +26 -0
  184. webull/data/common/instrument_status.py +23 -0
  185. webull/data/common/option_type.py +20 -0
  186. webull/data/common/subscribe_type.py +22 -0
  187. webull/data/common/timespan.py +29 -0
  188. webull/data/data_client.py +35 -0
  189. webull/data/data_streaming_client.py +89 -0
  190. webull/data/internal/__init__.py +0 -0
  191. webull/data/internal/default_retry_policy.py +84 -0
  192. webull/data/internal/exceptions.py +60 -0
  193. webull/data/internal/quotes_client.py +314 -0
  194. webull/data/internal/quotes_decoder.py +40 -0
  195. webull/data/internal/quotes_payload_decoder.py +35 -0
  196. webull/data/internal/quotes_topic.py +36 -0
  197. webull/data/quotes/__init__.py +0 -0
  198. webull/data/quotes/instrument.py +33 -0
  199. webull/data/quotes/market_data.py +187 -0
  200. webull/data/quotes/market_streaming_data.py +66 -0
  201. webull/data/quotes/subscribe/__init__.py +0 -0
  202. webull/data/quotes/subscribe/ask_bid_result.py +49 -0
  203. webull/data/quotes/subscribe/basic_result.py +45 -0
  204. webull/data/quotes/subscribe/broker_result.py +33 -0
  205. webull/data/quotes/subscribe/message_pb2.py +37 -0
  206. webull/data/quotes/subscribe/order_result.py +30 -0
  207. webull/data/quotes/subscribe/payload_type.py +19 -0
  208. webull/data/quotes/subscribe/quote_decoder.py +28 -0
  209. webull/data/quotes/subscribe/quote_result.py +47 -0
  210. webull/data/quotes/subscribe/snapshot_decoder.py +30 -0
  211. webull/data/quotes/subscribe/snapshot_result.py +69 -0
  212. webull/data/quotes/subscribe/tick_decoder.py +29 -0
  213. webull/data/quotes/subscribe/tick_result.py +47 -0
  214. webull/data/request/__init__.py +0 -0
  215. webull/data/request/get_batch_historical_bars_request.py +43 -0
  216. webull/data/request/get_corp_action_request.py +47 -0
  217. webull/data/request/get_eod_bars_request.py +32 -0
  218. webull/data/request/get_historical_bars_request.py +43 -0
  219. webull/data/request/get_instruments_request.py +30 -0
  220. webull/data/request/get_quotes_request.py +35 -0
  221. webull/data/request/get_snapshot_request.py +38 -0
  222. webull/data/request/get_tick_request.py +37 -0
  223. webull/data/request/subscribe_request.py +43 -0
  224. webull/data/request/unsubscribe_request.py +42 -0
  225. webull/trade/__init__.py +2 -0
  226. webull/trade/common/__init__.py +0 -0
  227. webull/trade/common/account_type.py +22 -0
  228. webull/trade/common/category.py +29 -0
  229. webull/trade/common/combo_ticker_type.py +23 -0
  230. webull/trade/common/combo_type.py +31 -0
  231. webull/trade/common/currency.py +24 -0
  232. webull/trade/common/forbid_reason.py +27 -0
  233. webull/trade/common/instrument_type.py +27 -0
  234. webull/trade/common/markets.py +27 -0
  235. webull/trade/common/order_entrust_type.py +21 -0
  236. webull/trade/common/order_side.py +23 -0
  237. webull/trade/common/order_status.py +25 -0
  238. webull/trade/common/order_tif.py +24 -0
  239. webull/trade/common/order_type.py +30 -0
  240. webull/trade/common/trade_policy.py +22 -0
  241. webull/trade/common/trading_date_type.py +24 -0
  242. webull/trade/common/trailing_type.py +23 -0
  243. webull/trade/events/__init__.py +0 -0
  244. webull/trade/events/default_retry_policy.py +64 -0
  245. webull/trade/events/events_pb2.py +43 -0
  246. webull/trade/events/events_pb2_grpc.py +66 -0
  247. webull/trade/events/signature_composer.py +61 -0
  248. webull/trade/events/types.py +21 -0
  249. webull/trade/request/__init__.py +0 -0
  250. webull/trade/request/cancel_order_request.py +28 -0
  251. webull/trade/request/get_account_balance_request.py +28 -0
  252. webull/trade/request/get_account_positions_request.py +30 -0
  253. webull/trade/request/get_account_profile_request.py +26 -0
  254. webull/trade/request/get_app_subscriptions.py +28 -0
  255. webull/trade/request/get_open_orders_request.py +30 -0
  256. webull/trade/request/get_order_detail_request.py +27 -0
  257. webull/trade/request/get_today_orders_request.py +31 -0
  258. webull/trade/request/get_trade_calendar_request.py +30 -0
  259. webull/trade/request/get_trade_instrument_detail_request.py +24 -0
  260. webull/trade/request/get_trade_security_detail_request.py +42 -0
  261. webull/trade/request/get_tradeable_instruments_request.py +27 -0
  262. webull/trade/request/palce_order_request.py +91 -0
  263. webull/trade/request/place_order_request_v2.py +58 -0
  264. webull/trade/request/replace_order_request.py +73 -0
  265. webull/trade/request/replace_order_request_v2.py +38 -0
  266. webull/trade/request/v2/__init__.py +0 -0
  267. webull/trade/request/v2/cancel_option_request.py +28 -0
  268. webull/trade/request/v2/cancel_order_request.py +28 -0
  269. webull/trade/request/v2/get_account_balance_request.py +28 -0
  270. webull/trade/request/v2/get_account_list.py +23 -0
  271. webull/trade/request/v2/get_account_positions_request.py +24 -0
  272. webull/trade/request/v2/get_order_detail_request.py +26 -0
  273. webull/trade/request/v2/get_order_history_request.py +35 -0
  274. webull/trade/request/v2/palce_order_request.py +87 -0
  275. webull/trade/request/v2/place_option_request.py +64 -0
  276. webull/trade/request/v2/preview_option_request.py +28 -0
  277. webull/trade/request/v2/preview_order_request.py +59 -0
  278. webull/trade/request/v2/replace_option_request.py +28 -0
  279. webull/trade/request/v2/replace_order_request.py +57 -0
  280. webull/trade/trade/__init__.py +0 -0
  281. webull/trade/trade/account_info.py +83 -0
  282. webull/trade/trade/order_operation.py +246 -0
  283. webull/trade/trade/trade_calendar.py +37 -0
  284. webull/trade/trade/trade_instrument.py +72 -0
  285. webull/trade/trade/v2/__init__.py +0 -0
  286. webull/trade/trade/v2/account_info_v2.py +55 -0
  287. webull/trade/trade/v2/order_operation_v2.py +206 -0
  288. webull/trade/trade_client.py +43 -0
  289. webull/trade/trade_events_client.py +233 -0
  290. webull_openapi_python_sdk-1.0.0.dist-info/METADATA +28 -0
  291. webull_openapi_python_sdk-1.0.0.dist-info/RECORD +295 -0
  292. webull_openapi_python_sdk-1.0.0.dist-info/WHEEL +5 -0
  293. webull_openapi_python_sdk-1.0.0.dist-info/licenses/LICENSE +202 -0
  294. webull_openapi_python_sdk-1.0.0.dist-info/licenses/NOTICE +56 -0
  295. 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)