Skip to content

Commit f742844

Browse files
committed
chore: bump 2.10.1
- fixes susn/usd feed
1 parent 24534dc commit f742844

9 files changed

Lines changed: 119 additions & 24 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"

infra/price-pusher/config/config.mainnet.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
- MRE7YIELD/USD
2828
- MRE7BTC/USD
2929
- UNIBTC/USD
30+
- USN/USD
31+
- SUSN/USD
3032
time_difference: 1200
3133
price_deviation: 0.025
3234

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"

pragma-sdk/pragma_sdk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"
Lines changed: 111 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,128 @@
1+
"""Fetcher for SUSN (Staked USN) price in USD."""
2+
13
from __future__ import annotations
24

3-
from typing import List, Optional
5+
import asyncio
6+
import time
7+
from typing import List, Optional, Sequence
8+
9+
from aiohttp import ClientSession
410

5-
from pragma_sdk.common.fetchers.fetchers.erc4626 import (
6-
ERC4626RateFetcher,
7-
build_erc4626_mapping,
11+
from pragma_sdk.common.exceptions import PublisherFetchError
12+
from pragma_sdk.common.fetchers.fetchers.evm_oracle import (
13+
EVMOracleFeedFetcher,
14+
FeedConfig,
815
)
16+
from pragma_sdk.common.types.entry import Entry, SpotEntry
917
from pragma_sdk.common.types.pair import Pair
1018

1119

12-
class sUSNFetcher(ERC4626RateFetcher):
13-
"""Fetches sUSN/USN exchange rate from the sUSN ERC4626 vault on Ethereum."""
20+
# ERC4626 convertToAssets(uint256 shares) selector
21+
CONVERT_TO_ASSETS_SELECTOR = "0x07a2d13a"
22+
# 1e18 in hex (padded to 32 bytes)
23+
ONE_SHARE_18_DECIMALS = (
24+
"0000000000000000000000000000000000000000000000000de0b6b3a7640000"
25+
)
26+
27+
# Contract addresses
28+
SUSN_VAULT_ADDRESS = "0xE24a3DC889621612422A64E6388927901608B91D"
29+
USN_ORACLE_ADDRESS = "0xBd154793659D1E6ea0C58754cEd6807059A421b0"
30+
USN_RATE_SELECTOR = "0x2c4e722e"
31+
32+
33+
class sUSNFetcher(EVMOracleFeedFetcher):
34+
"""
35+
Fetches SUSN/USD price by combining:
36+
1. SUSN/USN rate from ERC4626 vault (convertToAssets)
37+
2. USN/USD price from fixed rate oracle (rate)
38+
39+
Result: SUSN/USD = (SUSN/USN) * (USN/USD)
40+
"""
1441

1542
SOURCE = "SUSN_VAULT"
16-
feed_configs = build_erc4626_mapping(
17-
[
18-
(
19-
"sUSN/USN",
20-
"0xE24a3DC889621612422A64E6388927901608B91D",
21-
18, # decimals
22-
),
23-
]
24-
)
2543

2644
def __init__(
2745
self,
2846
pairs: List[Pair],
2947
publisher: str,
3048
api_key: Optional[str] = None,
3149
network: str = "mainnet",
50+
rpc_urls: Optional[Sequence[str]] = None,
3251
) -> None:
33-
super().__init__(pairs, publisher, api_key, network)
52+
super().__init__(pairs, publisher, api_key, network, rpc_urls)
53+
54+
async def fetch(
55+
self, session: ClientSession
56+
) -> List[Entry | PublisherFetchError | BaseException]:
57+
tasks = [
58+
asyncio.ensure_future(self.fetch_pair(pair, session)) for pair in self.pairs
59+
]
60+
return list(await asyncio.gather(*tasks, return_exceptions=True))
61+
62+
async def fetch_pair(
63+
self, pair: Pair, session: ClientSession
64+
) -> Entry | PublisherFetchError:
65+
"""Fetch SUSN/USD price."""
66+
67+
if str(pair) != "SUSN/USD":
68+
return PublisherFetchError(
69+
f"sUSNFetcher only supports SUSN/USD pair, got {pair}"
70+
)
71+
72+
# Fetch SUSN/USN rate from vault and USN/USD price in parallel
73+
susn_usn_task = self._read_vault_rate(session)
74+
usn_usd_task = self._read_usn_price(session)
75+
76+
results = await asyncio.gather(
77+
susn_usn_task, usn_usd_task, return_exceptions=True
78+
)
79+
80+
susn_usn_result = results[0]
81+
usn_usd_result = results[1]
82+
83+
if isinstance(susn_usn_result, PublisherFetchError):
84+
return susn_usn_result
85+
if isinstance(usn_usd_result, PublisherFetchError):
86+
return usn_usd_result
87+
88+
# Both are in 18 decimals, calculate SUSN/USD
89+
susn_usn_ratio = susn_usn_result / (10**18)
90+
usn_usd_price = usn_usd_result / (10**18)
91+
92+
susn_usd_price = susn_usn_ratio * usn_usd_price
93+
94+
# Convert to integer with pair decimals (8 for USD pairs)
95+
price_int = int(susn_usd_price * (10 ** pair.decimals()))
96+
timestamp = int(time.time())
97+
98+
return SpotEntry(
99+
pair_id=pair.id,
100+
price=price_int,
101+
volume=0,
102+
timestamp=timestamp,
103+
source=self.SOURCE,
104+
publisher=self.publisher,
105+
)
106+
107+
async def _read_vault_rate(
108+
self, session: ClientSession
109+
) -> float | PublisherFetchError:
110+
"""Call convertToAssets on the SUSN vault."""
111+
calldata = CONVERT_TO_ASSETS_SELECTOR + ONE_SHARE_18_DECIMALS
112+
vault_config = FeedConfig(
113+
contract_address=SUSN_VAULT_ADDRESS,
114+
decimals=18,
115+
selector=calldata,
116+
)
117+
return await self._read_feed_value(session, vault_config)
118+
119+
async def _read_usn_price(
120+
self, session: ClientSession
121+
) -> float | PublisherFetchError:
122+
"""Call rate() on the USN oracle - reuse parent's _read_feed_value."""
123+
usn_config = FeedConfig(
124+
contract_address=USN_ORACLE_ADDRESS,
125+
decimals=18,
126+
selector=USN_RATE_SELECTOR,
127+
)
128+
return await self._read_feed_value(session, usn_config)

pragma-sdk/pragma_sdk/supported_assets.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,10 +391,8 @@
391391
decimals: 18
392392
ticker: 'USN'
393393
ethereum_address: '0xda67b4284609d2d48e5d10cfac411572727dc1ed'
394-
coingecko_id: 'noon-usn'
395394

396395
- name: 'Staked Noon USD'
397396
decimals: 18
398397
ticker: 'SUSN'
399398
ethereum_address: '0xe24a3dc889621612422a64e6388927901608b91d'
400-
coingecko_id: 'staked-usn'
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.10.0"
1+
__version__ = "2.10.1"

0 commit comments

Comments
 (0)