rmi-backend/app/adapters/binance_web3.py

71 lines
1.8 KiB
Python

"""
Binance Web3 API adapter for Wallet PnL Analyzer.
All endpoints are free and require no authentication.
"""
import httpx
BASE_URL = "https://web3.binance.com"
CHAIN_IDS = {
"bsc": "56",
"eth": "1",
"base": "8453",
"arb": "42161",
"polygon": "137",
}
CHAIN_NAMES = {
"56": "BSC",
"1": "ETH",
"8453": "BASE",
"42161": "ARB",
"137": "POLYGON",
}
# Headers required by the wallet holdings endpoint
_HEADERS = {
"Accept-Encoding": "identity",
"clienttype": "web",
"clientversion": "1.2.0",
}
def _get(url, params=None, timeout=10):
resp = httpx.get(url, params=params, headers=_HEADERS, timeout=timeout)
resp.raise_for_status()
data = resp.json()
if data.get("code") != "000000":
raise ConnectionError(f"API error: {data.get('message', 'unknown')}")
return data.get("data", {})
def get_wallet_holdings(address: str, chain_id: str) -> list:
"""
Fetch all token holdings for a wallet address on a specific chain.
Args:
address: Wallet address (e.g. "0xAb58...")
chain_id: Chain ID string (e.g. "56", "1")
Returns:
List of token dicts with: symbol, name, price, remainQty,
percentChange24h, contractAddress, riskLevel
"""
url = f"{BASE_URL}/bapi/defi/v3/public/wallet-direct/buw/wallet/address/pnl/active-position-list"
all_tokens = []
offset = 0
max_pages = 5 # cap at 100 tokens to avoid long-running loops
for _ in range(max_pages):
params = {"address": address.lower(), "chainId": chain_id, "offset": offset}
data = _get(url, params=params)
batch = data.get("list") or []
all_tokens.extend(batch)
if len(batch) < 20:
break
offset += len(batch)
return all_tokens