test_price_state.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import time
  2. from pusher.config import Config, LazerConfig, HermesConfig, PriceConfig, PriceSource, SingleSourceConfig, \
  3. PairSourceConfig, HyperliquidConfig
  4. from pusher.price_state import PriceState, PriceUpdate
  5. DEX = "pyth"
  6. SYMBOL = "BTC"
  7. def get_config():
  8. config: Config = Config.model_construct()
  9. config.stale_price_threshold_seconds = 5
  10. config.hyperliquid = HyperliquidConfig.model_construct()
  11. config.hyperliquid.asset_context_symbols = [SYMBOL]
  12. config.lazer = LazerConfig.model_construct()
  13. config.lazer.feed_ids = [1, 8]
  14. config.hermes = HermesConfig.model_construct()
  15. config.hermes.feed_ids = ["e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", "2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b"]
  16. config.price = PriceConfig(
  17. oracle={
  18. SYMBOL: [
  19. SingleSourceConfig(source_type="single", source=PriceSource(source_name="hl_oracle", source_id="BTC", exponent=None)),
  20. PairSourceConfig(source_type="pair",
  21. base_source=PriceSource(source_name="lazer", source_id=1, exponent=-8),
  22. quote_source=PriceSource(source_name="lazer", source_id=8, exponent=-8)),
  23. PairSourceConfig(source_type="pair",
  24. base_source=PriceSource(source_name="hermes", source_id="e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", exponent=-8),
  25. quote_source=PriceSource(source_name="hermes", source_id="2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b", exponent=-8))
  26. ]
  27. },
  28. mark={},
  29. external={}
  30. )
  31. return config
  32. def test_good_hl_price():
  33. """
  34. Pass through fresh HL oracle price.
  35. """
  36. config = get_config()
  37. price_state = PriceState(config)
  38. now = time.time()
  39. price_state.hl_oracle_state.put(SYMBOL, PriceUpdate("110000.0", now - price_state.stale_price_threshold_seconds / 2.0))
  40. oracle_px, _, _ = price_state.get_all_prices(DEX)
  41. assert oracle_px == {f"{DEX}:{SYMBOL}": "110000.0"}
  42. def test_fallback_lazer():
  43. """
  44. HL oracle price is stale, so fall back to fresh Lazer price.
  45. """
  46. config = get_config()
  47. price_state = PriceState(config)
  48. now = time.time()
  49. price_state.hl_oracle_state.put(SYMBOL, PriceUpdate("110000.0", now - price_state.stale_price_threshold_seconds - 1.0))
  50. price_state.lazer_state.put(1, PriceUpdate("11050000000000", now - price_state.stale_price_threshold_seconds / 2.0))
  51. price_state.lazer_state.put(8, PriceUpdate("99000000", now - price_state.stale_price_threshold_seconds / 2.0))
  52. oracle_px, _, _ = price_state.get_all_prices(DEX)
  53. assert oracle_px == {f"{DEX}:{SYMBOL}": "111616.16"}
  54. def test_fallback_hermes():
  55. """
  56. HL oracle price and Lazer prices are stale, so fall back to fresh Hermes price.
  57. """
  58. config = get_config()
  59. price_state = PriceState(config)
  60. now = time.time()
  61. price_state.hl_oracle_state.put(SYMBOL, PriceUpdate("110000.0", now - price_state.stale_price_threshold_seconds - 1.0))
  62. price_state.lazer_state.put(1, PriceUpdate("11050000000000", now - price_state.stale_price_threshold_seconds - 1.0))
  63. price_state.lazer_state.put(8, PriceUpdate("99000000", now - price_state.stale_price_threshold_seconds / 2.0))
  64. price_state.hermes_state.put("e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43",
  65. PriceUpdate("11100000000000", now - price_state.stale_price_threshold_seconds / 2.0))
  66. price_state.hermes_state.put("2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b",
  67. PriceUpdate("98000000", now - price_state.stale_price_threshold_seconds / 2.0))
  68. oracle_px, _, _ = price_state.get_all_prices(DEX)
  69. assert oracle_px == {f"{DEX}:{SYMBOL}": "113265.31"}
  70. def test_all_fail():
  71. """
  72. All prices are stale, so return nothing.
  73. """
  74. config = get_config()
  75. price_state = PriceState(config)
  76. now = time.time()
  77. price_state.hl_oracle_state.put(SYMBOL, PriceUpdate("110000.0", now - price_state.stale_price_threshold_seconds - 1.0))
  78. price_state.lazer_state.put(1, PriceUpdate("11050000000000", now - price_state.stale_price_threshold_seconds - 1.0))
  79. price_state.lazer_state.put(8, PriceUpdate("99000000", now - price_state.stale_price_threshold_seconds - 1.0))
  80. price_state.hermes_state.put("e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43",
  81. PriceUpdate("11100000000000", now - price_state.stale_price_threshold_seconds - 1.0))
  82. price_state.hermes_state.put("2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b",
  83. PriceUpdate("98000000", now - price_state.stale_price_threshold_seconds - 1.0))
  84. oracle_px, _, _ = price_state.get_all_prices(DEX)
  85. assert oracle_px == {}