diff --git a/blockapi/test/v2/api/data/sui/response.json b/blockapi/test/v2/api/data/sui/response.json index f8891a09..8cbd13d8 100644 --- a/blockapi/test/v2/api/data/sui/response.json +++ b/blockapi/test/v2/api/data/sui/response.json @@ -1,76 +1,29 @@ -{ - "coins":[ - { - "coinType":"0x2::sui::SUI", - "coinName":"Sui", - "coinDenom":"SUI", - "decimals":9, - "coinSymbol":"SUI", - "objectType":"Coin", - "objectsCount":1, - "lockedBalance":null, - "totalBalance":376709800, - "coinPrice":3.36, - "imgUrl":"https://strapi-dev.scand.app/uploads/sui_c07df05f00.png", - "securityMessage":null, - "bridged":false, - "hasNoMetadata":false, - "verified":true - }, - { - "coinType":"0x9fe1780ac27ec50c9c441fb31822f5c148f841f09ee455c6a0daf7c634a30a27::aifrens::AIFRENS", - "coinName":"xAIFRENS", - "coinDenom":"xAIFRENS", - "decimals":0, - "coinSymbol":"xAIFRENS", - "objectType":"Coin", - "objectsCount":1, - "lockedBalance":null, - "totalBalance":80, - "coinPrice":1.229095042620968e-13, - "imgUrl":"https://strapi-dev.scand.app/uploads/x_AIFRENS_Logo_26fd7a81e1.jpeg", - "securityMessage":null, - "bridged":false, - "hasNoMetadata":false, - "verified":true - }, - { - "coinType":"0xa8816d3a6e3136e86bc2873b1f94a15cadc8af2703c075f2d546c2ae367f4df9::ocean::OCEAN", - "coinName":"Ocean Token", - "coinDenom":"OCEAN", - "decimals":9, - "coinSymbol":"OCEAN", - "objectType":"Coin", - "objectsCount":16, - "lockedBalance":null, - "totalBalance":31000000000, - "coinPrice":0.00013589238714095824, - "imgUrl":"https://file.walletapp.waveonsui.com/logos/ocean.png", - "securityMessage":null, - "bridged":false, - "hasNoMetadata":false, - "verified":true - }, - { - "coinType":"0xf33945da679604ad966a7381156549be43f94bd2d919665d406389ba1475e86b::dogai::DOGAI", - "coinName":"SuiDog AI", - "coinDenom":"DOGAI", - "decimals":6, - "coinSymbol":"DOGAI", - "objectType":"Coin", - "objectsCount":1, - "lockedBalance":null, - "totalBalance":42714100000, - "coinPrice":0.0000019948186051715394, - "imgUrl":"https://r.turbos.finance/icon/1731177923663.jpg", - "securityMessage":null, - "bridged":false, - "hasNoMetadata":false, - "verified":false - } - ], - "nfts":null, - "domains":null, - "unknowns":null, - "kiosks":null -} \ No newline at end of file +[ + { + "coinType": "0x9fe1780ac27ec50c9c441fb31822f5c148f841f09ee455c6a0daf7c634a30a27::aifrens::AIFRENS", + "coinName": "xAIFRENS", + "coinSymbol": "xAIFRENS", + "balance": 80, + "balanceUsd": 1.0965306954562768e-11, + "decimals": 0, + "coinPrice": 1.370663369320346e-13 + }, + { + "coinType": "0x2::sui::SUI", + "coinName": "Sui", + "coinSymbol": "SUI", + "balance": 0.13706648, + "balanceUsd": 0.5660845624, + "decimals": 9, + "coinPrice": 4.13 + }, + { + "coinType": "0xa8816d3a6e3136e86bc2873b1f94a15cadc8af2703c075f2d546c2ae367f4df9::ocean::OCEAN", + "coinName": "Ocean Token", + "coinSymbol": "OCEAN", + "balance": 31, + "balanceUsd": 0.0040252012787930554, + "decimals": 9, + "coinPrice": 0.00012984520254171147 + } +] \ No newline at end of file diff --git a/blockapi/test/v2/api/test_sui.py b/blockapi/test/v2/api/test_sui.py index 632a6e67..ed9bfe88 100644 --- a/blockapi/test/v2/api/test_sui.py +++ b/blockapi/test/v2/api/test_sui.py @@ -15,9 +15,9 @@ def sui_response_data(): @pytest.fixture def mocked_sui_response(requests_mock, sui_response_data): - requests_mock.post( - f"https://api.blockberry.one/sui/v1/accounts/0x123/objects", - status_code=20, + requests_mock.get( + f"https://api.blockberry.one/sui/v1/accounts/0x123/balance", + status_code=200, json=sui_response_data, ) yield requests_mock @@ -28,7 +28,7 @@ def test_sui(mocked_sui_response): balances = api.get_balance(TEST_ADDRESS) assert balances - assert len(balances) == 4 + assert len(balances) == 3 for balance in balances: assert balance.coin.address @@ -37,7 +37,8 @@ def test_sui(mocked_sui_response): assert balance.coin.name != 'unknown' assert balance - assert balance.balance_raw + assert balance.balance + assert not balance.balance_raw # We got only balances from blockberry SUI API @pytest.mark.parametrize( diff --git a/blockapi/v2/api/sui.py b/blockapi/v2/api/sui.py index 1c1d8d11..fe4b98a9 100644 --- a/blockapi/v2/api/sui.py +++ b/blockapi/v2/api/sui.py @@ -13,11 +13,11 @@ class SuiApi(BlockchainApi, IBalance): api_options = ApiOptions( blockchain=Blockchain.SUI, base_url="https://api.blockberry.one", - rate_limit=0.25, # 4 per second + rate_limit=1, # 1 per second ) supported_requests = { - 'get_balances': '/sui/v1/accounts/{address}/objects', + 'get_balances': '/sui/v1/accounts/{address}/balance', } def __init__(self, api_key, *args, **kwargs): @@ -29,9 +29,9 @@ def get_balance(self, address: str) -> List[BalanceItem]: return balances def _yield_available_balance(self, address: str) -> Iterable[BalanceItem]: - response = self._post('get_balances', address=address) + response = self._get('get_balances', address=address) - for response_coin in response.get('coins', list()): + for response_coin in response: coin = Coin.from_api( blockchain=Blockchain.SUI, decimals=response_coin.get('decimals'), @@ -41,7 +41,7 @@ def _yield_available_balance(self, address: str) -> Iterable[BalanceItem]: ) yield BalanceItem.from_api( - balance_raw=response_coin.get('totalBalance', 0), + balance=response_coin.get('balance', 0), coin=coin, raw=response_coin, ) @@ -53,12 +53,9 @@ def _format_address(address): return re.sub(r"0x0+", "0x", address) - def _post(self, request_method: str, address) -> dict: - - json_request = {"objectTypes": ["coin"]} - return self.post( + def _get(self, request_method: str, address) -> dict: + return self.get( request_method=request_method, headers=self._headers, - json=json_request, address=address, ) diff --git a/blockapi/v2/models.py b/blockapi/v2/models.py index b1057579..44b4f3bd 100644 --- a/blockapi/v2/models.py +++ b/blockapi/v2/models.py @@ -606,7 +606,7 @@ class BalanceItem: def from_api( cls, *, - balance_raw: Union[int, float, str, Decimal], + balance_raw: Union[int, float, str, Decimal] = None, coin: Optional[Coin] = None, coin_contract: Optional[CoinContract] = None, asset_type: AssetType = AssetType.AVAILABLE, @@ -615,15 +615,22 @@ def from_api( protocol: Optional[Protocol] = None, is_wallet: bool = True, pool_info: Optional[PoolInfo] = None, + balance: Optional[Decimal] = None, ) -> 'BalanceItem': if coin is None and coin_contract is None: raise ValueError('Either coin or coin_contract must be set') - return cls( - balance_raw=to_decimal(balance_raw), - balance=raw_to_decimals( + raw_balance = to_decimal(balance_raw) if balance_raw else None + balance = ( + balance + if balance + else raw_to_decimals( balance_raw, coin.decimals if coin else coin_contract.decimals - ), + ) + ) + return cls( + balance_raw=raw_balance, + balance=balance, coin=coin, coin_contract=coin_contract, asset_type=asset_type,