Skip to content

Commit

Permalink
fix: starkex x10 full support (#229)
Browse files Browse the repository at this point in the history
* Update supported_assets.yaml

* Update config.offchain.dev.yaml

* fix: assets list

* fix: timeout fetcher client

* fix: binance future fetcher in //

* fix: okx future fetcher in //

* debug log
  • Loading branch information
EvolveArt authored Nov 26, 2024
1 parent fec6ee3 commit 7e63d74
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 114 deletions.
29 changes: 28 additions & 1 deletion infra/price-pusher/config/config.offchain.dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@
- 1000SATS/USD
- ONDO/USD
- STRK/USD
- BCH/USD
- WBTC/USD
- WSTETH/USD
- STETH/USD
- NSTR/USD
- LORDS/USD
- ZEND/USD
- EKUBO/USD
- SHIB/USD
- CRV/USD
- BROTHER/USDPLUS
- POPCAT/USD
- SEI/USD
- FTM/USD
- GOAT/USD
- MOODENG/USD
- BONK/USD
- LUSD/USD

future:
- BTC/USDT
Expand Down Expand Up @@ -62,7 +80,16 @@
- NEAR/USDT
- 1000SATS/USDT
- ONDO/USDT
- STRK/USD
- STRK/USDT
- BCH/USDT
- SHIB/USDT
- CRV/USDT
- POPCAT/USDT
- SEI/USDT
- FTM/USDT
- GOAT/USDT
- MOODENG/USDT
- BONK/USDT

time_difference: 1
price_deviation: 0.025
59 changes: 50 additions & 9 deletions pragma-sdk/pragma_sdk/common/fetchers/fetcher_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import time
from typing import List
import logging

Expand Down Expand Up @@ -47,7 +48,7 @@ class FetcherClient:
.. code-block:: python
await fc.fetch(timeout_duration=20) # Denominated in seconds (default=10)
await fc.fetch(timeout_duration=20) # Denominated in seconds
"""

__fetchers: List[FetcherInterfaceT] = []
Expand Down Expand Up @@ -90,18 +91,58 @@ async def fetch(
:param timeout_duration: Timeout duration for each fetcher
:return: List of fetched data
"""
start_time = time.time()
tasks = []

# Create a timeout for both connection and individual operations
timeout = aiohttp.ClientTimeout(
total=timeout_duration
) # 20 seconds per request
async with aiohttp.ClientSession(timeout=timeout) as session:
for fetcher in self.fetchers:
data = fetcher.fetch(session)
tasks.append(data)
total=None, # No timeout for the entire session
connect=timeout_duration,
sock_read=timeout_duration,
sock_connect=timeout_duration,
)

async with aiohttp.ClientSession(
timeout=timeout, connector=aiohttp.TCPConnector(limit=0)
) as session:
tasks = []
for idx, fetcher in enumerate(self.fetchers):

async def wrapped_fetch(f, i):
try:
# Add timeout to the individual fetch operation
async with asyncio.timeout(timeout_duration):
fetch_start = time.time()
result = await f.fetch(session)
fetch_time = time.time() - fetch_start
logger.debug(
f"Fetcher {i} ({f.__class__.__name__}) completed in {fetch_time:.2f}s"
)
return result
except asyncio.TimeoutError:
logger.error(
f"Fetcher {i} ({f.__class__.__name__}) timed out after {timeout_duration}s"
)
return PublisherFetchError(f"Timeout after {timeout_duration}s")
except Exception as e:
logger.error(
f"Fetcher {i} ({f.__class__.__name__}) failed: {str(e)}"
)
raise

tasks.append(wrapped_fetch(fetcher, idx))

gather_start = time.time()
result = await asyncio.gather(*tasks, return_exceptions=return_exceptions)
result = [val for subl in result for val in subl] # type: ignore[misc,union-attr]
logger.info(f"Gathered all results in {time.time() - gather_start:.2f}s")

result = [r if isinstance(r, list) else [r] for r in result]
result = [val for subl in result for val in subl] # flatten

if filter_exceptions:
result = [
subl for subl in result if not isinstance(subl, BaseException)
]
return result # type: ignore[union-attr, misc, return-value]
return result

