71 lines
1.8 KiB
Python
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
|