hyperquant 1.45__tar.gz → 1.46__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {hyperquant-1.45 → hyperquant-1.46}/PKG-INFO +2 -1
  2. {hyperquant-1.45 → hyperquant-1.46}/pyproject.toml +2 -1
  3. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/auth.py +132 -2
  4. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/polymarket.py +106 -44
  5. {hyperquant-1.45 → hyperquant-1.46}/uv.lock +42 -2
  6. {hyperquant-1.45 → hyperquant-1.46}/.gitignore +0 -0
  7. {hyperquant-1.45 → hyperquant-1.46}/README.md +0 -0
  8. {hyperquant-1.45 → hyperquant-1.46}/requirements-dev.lock +0 -0
  9. {hyperquant-1.45 → hyperquant-1.46}/requirements.lock +0 -0
  10. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/__init__.py +0 -0
  11. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/bitget.py +0 -0
  12. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/bitmart.py +0 -0
  13. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/coinw.py +0 -0
  14. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/deepcoin.py +0 -0
  15. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/edgex.py +0 -0
  16. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/hyperliquid.py +0 -0
  17. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lbank.py +0 -0
  18. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
  19. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lib/hpstore.py +0 -0
  20. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lib/hyper_types.py +0 -0
  21. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lib/util.py +0 -0
  22. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/lighter.py +0 -0
  23. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/apexpro.py +0 -0
  24. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/bitget.py +0 -0
  25. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/bitmart.py +0 -0
  26. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/coinw.py +0 -0
  27. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/deepcoin.py +0 -0
  28. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/edgex.py +0 -0
  29. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/hyperliquid.py +0 -0
  30. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/lbank.py +0 -0
  31. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/lighter.py +0 -0
  32. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/ourbit.py +0 -0
  33. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/models/polymarket.py +0 -0
  34. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/ourbit.py +0 -0
  35. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/broker/ws.py +0 -0
  36. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/core.py +0 -0
  37. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/datavison/_util.py +0 -0
  38. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/datavison/binance.py +0 -0
  39. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/datavison/coinglass.py +0 -0
  40. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/datavison/okx.py +0 -0
  41. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/db.py +0 -0
  42. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/draw.py +0 -0
  43. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/logkit.py +0 -0
  44. {hyperquant-1.45 → hyperquant-1.46}/src/hyperquant/notikit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 1.45
3
+ Version: 1.46
4
4
  Summary: A minimal yet hyper-efficient backtesting framework for quantitative trading
5
5
  Project-URL: Homepage, https://github.com/yourusername/hyperquant
6
6
  Project-URL: Issues, https://github.com/yourusername/hyperquant/issues
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Topic :: Office/Business :: Financial :: Investment
15
15
  Requires-Python: >=3.11
16
16
  Requires-Dist: aiohttp>=3.13
17
+ Requires-Dist: coincurve>=21.0.0
17
18
  Requires-Dist: colorama>=0.4.6
18
19
  Requires-Dist: cryptography>=44.0.2
19
20
  Requires-Dist: duckdb>=1.2.2
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hyperquant"
3
- version = "1.45"
3
+ version = "1.46"
4
4
  description = "A minimal yet hyper-efficient backtesting framework for quantitative trading"
5
5
  authors = [
6
6
  { name = "MissinA", email = "1421329142@qq.com" }
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "web3>=7.14.0",
20
20
  "python-dotenv>=1.2.1",
21
21
  "py-clob-client>=0.28.0",
22
+ "coincurve>=21.0.0",
22
23
  ]
23
24
  readme = "README.md"
24
25
  requires-python = ">=3.11"
@@ -3,6 +3,7 @@ import hmac
3
3
  import urllib.parse
4
4
  import time
5
5
  import hashlib
6
+ from functools import lru_cache
6
7
  from typing import Any
7
8
  from aiohttp import ClientWebSocketResponse, FormData, JsonPayload
8
9
  from multidict import CIMultiDict
@@ -13,9 +14,9 @@ from urllib.parse import urlencode
13
14
  from datetime import datetime, timezone
14
15
  from eth_account import Account
15
16
  from eth_account.messages import encode_typed_data
17
+ from eth_utils import keccak, to_checksum_address
16
18
  import secrets
