Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions blockapi/test/v2/api/debank/test_debank_app_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,58 @@ def test_parse_polymarket_predictions(debank_app_parser, polymarket_response):
assert pred2.chain == Blockchain.POLYGON


def test_parse_deposit_unmapped_symbol_is_not_dropped(debank_app_parser):
"""A deposit token missing from symbol_to_coin_map must be kept, with the
coin built from the token's own fields (not silently dropped)."""
response = [
{
"id": "hyperliquid",
"name": "Hyperliquid",
"has_supported_portfolio": True,
"portfolio_item_list": [
{
"stats": {
"asset_usd_value": 1234.5,
"debt_usd_value": 0,
"net_usd_value": 1234.5,
},
"asset_token_list": [
{
"id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"name": "Hyperliquid",
"symbol": "HYPE",
"decimals": 18,
"app_id": "hyperliquid",
"price": 41.2,
"amount": 30.0,
}
],
"update_at": 1779790996.4148061,
"name": "Deposit",
"detail_types": ["common"],
"detail": {},
"position_index": "spot_0xabc",
}
],
}
]

parsed_apps = debank_app_parser.parse(response)
app = parsed_apps[0]

assert len(app.deposits) == 1
deposit = app.deposits[0]
assert deposit.asset_type == AssetType.DEPOSITED
assert deposit.balance_raw == Decimal("30.0")
assert deposit.coin.symbol == "HYPE"
assert deposit.coin.name == "Hyperliquid"
assert deposit.coin.decimals == 18
assert deposit.coin.blockchain == Blockchain.HYPERLIQUID
# token.id is passed through as address (unique per token) so unmapped
# tokens don't collapse into one unknown currency downstream.
assert deposit.coin.address == "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"


def test_parse_multiple_apps(debank_app_parser):
"""Test parsing multiple apps."""
response = [
Expand Down
45 changes: 31 additions & 14 deletions blockapi/v2/api/debank.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
DebankModelApp,
DebankModelAppPortfolioItem,
DebankModelAppStats,
DebankModelDepositToken,
DebankModelPredictionDetail,
DebankPrediction,
FetchResult,
Expand Down Expand Up @@ -688,33 +689,49 @@ def _parse_deposit(
) -> list[BalanceItem]:
balances = []
for token in item.asset_token_list or []:
coin = symbol_to_coin_map.get(token.symbol)
if not coin:
logger.error(
f'No coin mapping found for app deposit token {token.symbol} in chain {chain}. Skipping.'
# Map first so well-known tokens keep their canonical coingecko_id.
mapped = symbol_to_coin_map.get(token.symbol)
if mapped:
coin = Coin.from_api(
blockchain=chain,
decimals=mapped.decimals,
name=mapped.name,
symbol=mapped.symbol,
info=mapped.info,
)
continue

coin_with_app_chain = Coin.from_api(
blockchain=chain,
decimals=coin.decimals,
name=coin.name,
symbol=coin.symbol,
info=coin.info,
)
else:
coin = self._coin_from_deposit_token(token, chain)

balance = BalanceItem.from_api(
balance=Decimal(token.amount),
balance_raw=token.amount,
asset_type=AssetType.DEPOSITED,
coin=coin_with_app_chain,
coin=coin,
raw=token.model_dump(),
last_updated=int(item.update_at) if item.update_at else None,
)
balances.append(balance)

return balances

@staticmethod
def _coin_from_deposit_token(
token: DebankModelDepositToken, chain: Blockchain
) -> Coin:
# Address must stay unique per token: a null one makes downstream
# add_unknown_currency_v2 key the currency by chain, collapsing all
# unmapped tokens on a chain into one.
address = make_checksum_address(token.id) or token.id
coingecko_id = get_coingecko_id(token.id, token.symbol)
return Coin.from_api(
symbol=token.symbol,
name=token.name,
decimals=token.decimals,
blockchain=chain,
address=address,
info=CoinInfo(logo_url=token.logo_url, coingecko_id=coingecko_id),
)


class DebankApi(CustomizableBlockchainApi, BalanceMixin, IPortfolio):
"""
Expand Down
Loading