await asyncio.sleep(0) # Graceful shutdown
33 changes: 14 additions & 19 deletions pragma-sdk/pragma_sdk/common/fetchers/future_fetchers/binance.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import json
import time

Expand All @@ -21,7 +22,7 @@ class BinanceFutureFetcher(FetcherInterfaceT):

async def fetch_pair( # type: ignore[override]
self, pair: Pair, session: ClientSession
) -> List[FutureEntry] | PublisherFetchError:
) -> FutureEntry | PublisherFetchError:
url = self.format_url(pair)
async with session.get(url) as resp:
if resp.status == 404:
Expand All @@ -42,14 +43,10 @@ async def fetch_pair( # type: ignore[override]
async def fetch(
self, session: ClientSession
) -> List[Entry | PublisherFetchError | BaseException]:
entries: List[Entry | PublisherFetchError | BaseException] = []
entries = []
for pair in self.pairs:
entries_or_error = await self.fetch_pair(pair, session)
if isinstance(entries_or_error, PublisherFetchError):
entries.append(entries_or_error)
else:
entries.extend(entries_or_error)
return entries
entries.append(asyncio.ensure_future(self.fetch_pair(pair, session)))
return list(await asyncio.gather(*entries, return_exceptions=True))

def format_url(self, pair: Pair) -> str:
return (
Expand Down Expand Up @@ -79,14 +76,12 @@ def _construct(
else:
expiry_timestamp = int(0)

return [
FutureEntry(
pair_id=pair.id,
price=price_int,
volume=int(volume),
timestamp=int(time.time()),
source=self.SOURCE,
publisher=self.publisher,
expiry_timestamp=expiry_timestamp * 1000,
)
]
return FutureEntry(
pair_id=pair.id,
price=price_int,
volume=int(volume),
timestamp=int(time.time()),
source=self.SOURCE,
publisher=self.publisher,
expiry_timestamp=expiry_timestamp * 1000,
)
20 changes: 6 additions & 14 deletions pragma-sdk/pragma_sdk/common/fetchers/future_fetchers/okx.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import json
import time

Expand Down Expand Up @@ -39,9 +40,8 @@ def format_expiry_timestamp_url(self, instrument_id: str) -> str:

async def fetch_pair( # type: ignore[override]
self, pair: Pair, session: ClientSession
) -> PublisherFetchError | List[Entry]:
) -> PublisherFetchError | FutureEntry:
url = self.format_url(pair)
future_entries: List[Entry] = []
async with session.get(url) as resp:
if resp.status == 404:
return PublisherFetchError(f"No data found for {pair} from OKX")
Expand All @@ -58,23 +58,15 @@ async def fetch_pair( # type: ignore[override]
or result["msg"] == "Instrument ID does not exist"
):
return PublisherFetchError(f"No data found for {pair} from OKX")
result_len = len(result["data"])
if result_len >= 1:
for i in range(0, result_len):
future_entries.append(self._construct(pair, result["data"][i], 0))
return future_entries
return self._construct(pair, result["data"][0], 0)

async def fetch(
self, session: ClientSession
) -> List[Entry | PublisherFetchError | BaseException]:
entries: List[Entry | PublisherFetchError | BaseException] = []
entries = []
for pair in self.pairs:
future_entries = await self.fetch_pair(pair, session)
if isinstance(future_entries, list):
entries.extend(future_entries)
else:
entries.append(future_entries)
return entries
entries.append(asyncio.ensure_future(self.fetch_pair(pair, session)))
return list(await asyncio.gather(*entries, return_exceptions=True))

def format_url(self, pair: Pair) -> str:
url = f"{self.BASE_URL}?instType=SWAP&uly={pair.base_currency.id}-{pair.quote_currency.id}"
Expand Down
2 changes: 1 addition & 1 deletion pragma-sdk/pragma_sdk/offchain/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ async def _create_entries(
"signature": [str(s) for s in sig],
"entries": Entry.offchain_serialize_entries(entries),
}
print(data)
# print(data)

async with aiohttp.ClientSession() as session:
start = time.time()
Expand Down
92 changes: 80 additions & 12 deletions pragma-sdk/pragma_sdk/supported_assets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
starknet_address: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7'

- name: 'Solana'
decimals: 18
decimals: 9
ticker: 'SOL'
coingecko_id: 'solana'

Expand Down Expand Up @@ -71,6 +71,11 @@
starknet_address: '0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac'
ethereum_address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'

- name: 'Bitcoin Cash'
decimals: 8
ticker: 'BCH'
coingecko_id: 'bitcoin-cash'

- name: 'Wrapped Lido Staked Ether'
decimals: 18
ticker: 'WSTETH'
Expand Down Expand Up @@ -134,8 +139,13 @@
ticker: 'MATIC'
coingecko_id: 'matic-network'

- name: 'Worldcoin'
decimals: 18
ticker: 'WLD'
coingecko_id: 'worldcoin-wld'

- name: 'Ripple'
decimals: 6
decimals: 15
ticker: 'XRP'
coingecko_id: 'ripple'

Expand All @@ -145,7 +155,7 @@
coingecko_id: 'dogecoin'

- name: '1000 Pepe'
decimals: 18
decimals: 15
ticker: '1000PEPE'
coingecko_id: '1000-pepe'

Expand All @@ -164,10 +174,10 @@
ticker: 'SUI'
coingecko_id: 'sui'

- name: 'Wrapped IchiFarm'
decimals: 18
- name: 'dogwifhat'
decimals: 6
ticker: 'WIF'
coingecko_id: 'ichifarm-wrapped'
coingecko_id: 'dogwifcoin'

- name: 'Celestia'
decimals: 18
Expand Down Expand Up @@ -205,15 +215,20 @@
ticker: 'OP'
coingecko_id: 'optimism'

- name: 'Ordinal Dogecoin'
decimals: 18
- name: 'Aptos'
decimals: 8
ticker: 'APT'
coingecko_id: 'aptos'

- name: 'Ordinals'
decimals: 8
ticker: 'ORDI'
coingecko_id: 'ordinals-dogecoin'
coingecko_id: 'ordinals'

- name: 'Japan Token'
- name: 'Filecoin'
decimals: 18
ticker: 'JTO'
coingecko_id: 'japan-token'
ticker: 'FIL'
coingecko_id: 'filecoin'

- name: 'Jupiter'
decimals: 9
Expand All @@ -231,6 +246,24 @@
coingecko_id: 'okb'
ethereum_address: '0x75231f58b43240c9718dd58b4967c5114342a86c'

- name: 'ApeCoin'
decimals: 18
ticker: 'APE'
coingecko_id: 'apecoin'
ethereum_address: '0x4d224452801aced8b2f0aebe155379bb5d594381'

- name: 'Shiba Inu'
decimals: 18
ticker: 'SHIB'
coingecko_id: 'shiba-inu'
ethereum_address: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce'

- name: 'Curve DAO'
decimals: 18
ticker: 'CRV'
coingecko_id: 'curve-dao-token'
ethereum_address: '0xd533a949740bb3306d119cc777fa900ba034cd52'

- name: 'Cosmos'
decimals: 6
ticker: 'ATOM'
Expand All @@ -251,3 +284,38 @@
ticker: 'BROTHER'
coingecko_id: 'starknet-brother'
starknet_address: '0x03b405a98c9e795d427fe82cdeeeed803f221b52471e3a757574a2b4180793ee'

- name: 'Cardano'
decimals: 6
ticker: 'ADA'
coingecko_id: 'cardano'

- name: 'Popcat'
decimals: 9
ticker: 'POPCAT'
coingecko_id: 'popcat'

- name: 'Sei'
decimals: 6
ticker: 'SEI'
coingecko_id: 'sei-network'

- name: 'Fantom'
decimals: 18
ticker: 'FTM'
coingecko_id: 'fantom'

- name: 'Goatseus Maximus'
decimals: 6
ticker: 'GOAT'
coingecko_id: 'goatseus-maximus'

- name: 'Moo Deng'
decimals: 6
ticker: 'MOODENG'
coingecko_id: 'moo-deng'

- name: 'Bonk'
decimals: 5
ticker: 'BONK'
coingecko_id: 'bonk'
Loading

0 comments on commit 7e63d74

Please sign in to comment.