17
19
  from random import random
18
- from datetime import datetime, timezone
19
20
 
20
21
 
21
22
  POLY_ADDRESS = "POLY_ADDRESS"
@@ -27,6 +28,53 @@ POLY_PASSPHRASE = "POLY_PASSPHRASE"
27
28
  CLOB_AUTH_DOMAIN = {"name": "ClobAuthDomain", "version": "1"}
28
29
  CLOB_AUTH_MESSAGE = "This message attests that I control the given wallet"
29
30
 
31
+ _PM_DOMAIN_TYPEHASH = keccak(b"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
32
+ _PM_ORDER_TYPEHASH = keccak(
33
+ b"Order(uint256 salt,address maker,address signer,address taker,uint256 tokenId,uint256 makerAmount,uint256 takerAmount,uint256 expiration,uint256 nonce,uint256 feeRateBps,uint8 side,uint8 signatureType)"
34
+ )
35
+ _PM_DOMAIN_NAME_HASH = keccak(text="Polymarket CTF Exchange")
36
+ _PM_DOMAIN_VERSION_HASH = keccak(text="1")
37
+
38
+
39
+ def _int_to_32(val: int) -> bytes:
40
+ return int(val).to_bytes(32, "big", signed=False)
41
+
42
+
43
+ def _addr_to_32(addr: str) -> bytes:
44
+ # Normalize to checksum to match eth signing behavior
45
+ normalized = to_checksum_address(addr)
46
+ return int(normalized, 16).to_bytes(32, "big", signed=False)
47
+
48
+
49
+ @lru_cache(maxsize=32)
50
+ def _pm_domain_separator(chain_id: int, verifying_contract: str) -> bytes:
51
+ return keccak(
52
+ _PM_DOMAIN_TYPEHASH
53
+ + _PM_DOMAIN_NAME_HASH
54
+ + _PM_DOMAIN_VERSION_HASH
55
+ + _int_to_32(chain_id)
56
+ + _addr_to_32(verifying_contract),
57
+ )
58
+
59
+
60
+ def _pm_order_hash(message: dict[str, Any]) -> bytes:
61
+ """Manually hash the Polymarket Order struct for EIP-712."""
62
+ return keccak(
63
+ _PM_ORDER_TYPEHASH
64
+ + _int_to_32(message["salt"])
65
+ + _addr_to_32(message["maker"])
66
+ + _addr_to_32(message["signer"])
67
+ + _addr_to_32(message["taker"])
68
+ + _int_to_32(message["tokenId"])
69
+ + _int_to_32(message["makerAmount"])
70
+ + _int_to_32(message["takerAmount"])
71
+ + _int_to_32(message["expiration"])
72
+ + _int_to_32(message["nonce"])
73
+ + _int_to_32(message["feeRateBps"])
74
+ + _int_to_32(message["side"])
75
+ + _int_to_32(message["signatureType"]),
76
+ )
77
+
30
78
 
31
79
  def md5_hex(s: str) -> str:
32
80
  return hashlib.md5(s.encode("utf-8")).hexdigest()
@@ -484,7 +532,7 @@ class Auth:
484
532
  return args
485
533
 
486
534
  @staticmethod
487
- def polymarket(args: tuple[str, URL], kwargs: dict[str, Any]) -> tuple[str, URL]:
535
+ def polymarket_back(args: tuple[str, URL], kwargs: dict[str, Any]) -> tuple[str, URL]:
488
536
  method: str = args[0].upper()
489
537
  url: URL = args[1]
490
538
  headers: CIMultiDict = kwargs["headers"]
@@ -679,6 +727,11 @@ class Auth:
679
727
 
680
728
  return args
681
729
 
730
+ @staticmethod
731
+ def polymarket(args: tuple[str, URL], kwargs: dict[str, Any]) -> tuple[str, URL]:
732
+ """Alias kept for backward compatibility with pybotters host registration."""
733
+ return Auth.polymarket_back(args, kwargs)
734
+
682
735
  # --------------------------
683
736
  # Polymarket order signing
684
737
  # --------------------------
@@ -792,6 +845,83 @@ class Auth:
792
845
  }
793
846
  return out
794
847
 
