diff --git a/birdeyepy/birdeye.py b/birdeyepy/birdeye.py index 7c95237..65ab6ea 100644 --- a/birdeyepy/birdeye.py +++ b/birdeyepy/birdeye.py @@ -7,7 +7,7 @@ ) -__version__ = "0.0.6" +__version__ = "0.0.7" class BirdEye: diff --git a/birdeyepy/resources/defi.py b/birdeyepy/resources/defi.py index 4ad6c1b..3caa6ab 100644 --- a/birdeyepy/resources/defi.py +++ b/birdeyepy/resources/defi.py @@ -66,3 +66,233 @@ def history( response = self.http.send(path=BirdEyeApiUrls.DEFI_HISTORY_PRICE, **request) return cast(dict, response) + + def supported_networks(self) -> dict: + """Get a list of all supported networks.""" + response = self.http.send(path=BirdEyeApiUrls.DEFI_SUPPORTED_NETWORKS) + + return cast(dict, response) + + @as_api_args + def price_multiple( + self, + *, + addresses: list | str, + check_liquidity: Optional[int] = 100, + include_liquidity: Optional[bool] = None, + ) -> dict: + """Get price updates of multiple tokens in a single API call. Maximum 100 tokens + + :param addresses: The addresses of the tokens. + :param check_liquidity: The minimum liquidity to check. + :param include_liquidity: Include liquidity in the response. + """ + params = {"list_address": addresses, "check_liquidity": check_liquidity} + + if include_liquidity is not None: + params["include_liquidity"] = include_liquidity + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_PRICE_MULTIPLE, **request) + + return cast(dict, response) + + def history_by_unix(self, *, address: str, unixtime: int) -> dict: + """Get historical price of a token at a specific Unix time. + + :param address: The address of the token. + :param unixtime: The Unix time. + """ + params = {"address": address, "time": unixtime} + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send( + path=BirdEyeApiUrls.DEFI_HISTORY_PRICE_BY_UNIX, **request + ) + + return cast(dict, response) + + def trades_token( + self, + *, + address: Optional[str] = DEFAULT_SOL_ADDRESS, + tx_type: Optional[str] = "swap", + sort_type: Optional[str] = "desc", + offset: Optional[int] = 0, + limit: Optional[int] = 50, + ) -> dict: + """Get trades of a token. + + :param address: The address of the token. + :param tx_type: The type of transaction. + :param sort_type: The type of sorting. + :param limit: The limit. + """ + params = { + "address": address, + "tx_type": tx_type, + "sort_type": sort_type, + "offset": offset, + "limit": limit, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_TRADES_TOKEN, **request) + + return cast(dict, response) + + def trades_pair( + self, + *, + address: str, + tx_type: Optional[str] = "swap", + sort_type: Optional[str] = "desc", + offset: Optional[int] = 0, + limit: Optional[int] = 50, + ) -> dict: + """Get list of trades of a certain pair or market. + + :param address: The address of the token. + :param tx_type: The type of transaction. + :param sort_type: The type of sorting. + :param limit: The limit. + """ + params = { + "address": address, + "tx_type": tx_type, + "sort_type": sort_type, + "offset": offset, + "limit": limit, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_TRADES_PAIR, **request) + + return cast(dict, response) + + def trades_token_by_time( + self, + *, + address: Optional[str] = DEFAULT_SOL_ADDRESS, + tx_type: Optional[str] = "swap", + sort_type: Optional[str] = "desc", + offset: Optional[int] = 0, + limit: Optional[int] = 50, + before_time: Optional[int] = 0, + after_time: Optional[int] = 0, + ) -> dict: + """Get list of trades of a token with time bound option.""" + params = { + "address": address, + "tx_type": tx_type, + "sort_type": sort_type, + "offset": offset, + "limit": limit, + "before_time": before_time, + "after_time": after_time, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send( + path=BirdEyeApiUrls.DEFI_TRADES_TOKEN_BY_TIME, **request + ) + + return cast(dict, response) + + def trades_pair_by_time( + self, + *, + address: Optional[str] = DEFAULT_SOL_ADDRESS, + tx_type: Optional[str] = "swap", + sort_type: Optional[str] = "desc", + offset: Optional[int] = 0, + limit: Optional[int] = 50, + before_time: Optional[int] = 0, + after_time: Optional[int] = 0, + ) -> dict: + """Get list of trades of a certain pair or market with time bound option.""" + params = { + "address": address, + "tx_type": tx_type, + "sort_type": sort_type, + "offset": offset, + "limit": limit, + "before_time": before_time, + "after_time": after_time, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send( + path=BirdEyeApiUrls.DEFI_TRADES_PAIR_BY_TIME, **request + ) + + return cast(dict, response) + + def ohlcv( + self, + *, + address: str, + time_from: int, + time_to: int, + type_in_time: Optional[str] = "15m", + ) -> dict: + """Get OHLCV price of a token. + + :param address: The address of the token. + :param time_from: Specify the start time using Unix timestamps in seconds + :param time_to: Specify the end time using Unix timestamps in seconds + :param type_in_time: The type of time...defaults to '15m' + """ + params = { + "address": address, + "time_from": time_from, + "time_to": time_to, + "type": type_in_time, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_OHLCV, **request) + + return cast(dict, response) + + def ohlcv_pair( + self, + *, + address: str, + time_from: int, + time_to: int, + type_in_time: Optional[str] = "15m", + ) -> dict: + """Get OHLCV price of a pair. + + :param address: The address of the token. + :param time_from: Specify the start time using Unix timestamps in seconds + :param time_to: Specify the end time using Unix timestamps in seconds + :param type_in_time: The type of time...defaults to '15m' + """ + params = { + "address": address, + "time_from": time_from, + "time_to": time_to, + "type": type_in_time, + } + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_OHLCV_PAIR, **request) + + return cast(dict, response) + + def volume_price_single( + self, *, address: str, type_in_time: Optional[str] = "24h" + ) -> dict: + """Get volume and price of a token. + + :param address: The address of the token. + :param type_in_time: The type of time...defaults to '24h' + """ + params = {"address": address, "type": type_in_time} + + request: BirdEyeRequestParams = {"params": params} + response = self.http.send(path=BirdEyeApiUrls.DEFI_VOLUME_SINGLE, **request) + + return cast(dict, response) diff --git a/birdeyepy/utils/enums.py b/birdeyepy/utils/enums.py index eb4ef26..322ed51 100644 --- a/birdeyepy/utils/enums.py +++ b/birdeyepy/utils/enums.py @@ -9,6 +9,16 @@ class BirdEyeApiUrls: DEFI_PRICE = "defi/price" DEFI_TOKEN_LIST = "defi/tokenlist" DEFI_HISTORY_PRICE = "defi/history_price" + DEFI_SUPPORTED_NETWORKS = "defi/networks" + DEFI_PRICE_MULTIPLE = "defi/multi_price" + DEFI_HISTORY_PRICE_BY_UNIX = "defi/historical_price_unix" + DEFI_TRADES_TOKEN = "defi/txs/token" + DEFI_TRADES_PAIR = "defi/txs/pair" + DEFI_TRADES_TOKEN_BY_TIME = "defi/txs/token/seek_by_time" + DEFI_TRADES_PAIR_BY_TIME = "defi/txs/pair/seek_by_time" + DEFI_OHLCV = "defi/ohlcv" + DEFI_OHLCV_PAIR = "defi/ohlcv/pair" + DEFI_VOLUME_SINGLE = "defi/price_volume/single" # TRADER TRADER_GAINERS_LOSERS = "trader/gainers-losers" diff --git a/docs/source/code_overview/client.rst b/docs/source/code_overview/client.rst index 6fbbac6..64d1711 100644 --- a/docs/source/code_overview/client.rst +++ b/docs/source/code_overview/client.rst @@ -49,6 +49,63 @@ APIs type_in_time="15m" # default ) + # https://docs.birdeye.so/reference/get_defi-networks + client.defi.supported_networks() + + # https://docs.birdeye.so/reference/get_defi-multi-price + client.defi.price_multiple( + addresses=["Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ", "AGQZRtz7hZtz3VJ1CoXRMNMyh2ZMZ1g6pv4aGMUSpump"], + ) # can also use comma separated strings 'Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ,AGQZRtz7hZtz3VJ1CoXRMNMyh2ZMZ1g6pv4aGMUSpump' + + # https://docs.birdeye.so/reference/get_defi-historical-price-unix + client.defi.history_by_unix( + address="Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ", + unixtime=1732398942 + ) + + # https://docs.birdeye.so/reference/get_defi-txs-token + client.defi.trades_token( + address="Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ + ) + + # https://docs.birdeye.so/reference/get_defi-txs-pair + client.defi.trades_pair( + address="9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT + ) + + # https://docs.birdeye.so/reference/get_defi-txs-token-seek-by-time + client.defi.trades_token_by_time( + address="Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ", + before_time=1732398942, + after_time=1732398961 + ) + + # https://docs.birdeye.so/reference/get_defi-txs-pair-seek-by-time + client.defi.trades_pair_by_time( + address="9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT", + before_time=1732398942, + after_time=1732398961 + ) + + # https://docs.birdeye.so/reference/get_defi-ohlcv + client.defi.ohlcv( + address="Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ", + time_from=1732398942, + time_to=1732398961 + ) + + # https://docs.birdeye.so/reference/get_defi-ohlcv-pair + client.defi.ohlcv_pair( + address="9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT", + time_from=1732398942, + time_to=1732398961 + ) + + # https://docs.birdeye.so/reference/get_defi-price-volume-single + client.defi.volume_price_single( + address="Gr11mosZNZjwpqnemXNnWs9E2Bnv7R6vzaKwJTdjo8zQ" + ) + # TOKEN # https://docs.birdeye.so/reference/get_defi-tokenlist diff --git a/pyproject.toml b/pyproject.toml index 5692c68..bc0bfb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "birdeye-py" -version = "0.0.6" +version = "0.0.7" description = "Python wrapper for birdeye.so api" readme = "README.md" requires-python = ">=3.9" diff --git a/tests/unit/resources/test_defi.py b/tests/unit/resources/test_defi.py index e9c3ece..31fd212 100644 --- a/tests/unit/resources/test_defi.py +++ b/tests/unit/resources/test_defi.py @@ -41,3 +41,208 @@ def test_defi_history_api_called_with_expected_args() -> None: "type": "15m", }, ) + + +def test_defi_supported_networks_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.supported_networks() + + # Assert + mock_http.send.assert_called_once_with(path=BirdEyeApiUrls.DEFI_SUPPORTED_NETWORKS) + + +def test_defi_price_multiple_args_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.price_multiple(addresses="test", check_liquidity=50, include_liquidity=False) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_PRICE_MULTIPLE, + params={ + "list_address": "test", + "check_liquidity": 50, + "include_liquidity": "false", + }, + ) + + +def test_defi_history_by_unix_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.history_by_unix(address="test", unixtime=1) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_HISTORY_PRICE_BY_UNIX, + params={"address": "test", "time": 1}, + ) + + +def test_defi_trades_token_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.trades_token(address="test") + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_TRADES_TOKEN, + params={ + "address": "test", + "tx_type": "swap", + "sort_type": "desc", + "offset": 0, + "limit": 50, + }, + ) + + +def test_defi_trades_pair_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.trades_pair(address="test") + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_TRADES_PAIR, + params={ + "address": "test", + "tx_type": "swap", + "sort_type": "desc", + "offset": 0, + "limit": 50, + }, + ) + + +def test_defi_trades_token_by_time_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.trades_token_by_time( + address="test", + before_time=1, + after_time=2, + ) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_TRADES_TOKEN_BY_TIME, + params={ + "address": "test", + "before_time": 1, + "after_time": 2, + "tx_type": "swap", + "sort_type": "desc", + "offset": 0, + "limit": 50, + }, + ) + + +def test_defi_trades_pair_by_time_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.trades_pair_by_time( + address="test", + before_time=1, + after_time=2, + ) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_TRADES_PAIR_BY_TIME, + params={ + "address": "test", + "before_time": 1, + "after_time": 2, + "tx_type": "swap", + "sort_type": "desc", + "offset": 0, + "limit": 50, + }, + ) + + +def test_defi_ohlcv_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.ohlcv( + address="test", + time_from=1, + time_to=2, + ) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_OHLCV, + params={ + "address": "test", + "time_from": 1, + "time_to": 2, + "type": "15m", + }, + ) + + +def test_defi_ohlcv_pair_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.ohlcv_pair( + address="test", + time_from=1, + time_to=2, + ) + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_OHLCV_PAIR, + params={ + "address": "test", + "time_from": 1, + "time_to": 2, + "type": "15m", + }, + ) + + +def test_defi_volume_price_single_api_called_with_expected_args() -> None: + # Arrange + mock_http = MagicMock() + + # Act + client = DeFi(http=mock_http) + client.volume_price_single(address="test") + + # Assert + mock_http.send.assert_called_once_with( + path=BirdEyeApiUrls.DEFI_VOLUME_SINGLE, + params={"address": "test", "type": "24h"}, + ) diff --git a/uv.lock b/uv.lock index 22eaedc..abc725b 100644 --- a/uv.lock +++ b/uv.lock @@ -42,7 +42,7 @@ wheels = [ [[package]] name = "birdeye-py" -version = "0.0.6" +version = "0.0.7" source = { virtual = "." } dependencies = [ { name = "requests" },