Skip to content

Commit

Permalink
Merge 3aa70c4 into 8234856
Browse files Browse the repository at this point in the history
  • Loading branch information
Uxio0 committed Sep 20, 2022
2 parents 8234856 + 3aa70c4 commit ad9c6c7
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 13 deletions.
2 changes: 0 additions & 2 deletions gnosis/eth/oracles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
UnderlyingToken,
UniswapOracle,
UniswapV2Oracle,
UsdPricePoolOracle,
YearnOracle,
ZerionComposedOracle,
)
Expand All @@ -45,7 +44,6 @@
"UniswapOracle",
"UniswapV2Oracle",
"UniswapV3Oracle",
"UsdPricePoolOracle",
"YearnOracle",
"ZerionComposedOracle",
]
11 changes: 11 additions & 0 deletions gnosis/eth/oracles/kyber.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ def __init__(
self.w3 = ethereum_client.w3
self._kyber_network_proxy_address = kyber_network_proxy_address

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() in cls.ADDRESSES

@cached_property
def kyber_network_proxy_address(self):
if self._kyber_network_proxy_address:
Expand Down
118 changes: 107 additions & 11 deletions gnosis/eth/oracles/oracles.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,45 @@ class UnderlyingToken:
quantity: int


class PriceOracle(ABC):
class BaseOracle(ABC):
@classmethod
@abstractmethod
def get_price(self, *args) -> float:
pass
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
raise NotImplementedError


class PricePoolOracle(ABC):
class PriceOracle(BaseOracle):
@abstractmethod
def get_pool_token_price(self, pool_token_address: ChecksumAddress) -> float:
pass
def get_price(self, *args) -> float:
raise NotImplementedError


class UsdPricePoolOracle(ABC):
class PricePoolOracle(BaseOracle):
@abstractmethod
def get_pool_usd_token_price(self, pool_token_address: ChecksumAddress) -> float:
pass
def get_pool_token_price(self, pool_token_address: ChecksumAddress) -> float:
raise NotImplementedError


class ComposedPriceOracle(ABC):
class ComposedPriceOracle(BaseOracle):
@abstractmethod
def get_underlying_tokens(self, *args) -> List[Tuple[UnderlyingToken]]:
pass
raise NotImplementedError


class UniswapOracle(PriceOracle):
"""
Uniswap V1 Oracle
https://docs.uniswap.org/protocol/V1/guides/connect-to-uniswap
"""

ADDRESSES = {
EthereumNetwork.MAINNET: "0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95",
EthereumNetwork.RINKEBY: "0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36",
Expand All @@ -88,6 +102,17 @@ def __init__(
self.w3 = ethereum_client.w3
self._uniswap_factory_address = uniswap_factory_address

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() in cls.ADDRESSES

@cached_property
def uniswap_factory_address(self):
if self._uniswap_factory_address:
Expand Down Expand Up @@ -231,6 +256,22 @@ def __init__(
ethereum_client.w3, self.router_address
)

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.is_contract(
cls.ROUTER_ADDRESSES.get(
ethereum_client.get_network(),
cls.ROUTER_ADDRESSES[EthereumNetwork.MAINNET],
)
)

@cached_property
def factory(self):
return get_uniswap_v2_factory_contract(
Expand Down Expand Up @@ -436,6 +477,17 @@ def __init__(self, ethereum_client: EthereumClient, price_oracle: PriceOracle):
self.w3 = ethereum_client.w3
self.price_oracle = price_oracle

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() == EthereumNetwork.MAINNET

def get_price(self, token_address: str) -> float:
if (
token_address == "0x4da27a545c0c5B758a6BA100e3a049001de870f5"
Expand Down Expand Up @@ -467,6 +519,17 @@ def __init__(self, ethereum_client: EthereumClient, price_oracle: PriceOracle):
self.w3 = ethereum_client.w3
self.price_oracle = price_oracle

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() == EthereumNetwork.MAINNET

def get_price(self, token_address: str) -> float:
try:
underlying_token = (
Expand Down Expand Up @@ -504,6 +567,17 @@ def __init__(
self.ethereum_client = ethereum_client
self.w3 = ethereum_client.w3

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() == EthereumNetwork.MAINNET

@cached_property
def zerion_adapter_contract(self) -> Optional[Contract]:
"""
Expand Down Expand Up @@ -626,6 +700,17 @@ def __init__(
ethereum_client, iearn_token_adapter
)

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() == EthereumNetwork.MAINNET

def get_underlying_tokens(
self, token_address: ChecksumAddress
) -> List[Tuple[float, ChecksumAddress]]:
Expand Down Expand Up @@ -661,6 +746,17 @@ def __init__(self, ethereum_client: EthereumClient, price_oracle: PriceOracle):
self.w3 = ethereum_client.w3
self.price_oracle = price_oracle

@classmethod
def is_available(
cls,
ethereum_client: EthereumClient,
) -> bool:
"""
:param ethereum_client:
:return: `True` if Oracle is available for the EthereumClient provided, `False` otherwise
"""
return ethereum_client.get_network() == EthereumNetwork.MAINNET

def get_pool_token_price(self, pool_token_address: ChecksumAddress) -> float:
"""
Estimate balancer pool token price based on its components
Expand Down
2 changes: 2 additions & 0 deletions gnosis/eth/tests/oracles/test_kyber.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class TestKyberOracle(EthereumTestCaseMixin, TestCase):
def test_kyber_oracle(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(KyberOracle.is_available(ethereum_client))
kyber_oracle = KyberOracle(ethereum_client)
price = kyber_oracle.get_price(
gno_token_mainnet_address, weth_token_mainnet_address
Expand Down
2 changes: 2 additions & 0 deletions gnosis/eth/tests/oracles/test_sushiswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def test_get_price(self):
oracles_get_decimals.cache_clear()
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(SushiswapOracle.is_available(ethereum_client))
sushiswap_oracle = SushiswapOracle(ethereum_client)

price = sushiswap_oracle.get_price(
Expand Down
20 changes: 20 additions & 0 deletions gnosis/eth/tests/test_oracles.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class TestOracles(EthereumTestCaseMixin, TestCase):
def test_uniswap_oracle(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(UniswapOracle.is_available(ethereum_client))
uniswap_oracle = UniswapOracle(ethereum_client)
token_address = dai_token_mainnet_address
price = uniswap_oracle.get_price(token_address)
Expand Down Expand Up @@ -100,6 +102,8 @@ def test_get_price(self):
oracles_get_decimals.cache_clear()
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(UniswapV2Oracle.is_available(ethereum_client))
uniswap_v2_oracle = UniswapV2Oracle(ethereum_client)

self.assertEqual(oracles_get_decimals.cache_info().currsize, 0)
Expand Down Expand Up @@ -195,6 +199,8 @@ class TestAaveOracle(EthereumTestCaseMixin, TestCase):
def test_get_token_price(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(AaveOracle.is_available(ethereum_client))
uniswap_oracle = UniswapV2Oracle(ethereum_client)
aave_oracle = AaveOracle(ethereum_client, uniswap_oracle)

Expand All @@ -218,6 +224,8 @@ class TestCreamOracle(EthereumTestCaseMixin, TestCase):
def test_get_price(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(CreamOracle.is_available(ethereum_client))
sushi_oracle = SushiswapOracle(ethereum_client)
cream_oracle = CreamOracle(ethereum_client, sushi_oracle)

Expand Down Expand Up @@ -249,6 +257,8 @@ def test_get_underlying_tokens(self):

mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(CurveOracle.is_available(ethereum_client))
curve_oracle = CurveOracle(ethereum_client)

# Curve.fi ETH/stETH (steCRV) is working with the updated adapter
Expand Down Expand Up @@ -321,6 +331,8 @@ def test_get_underlying_token(self):

mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(PoolTogetherOracle.is_available(ethereum_client))
pool_together_oracle = PoolTogetherOracle(ethereum_client)

underlying_tokens = pool_together_oracle.get_underlying_tokens(
Expand All @@ -345,6 +357,8 @@ class TestYearnOracle(EthereumTestCaseMixin, TestCase):
def test_get_underlying_tokens(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(YearnOracle.is_available(ethereum_client))
yearn_oracle = YearnOracle(ethereum_client)
yearn_token_address = "0x5533ed0a3b83F70c3c4a1f69Ef5546D3D4713E44" # Yearn Curve.fi DAI/USDC/USDT/sUSD
yearn_underlying_token_address = (
Expand Down Expand Up @@ -400,6 +414,8 @@ class TestBalancerOracle(EthereumTestCaseMixin, TestCase):
def test_get_pool_token_price(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(BalancerOracle.is_available(ethereum_client))
uniswap_oracle = UniswapV2Oracle(ethereum_client)
balancer_oracle = BalancerOracle(ethereum_client, uniswap_oracle)
balancer_token_address = (
Expand All @@ -424,6 +440,8 @@ class TestMooniswapOracle(EthereumTestCaseMixin, TestCase):
def test_get_pool_token_price(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(MooniswapOracle.is_available(ethereum_client))
uniswap_oracle = UniswapV2Oracle(ethereum_client)
mooniswap_oracle = MooniswapOracle(ethereum_client, uniswap_oracle)
mooniswap_pool_address = "0x6a11F3E5a01D129e566d783A7b6E8862bFD66CcA" # 1inch Liquidity Pool (ETH-WBTC)
Expand Down Expand Up @@ -455,6 +473,8 @@ class TestEnzymeOracle(EthereumTestCaseMixin, TestCase):
def test_get_underlying_tokens(self):
mainnet_node = just_test_if_mainnet_node()
ethereum_client = EthereumClient(mainnet_node)

self.assertTrue(EnzymeOracle.is_available(ethereum_client))
enzyme_oracle = EnzymeOracle(ethereum_client)
mln_vault_token_address = "0x45c45799Bcf6C7Eb2Df0DA1240BE04cE1D18CC69"
mln_vault_underlying_token = "0xec67005c4E498Ec7f55E092bd1d35cbC47C91892"
Expand Down

0 comments on commit ad9c6c7

Please sign in to comment.