848
+ @staticmethod
849
+ def sign_polymarket_order2(
850
+ *,
851
+ private_key: str,
852
+ chain_id: int,
853
+ exchange_address: str,
854
+ order: dict[str, Any],
855
+ ) -> dict[str, Any]:
856
+ """
857
+ Fast EIP-712 signer using coincurve + manual hashing.
858
+
859
+ Avoids heavy typed-data helpers by caching type/domain hashes and
860
+ signing the final digest directly.
861
+ """
862
+ try:
863
+ from coincurve import PrivateKey
864
+ except Exception as e: # pragma: no cover - optional dependency
865
+ raise RuntimeError("coincurve is required for sign_polymarket_order2") from e
866
+
867
+ try:
868
+ now_ts = datetime.now().replace(tzinfo=timezone.utc).timestamp()
869
+ generated_salt = round(now_ts * random())
870
+ except Exception:
871
+ generated_salt = int(time.time())
872
+
873
+ side = int(order.get("side", 0))
874
+ signature_type = int(order.get("signatureType", 1))
875
+ signer_addr = order.get("signer") or Account.from_key(private_key).address
876
+ taker_addr = order.get("taker") or "0x0000000000000000000000000000000000000000"
877
+
878
+ message = {
879
+ "salt": int(order.get("salt") or generated_salt),
880
+ "maker": order.get("maker"),
881
+ "signer": signer_addr,
882
+ "taker": taker_addr,
883
+ "tokenId": int(order["tokenId"]),
884
+ "makerAmount": int(order["makerAmount"]),
885
+ "takerAmount": int(order["takerAmount"]),
886
+ "expiration": int(order.get("expiration", 0)),
887
+ "nonce": int(order.get("nonce", 0)),
888
+ "feeRateBps": int(order.get("feeRateBps", 0)),
889
+ "side": side,
890
+ "signatureType": signature_type,
891
+ }
892
+
893
+ # Normalize addresses for hashing
894
+ exchange_addr = to_checksum_address(exchange_address)
895
+ message["maker"] = to_checksum_address(message["maker"])
896
+ message["signer"] = to_checksum_address(message["signer"])
897
+ message["taker"] = to_checksum_address(message["taker"])
898
+
899
+ domain_sep = _pm_domain_separator(int(chain_id), exchange_addr)
900
+ msg_hash = _pm_order_hash(message)
901
+ typed_hash = keccak(b"\x19\x01" + domain_sep + msg_hash)
902
+
903
+ pk_bytes = bytes.fromhex(private_key[2:] if private_key.startswith("0x") else private_key)
904
+ sig65 = PrivateKey(pk_bytes).sign_recoverable(typed_hash, hasher=None)
905
+ r, s, rec_id = sig65[:32], sig65[32:64], sig65[64]
906
+ v = rec_id + 27 # align with eth_account v
907
+ signature = "0x" + (r + s + bytes([v])).hex()
908
+
909
+ return {
910
+ "salt": int(message["salt"]),
911
+ "maker": message["maker"],
912
+ "signer": message["signer"],
913
+ "taker": message["taker"],
914
+ "tokenId": str(message["tokenId"]),
915
+ "makerAmount": str(message["makerAmount"]),
916
+ "takerAmount": str(message["takerAmount"]),
917
+ "expiration": str(message["expiration"]),
918
+ "nonce": str(message["nonce"]),
919
+ "feeRateBps": str(message["feeRateBps"]),
920
+ "side": "BUY" if side == 0 else "SELL",
921
+ "signatureType": int(signature_type),
922
+ "signature": signature,
923
+ }
924
+
795
925
  pybotters.auth.Hosts.items["futures.ourbit.com"] = pybotters.auth.Item(
796
926
  "ourbit", Auth.ourbit
797
927
  )
@@ -66,7 +66,7 @@ CONDITIONAL_TOKENS_ABI = [
66
66
  }
67
67
  ]
68
68
  DEFAULT_POLYGON_RPCS = (
69
- "https://polygon.llamarpc.com",
69
+ # "https://polygon.llamarpc.com",
70
70
  "https://polygon-rpc.com",
71
71
  "https://rpc.ankr.com/polygon",
72
72
  )
