Skip to content

Commit 8f7ade6

Browse files
author
Jeff Schroeder
committed
Initial squashed commit
0 parents  commit 8f7ade6

File tree

11 files changed

+1719
-0
lines changed

11 files changed

+1719
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Pyth Client in Python
2+
=====================
3+
4+
A Python library to retrieve data from Pyth account structures off the Solana blockchain.

examples/dump.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
import asyncio
5+
import os
6+
import signal
7+
import sys
8+
from typing import List, Any
9+
10+
from loguru import logger
11+
12+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13+
from pythclient.pythclient import PythClient, V2_PROGRAM_KEY, V2_FIRST_MAPPING_ACCOUNT_KEY
14+
from pythclient.ratelimit import RateLimit
15+
from pythclient.pythaccounts import PythPriceAccount
16+
17+
logger.enable("pythclient")
18+
19+
RateLimit.configure_default_ratelimit(overall_cps=9, method_cps=3, connection_cps=3)
20+
21+
to_exit = False
22+
23+
24+
def set_to_exit(sig: Any, frame: Any):
25+
global to_exit
26+
to_exit = True
27+
28+
29+
signal.signal(signal.SIGINT, set_to_exit)
30+
31+
32+
async def main():
33+
global to_exit
34+
use_program = len(sys.argv) >= 2 and sys.argv[1] == "program"
35+
async with PythClient(first_mapping_account_key=V2_FIRST_MAPPING_ACCOUNT_KEY, program_key=V2_PROGRAM_KEY if use_program else None) as c:
36+
await c.refresh_all_prices()
37+
products = await c.get_products()
38+
all_prices: List[PythPriceAccount] = []
39+
for p in products:
40+
print(p.key, p.attrs)
41+
prices = await p.get_prices()
42+
for _, pr in prices.items():
43+
all_prices.append(pr)
44+
print(
45+
pr.key,
46+
pr.product_account_key,
47+
pr.price_type,
48+
pr.aggregate_price,
49+
"p/m",
50+
pr.aggregate_price_confidence_interval,
51+
)
52+
53+
ws = c.create_watch_session()
54+
await ws.connect()
55+
if use_program:
56+
print("Subscribing to program account")
57+
await ws.program_subscribe(V2_PROGRAM_KEY, await c.get_all_accounts())
58+
else:
59+
print("Subscribing to all prices")
60+
for account in all_prices:
61+
await ws.subscribe(account)
62+
print("Subscribed!")
63+
64+
while True:
65+
if to_exit:
66+
break
67+
update_task = asyncio.create_task(ws.next_update())
68+
while True:
69+
if to_exit:
70+
update_task.cancel()
71+
break
72+
done, _ = await asyncio.wait({update_task}, timeout=1)
73+
if update_task in done:
74+
pr = update_task.result()
75+
if isinstance(pr, PythPriceAccount):
76+
assert pr.product
77+
print(
78+
pr.product.symbol,
79+
pr.price_type,
80+
pr.aggregate_price,
81+
"p/m",
82+
pr.aggregate_price_confidence_interval,
83+
)
84+
break
85+
else:
86+
print("WTF!: ", price)
87+
88+
print("Unsubscribing...")
89+
if use_program:
90+
await ws.program_unsubscribe(V2_PROGRAM_KEY)
91+
else:
92+
for account in all_prices:
93+
await ws.unsubscribe(account)
94+
await ws.disconnect()
95+
print("Disconnected")
96+
97+
98+
asyncio.run(main())

pythclient/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from loguru import logger as _logger
2+
# as per Loguru documentation's recommendation for libraries
3+
_logger.disable(__name__)

pythclient/config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Library-wide settings.
3+
"""
4+
5+
backoff_max_value = 16
6+
backoff_max_tries = 8
7+
8+
# The following getter functions are passed to the backoff decorators
9+
10+
def get_backoff_max_value():
11+
return backoff_max_value
12+
13+
def get_backoff_max_tries():
14+
return backoff_max_tries

pythclient/exceptions.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class RateLimitedException(Exception):
2+
"""
3+
Raised when the client is rate-limited.
4+
"""
5+
pass
6+
7+
class SolanaException(Exception):
8+
"""
9+
Raised when the Solana API returns an error.
10+
"""
11+
pass
12+
13+
class WebSocketClosedException(Exception):
14+
"""
15+
Raised when the WebSocket is closed while we are waiting for an update.
16+
"""
17+
18+
class NotLoadedException(Exception):
19+
"""
20+
Raised when the child accounts are not yet loaded.
21+
"""
22+
23+
class MissingAccountException(Exception):
24+
"""
25+
Raised when an account is needed but is missing.
26+
"""

0 commit comments

Comments
 (0)