From 6b4ea5925dafa9b1dc9d9a7a0ee5ad6842759f56 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Sat, 12 Jun 2021 14:21:07 +0100 Subject: [PATCH] Added FTX price oracle. --- Makefile | 2 + mango/oraclefactory.py | 9 ++-- mango/oracles/ftx/__init__.py | 0 mango/oracles/ftx/ftx.py | 81 +++++++++++++++++++++++++++++++++++ requirements.txt | 23 +++++----- 5 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 mango/oracles/ftx/__init__.py create mode 100644 mango/oracles/ftx/ftx.py diff --git a/Makefile b/Makefile index 25c7a72..12ddf03 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,11 @@ commands := $(wildcard bin/*) setup: ## Install all the build and lint dependencies pip install -r requirements.txt + echo "y" | mypy --install-types upgrade: ## Upgrade all the build and lint dependencies pip install --upgrade -r requirements.txt + echo "y" | mypy --install-types test: ## Run all the tests pytest -rP tests diff --git a/mango/oraclefactory.py b/mango/oraclefactory.py index 0d288a9..604b5da 100644 --- a/mango/oraclefactory.py +++ b/mango/oraclefactory.py @@ -14,6 +14,7 @@ # [Email](mailto:hello@blockworks.foundation) from .oracle import OracleProvider +from .oracles.ftx import ftx from .oracles.pythnetwork import pythnetwork from .oracles.serum import serum from .spotmarket import SpotMarketLookup @@ -25,8 +26,10 @@ from .spotmarket import SpotMarketLookup # def create_oracle_provider(provider_name: str, spot_market_lookup: SpotMarketLookup) -> OracleProvider: - if provider_name == "pyth": - return pythnetwork.PythOracleProvider() - elif provider_name == "serum": + if provider_name == "serum": return serum.SerumOracleProvider(spot_market_lookup) + elif provider_name == "ftx": + return ftx.FtxOracleProvider() + elif provider_name == "pyth": + return pythnetwork.PythOracleProvider() raise Exception(f"Unknown oracle provider '{provider_name}'.") diff --git a/mango/oracles/ftx/__init__.py b/mango/oracles/ftx/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mango/oracles/ftx/ftx.py b/mango/oracles/ftx/ftx.py new file mode 100644 index 0000000..7defcb7 --- /dev/null +++ b/mango/oracles/ftx/ftx.py @@ -0,0 +1,81 @@ +# # ⚠ Warning +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# [🥭 Mango Markets](https://markets/) support is available at: +# [Docs](https://docs.markets/) +# [Discord](https://discord.gg/67jySBhxrg) +# [Twitter](https://twitter.com/mangomarkets) +# [Github](https://github.com/blockworks-foundation) +# [Email](mailto:hello@blockworks.foundation) + + +import requests +import typing + +from datetime import datetime +from decimal import Decimal + +from ...context import Context +from ...market import Market +from ...oracle import Oracle, OracleProvider, OracleSource, Price + + +# # 🥭 FTX +# +# This file contains code specific to the [Ftx Network](https://pyth.network/). +# + +def _ftx_get_from_url(url: str) -> typing.Dict: + response = requests.get(url) + response_values = response.json() + if ("success" not in response_values) or (not response_values["success"]): + raise Exception(f"Failed to get from FTX URL: {url} - {response_values}") + return response_values["result"] + + +# # 🥭 FtxOracle class +# +# Implements the `Oracle` abstract base class specialised to the Ftx Network. +# + + +class FtxOracle(Oracle): + def __init__(self, market: Market): + name = f"Ftx Oracle for {market.symbol}" + super().__init__(name, market) + self.market: Market = market + self.source: OracleSource = OracleSource("FTX", name, market) + + def fetch_price(self, context: Context) -> Price: + result = _ftx_get_from_url(f"https://ftx.com/api/markets/{self.market.symbol}") + bid = Decimal(result["bid"]) + ask = Decimal(result["ask"]) + price = Decimal(result["price"]) + + return Price(self.source, datetime.now(), self.market, bid, price, ask) + + +# # 🥭 FtxOracleProvider class +# +# Implements the `OracleProvider` abstract base class specialised to the Ftx Network. +# + +class FtxOracleProvider(OracleProvider): + def __init__(self) -> None: + super().__init__("Ftx Oracle Factory") + + def oracle_for_market(self, context: Context, market: Market) -> typing.Optional[Oracle]: + return FtxOracle(market) + + def all_available_symbols(self, context: Context) -> typing.List[str]: + result = _ftx_get_from_url("https://ftx.com/api/markets") + symbols: typing.List[str] = [] + for market in result: + symbols += [market["name"]] + + return symbols diff --git a/requirements.txt b/requirements.txt index fcf9071..2067518 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,12 @@ -ipython -jupyter_contrib_nbextensions -mypy -nblint -pandas -pyserum -pytest -rx -rxpy_backpressure -solana -web3 +ipython>=7.24.1 +jupyter_contrib_nbextensions>=0.5.1 +mypy>=0.902 +nblint>=0.0.3 +pandas>=1.2.4 +pyserum>=0.3.3a1 +pytest>=6.2.4 +requests>=2.25.1 +rx>=3.2.0 +rxpy_backpressure>=1.0.0 +solana>=0.9.2 +websockets>=9.1