@@ -931,10 +931,23 @@ class Polymarket:
931
931
  raise RuntimeError("Polymarket private key not configured in apis.json")
932
932
  if not str(private_key).startswith("0x"):
933
933
  private_key = f"0x{private_key}"
934
+ try:
935
+ # Normalize cached session key to avoid repeated normalization work
936
+ if session and isinstance(apis, dict):
937
+ apis[API_NAME][0] = private_key
938
+ except Exception:
939
+ pass
940
+
941
+ cache_key = (private_key, self.funder)
942
+ cached = getattr(self, "_signing_ctx_cache", None)
943
+ if cached and cached.get("key") == cache_key:
944
+ return cached["ctx"]
934
945
 
935
946
  signer_addr = _A.from_key(private_key).address
936
947
  maker_addr = self.funder or signer_addr
937
- return private_key, maker_addr, signer_addr
948
+ ctx = (private_key, maker_addr, signer_addr)
949
+ self._signing_ctx_cache = {"key": cache_key, "ctx": ctx}
950
+ return ctx
938
951
 
939
952
  async def _build_signed_order(
940
953
  self,
@@ -983,24 +996,45 @@ class Polymarket:
983
996
  side_flag = 0 if side == "BUY" else 1
984
997
  sig_type = int(self.signature_type)
985
998
 
986
- return Auth.sign_polymarket_order(
987
- private_key=private_key,
988
- chain_id=self.chain_id,
989
- exchange_address=contract["exchange"],
990
- order={
991
- "maker": maker_addr,
992
- "signer": signer_addr,
993
- "taker": taker or ZERO_ADDRESS,
994
- "tokenId": str(token_id),
995
- "makerAmount": int(maker_amount),
996
- "takerAmount": int(taker_amount),
997
- "expiration": int(expiration or 0),
998
- "nonce": int(nonce or 0),
999
- "feeRateBps": int(fee_bps or 0),
1000
- "side": side_flag,
1001
- "signatureType": sig_type,
1002
- },
1003
- )
999
+ try:
1000
+ return Auth.sign_polymarket_order2(
1001
+ private_key=private_key,
1002
+ chain_id=self.chain_id,
1003
+ exchange_address=contract["exchange"],
1004
+ order={
1005
+ "maker": maker_addr,
1006
+ "signer": signer_addr,
1007
+ "taker": taker or ZERO_ADDRESS,
1008
+ "tokenId": str(token_id),
1009
+ "makerAmount": int(maker_amount),
1010
+ "takerAmount": int(taker_amount),
1011
+ "expiration": int(expiration or 0),
1012
+ "nonce": int(nonce or 0),
1013
+ "feeRateBps": int(fee_bps or 0),
1014
+ "side": side_flag,
1015
+ "signatureType": sig_type,
1016
+ },
1017
+ )
1018
+ except RuntimeError:
1019
+ # Fallback when coincurve is unavailable
1020
+ return Auth.sign_polymarket_order(
1021
+ private_key=private_key,
1022
+ chain_id=self.chain_id,
1023
+ exchange_address=contract["exchange"],
1024
+ order={
1025
+ "maker": maker_addr,
1026
+ "signer": signer_addr,
1027
+ "taker": taker or ZERO_ADDRESS,
1028
+ "tokenId": str(token_id),
1029
+ "makerAmount": int(maker_amount),
1030
+ "takerAmount": int(taker_amount),
1031
+ "expiration": int(expiration or 0),
1032
+ "nonce": int(nonce or 0),
1033
+ "feeRateBps": int(fee_bps or 0),
1034
+ "side": side_flag,
1035
+ "signatureType": sig_type,
1036
+ },
1037
+ )
1004
1038
 
1005
1039
  async def _build_signed_market_order(
1006
1040
  self,
@@ -1053,24 +1087,45 @@ class Polymarket:
1053
1087
  side_flag = 0 if side == "BUY" else 1
1054
1088
  sig_type = int(self.signature_type)
1055
1089
 
1056
- return Auth.sign_polymarket_order(
1057
- private_key=private_key,
1058
- chain_id=self.chain_id,
1059
- exchange_address=contract["exchange"],
1060
- order={
1061
- "maker": maker_addr,
1062
- "signer": signer_addr,
1063
- "taker": taker or ZERO_ADDRESS,
1064
- "tokenId": str(token_id),
1065
- "makerAmount": int(maker_amount),
1066
- "takerAmount": int(taker_amount),
1067
- "expiration": 0,
1068
- "nonce": int(nonce or 0),
1069
- "feeRateBps": int(fee_bps or 0),
1070
- "side": side_flag,
1071
- "signatureType": sig_type,
1072
- },
1073
- )
1090
+ try:
1091
+ return Auth.sign_polymarket_order2(
1092
+ private_key=private_key,
1093
+ chain_id=self.chain_id,
1094
+ exchange_address=contract["exchange"],
1095
+ order={
1096
+ "maker": maker_addr,
1097
+ "signer": signer_addr,
1098
+ "taker": taker or ZERO_ADDRESS,
1099
+ "tokenId": str(token_id),
1100
+ "makerAmount": int(maker_amount),
1101
+ "takerAmount": int(taker_amount),
1102
+ "expiration": 0,
1103
+ "nonce": int(nonce or 0),
1104
+ "feeRateBps": int(fee_bps or 0),
1105
+ "side": side_flag,
1106
+ "signatureType": sig_type,
1107
+ },
1108
+ )
1109
+ except RuntimeError:
1110
+ # Fallback when coincurve is unavailable
1111
+ return Auth.sign_polymarket_order(
1112
+ private_key=private_key,
1113
+ chain_id=self.chain_id,
1114
+ exchange_address=contract["exchange"],
1115
+ order={
1116
+ "maker": maker_addr,
1117
+ "signer": signer_addr,
1118
+ "taker": taker or ZERO_ADDRESS,
1119
+ "tokenId": str(token_id),
1120
+ "makerAmount": int(maker_amount),
1121
+ "takerAmount": int(taker_amount),
1122
+ "expiration": 0,
1123
+ "nonce": int(nonce or 0),
1124
+ "feeRateBps": int(fee_bps or 0),
1125
+ "side": side_flag,
1126
+ "signatureType": sig_type,
1127
+ },
1128
+ )
1074
1129
 
1075
1130
  async def _resolve_tick_size(self, token_id: str, tick_size: str | float | None) -> str:
1076
1131
  if tick_size is not None:
@@ -1107,9 +1162,16 @@ class Polymarket:
1107
1162
  api_secret = creds.get("api_secret")
1108
1163
  api_passphrase = creds.get("api_passphrase")
1109
1164
 
1110
- entry = getattr(session, "_apis", {}).get(API_NAME, [])
1111
- private_key = entry[0] if entry else None
1112
- addr = _A.from_key(private_key).address if private_key else None
1165
+ # Reuse signing context cache
1166
+ private_key, _, signer_addr = self._get_signing_context()
1167
+
1168
+ cache_key = (api_key, api_secret, api_passphrase, private_key)
1169
+ cached = getattr(self, "_rest_sign_cache", None)
1170
+ if cached and cached.get("key") == cache_key:
1171
+ secret_bytes = cached["secret"]
1172
+ else:
1173
+ secret_bytes = base64.urlsafe_b64decode(api_secret)
1174
+ self._rest_sign_cache = {"key": cache_key, "secret": secret_bytes}
1113
1175
 
1114
1176
  ts = int(time.time())
1115
1177
  request_path = path
@@ -1121,13 +1183,12 @@ class Polymarket:
1121
1183
  serialized = (
1122
1184
  str(payload_obj).replace("'", '"') if payload_obj is not None else ""
1123
1185
  )
1124
- secret_bytes = base64.urlsafe_b64decode(api_secret)
1125
1186
  msg = f"{ts}{method}{request_path}{serialized}"
1126
1187
  sig = hmac.new(secret_bytes, msg.encode("utf-8"), hashlib.sha256).digest()
1127
1188
  sign_b64 = base64.urlsafe_b64encode(sig).decode("utf-8")
1128
1189
 
1129
1190
  headers = {
1130
- "POLY_ADDRESS": addr,
1191
+ "POLY_ADDRESS": signer_addr,
1131
1192
  "POLY_SIGNATURE": sign_b64,
1132
1193
  "POLY_TIMESTAMP": str(ts),
1133
1194
  "POLY_API_KEY": api_key,
@@ -1594,7 +1655,8 @@ class Polymarket:
1594
1655
  try:
1595
1656
  acct = _A.from_key(private_key)
1596
1657
  sender = acct.address
1597
- nonce = w3.eth.get_transaction_count(sender)
1658
+ # 使用 pending 避免重复使用已在 mempool 的 nonce 触发 replacement underpriced
1659
+ nonce = w3.eth.get_transaction_count(sender, "pending")
1598
1660
  gas_price_chain = w3.eth.gas_price
1599
1661
  except Exception as exc:
1600
1662
  raise RuntimeError("获取 sender nonce/gas_price 失败") from exc
@@ -462,6 +462,44 @@ wheels = [
462
462
  { url = "https://files.pythonhosted.org/packages/40/40/f259e2bf986d39717427bc12baa8189cd43f9675e81cd3bcab639e593614/ckzg-2.1.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:df66d2be54d91f74aded4ceb71e7b1f789e2636a3015f438904a22ec9de750f1", size = 101018 },
463
463
  ]
464
464
 
465
+ [[package]]
466
+ name = "coincurve"
467
+ version = "21.0.0"
468
+ source = { registry = "https://pypi.org/simple" }
469
+ sdist = { url = "https://files.pythonhosted.org/packages/6f/a2/f2a38eb05b747ed3e54e1be33be339d4a14c1f5cc6a6e2b342b5e8160d51/coincurve-21.0.0.tar.gz", hash = "sha256:8b37ce4265a82bebf0e796e21a769e56fdbf8420411ccbe3fafee4ed75b6a6e5", size = 128986 }
470
+ wheels = [
471
+ { url = "https://files.pythonhosted.org/packages/19/5a/9aaa096d830b5d1386335759e73038a5352f8cd670efed55d242f92d0bce/coincurve-21.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:65ec42cab9c60d587fb6275c71f0ebc580625c377a894c4818fb2a2b583a184b", size = 1390936 },
472
+ { url = "https://files.pythonhosted.org/packages/8a/e4/37dd30ed171432e32c075a03237915c0e69a5a524a807f380d910b276a2a/coincurve-21.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5828cd08eab928db899238874d1aab12fa1236f30fe095a3b7e26a5fc81df0a3", size = 1384762 },
473
+ { url = "https://files.pythonhosted.org/packages/09/fd/78870f4babed4981feb9b97b3189aec0f01a1a24be8a1ac04807dc68aa0d/coincurve-21.0.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54de1cac75182de9f71ce41415faafcaf788303e21cbd0188064e268d61625e5", size = 1597025 },
474
+ { url = "https://files.pythonhosted.org/packages/9d/fb/b4850f8afc941655ef4c1204b50f9e21f841c6a64aa83a559277ca305cbd/coincurve-21.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07cda058d9394bea30d57a92fdc18ee3ca6b5bc8ef776a479a2ffec917105836", size = 1603987 },
475
+ { url = "https://files.pythonhosted.org/packages/9d/b7/df41dbcec3f70e383fa024949ce8956ff3b2a1b9eac330fba18c2115eece/coincurve-21.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9070804d7c71badfe4f0bf19b728cfe7c70c12e733938ead6b1db37920b745c0", size = 1604762 },
476
+ { url = "https://files.pythonhosted.org/packages/70/84/1b2437fc22590073eefb3da0418648b2d5b768951ef851822be8c164b998/coincurve-21.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:669ab5db393637824b226de058bb7ea0cb9a0236e1842d7b22f74d4a8a1f1ff1", size = 1637469 },
477
+ { url = "https://files.pythonhosted.org/packages/9c/4b/893763b3964b3044071a450fdada4c5024dc16f7644258a7bd06cf41e2ba/coincurve-21.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3bcd538af097b3914ec3cb654262e72e224f95f2e9c1eb7fbd75d843ae4e528e", size = 1601177 },
478
+ { url = "https://files.pythonhosted.org/packages/77/45/d2f42159cb461f5b070ff848244f1b83f3ea9ec3a3435368f9be33e4e276/coincurve-21.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45b6a5e6b5536e1f46f729829d99ce1f8f847308d339e8880fe7fa1646935c10", size = 1635597 },
479
+ { url = "https://files.pythonhosted.org/packages/9a/7c/528cff0aa17acd6c64b10c4bd8bb0adb6c96420be4e170916150537f36f6/coincurve-21.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:87597cf30dfc05fa74218810776efacf8816813ab9fa6ea1490f94e9f8b15e77", size = 1328626 },
480
+ { url = "https://files.pythonhosted.org/packages/cb/91/845b00da05b132e7bb3f3d1c4c301c195b39a9dc8f9962295ff340a27f18/coincurve-21.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:b992d1b1dac85d7f542d9acbcf245667438839484d7f2b032fd032256bcd778e", size = 1325365 },
481
+ { url = "https://files.pythonhosted.org/packages/f3/61/a2d9e109f99b6f5e65e653ac998b0944c5b82c568ac142fcbb381a4803be/coincurve-21.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f60ad56113f08e8c540bb89f4f35f44d434311433195ffff22893ccfa335070c", size = 1391948 },
482
+ { url = "https://files.pythonhosted.org/packages/24/5a/2da75ee00a722ef1fa068ada3bc34c564595ead86fef573434e2f0cb0a5c/coincurve-21.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1cb1cd19fb0be22e68ecb60ad950b41f18b9b02eebeffaac9391dc31f74f08f2", size = 1384958 },
483
+ { url = "https://files.pythonhosted.org/packages/dc/50/6bf0bf7e8a9a9dd419ecc1e479dcb9fbfe657029276ad703806a25a2bef2/coincurve-21.0.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05d7e255a697b3475d7ae7640d3bdef3d5bc98ce9ce08dd387f780696606c33b", size = 1606576 },
484
+ { url = "https://files.pythonhosted.org/packages/bd/ab/9e89908fdd09ad522938085587aaa821b022f4def16c286c5580cfc85811/coincurve-21.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a366c314df7217e3357bb8c7d2cda540b0bce180705f7a0ce2d1d9e28f62ad4", size = 1613642 },
485
+ { url = "https://files.pythonhosted.org/packages/b7/75/050b6fd08978de85a7b480f0f220ab6a30967c0910119f3096a8dd40befc/coincurve-21.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b04778b75339c6e46deb9ae3bcfc2250fbe48d1324153e4310fc4996e135715", size = 1616974 },
486
+ { url = "https://files.pythonhosted.org/packages/d7/62/2740ba0cafebf45708633635fecadcbe582d7a3ed1ce8b4637921feceaf8/coincurve-21.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8efcbdcd50cc219989a2662e6c6552f455efc000a15dd6ab3ebf4f9b187f41a3", size = 1644133 },
487
+ { url = "https://files.pythonhosted.org/packages/94/14/1f27c3048c4084fa85ef65f42a4ca631f2b184336e6d9446fecec20e0a7f/coincurve-21.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6df44b4e3b7acdc1453ade52a52e3f8a5b53ecdd5a06bd200f1ec4b4e250f7d9", size = 1619918 },
488
+ { url = "https://files.pythonhosted.org/packages/ca/22/7ec3ec4c8e7764daa25767d6674cb5741ea2d9b39ff758e9918d22a4b49b/coincurve-21.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bcc0831f07cb75b91c35c13b1362e7b9dc76c376b27d01ff577bec52005e22a8", size = 1645797 },
489
+ { url = "https://files.pythonhosted.org/packages/fb/60/87982b7499943ab12605df7b14f6001fff331aca0881b260682461e2309d/coincurve-21.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:5dd7b66b83b143f3ad3861a68fc0279167a0bae44fe3931547400b7a200e90b1", size = 1329255 },
490
+ { url = "https://files.pythonhosted.org/packages/62/c0/65b60b371579570931daca8a3f67debfc1482908b8ed03432297274a27da/coincurve-21.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:78dbe439e8cb22389956a4f2f2312813b4bd0531a0b691d4f8e868c7b366555d", size = 1325973 },
491
+ { url = "https://files.pythonhosted.org/packages/b3/40/cce55adaec37a588eb24b67da8eb68926546458e12ed2c4c2a21deb93d4c/coincurve-21.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9df5ceb5de603b9caf270629996710cf5ed1d43346887bc3895a11258644b65b", size = 1391762 },
492
+ { url = "https://files.pythonhosted.org/packages/ca/7a/628a30281d246ce98aea56592e0c8e79b03a93ee8b85d688db3388130c2d/coincurve-21.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:154467858d23c48f9e5ab380433bc2625027b50617400e2984cc16f5799ab601", size = 1384921 },
493
+ { url = "https://files.pythonhosted.org/packages/61/cc/719c5da31e6ba07e438abcf962f7a365eb69a06a0621ca4f2a484f344e09/coincurve-21.0.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f57f07c44d14d939bed289cdeaba4acb986bba9f729a796b6a341eab1661eedc", size = 1606559 },
494
+ { url = "https://files.pythonhosted.org/packages/b2/ee/dd14237013d732e7fc3248c0c33a1d36b88b5378dfa3e624a50a23fb6f19/coincurve-21.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fb03e3a388a93d31ed56a442bdec7983ea404490e21e12af76fb1dbf097082a", size = 1613684 },
495
+ { url = "https://files.pythonhosted.org/packages/f0/05/eaa7f36a03376ced1c19e0cb563341cc83fe48f5734b2effe8f16d0ee0ab/coincurve-21.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09ba4fd9d26b00b06645fcd768c5ad44832a1fa847ebe8fb44970d3204c3cb7", size = 1617001 },
496
+ { url = "https://files.pythonhosted.org/packages/39/32/fc75f1dd914ac95eb2704425c7ca1a9f509f982e15d05e0ca895b9e6ea9c/coincurve-21.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1a1e7ee73bc1b3bcf14c7b0d1f44e6485785d3b53ef7b16173c36d3cefa57f93", size = 1643924 },
497
+ { url = "https://files.pythonhosted.org/packages/1a/4b/8c6e65b5755e26fc02077803879747615c1c327047328d1784bccb4ff4c3/coincurve-21.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ad05952b6edc593a874df61f1bc79db99d716ec48ba4302d699e14a419fe6f51", size = 1619964 },
498
+ { url = "https://files.pythonhosted.org/packages/64/bc/d0a743305ff9fa26e72b4c77b534d5958ec8030b3772555a7172a0c134e5/coincurve-21.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4d2bf350ced38b73db9efa1ff8fd16a67a1cb35abb2dda50d89661b531f03fd3", size = 1645526 },
499
+ { url = "https://files.pythonhosted.org/packages/9d/44/ab082e2dc8c9a45774f1bb9961f58b43c0882b866f5c469ead932d45a35d/coincurve-21.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:54d9500c56d5499375e579c3917472ffcf804c3584dd79052a79974280985c74", size = 1329285 },
500
+ { url = "https://files.pythonhosted.org/packages/f3/94/407f6fc811310f15b1fc7255f436f6a9040854213beeb10093f56b5b7fd3/coincurve-21.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:773917f075ec4b94a7a742637d303a3a082616a115c36568eb6c873a8d950d18", size = 1326027 },
501
+ ]
502
+
465
503
  [[package]]
466
504
  name = "colorama"
467
505
  version = "0.4.6"
@@ -945,10 +983,11 @@ wheels = [
945
983
 
946
984
  [[package]]
947
985
  name = "hyperquant"
948
- version = "1.44"
986
+ version = "1.45"
949
987
  source = { editable = "." }
950
988
  dependencies = [
951
989
  { name = "aiohttp" },
990
+ { name = "coincurve" },
952
991
  { name = "colorama" },
953
992
  { name = "cryptography" },
954
993
  { name = "duckdb" },
@@ -970,7 +1009,8 @@ dev = [
970
1009
 
971
1010
  [package.metadata]
972
1011
  requires-dist = [
973
- { name = "aiohttp", specifier = ">=3.10.4" },
1012
+ { name = "aiohttp", specifier = ">=3.13" },
1013
+ { name = "coincurve", specifier = ">=21.0.0" },
974
1014
  { name = "colorama", specifier = ">=0.4.6" },
975
1015
  { name = "cryptography", specifier = ">=44.0.2" },
976
1016
  { name = "duckdb", specifier = ">=1.2.2" },
File without changes
File without changes
File without changes