
Debank
- 73 installs
- 21 repo stars
- Updated August 3, 2026
- starchild-ai-agent/official-skills
Helps with ai & agent building tasks during AI-assisted development.
About
debank is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- debank
- AI & Agent Building
- AI-coding skill
Debank by the numbers
- 73 all-time installs (skills.sh)
- +5 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #5,587 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/starchild-ai-agent/official-skills --skill debankAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 73 |
|---|---|
| repo stars | ★ 21 |
| Last updated | August 3, 2026 |
| Repository | starchild-ai-agent/official-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Script Usage
Script-mode skill — read this file, then invoke from a bash block:
python3 - <<'EOF'
import sys, json
sys.path.insert(0, "/data/workspace/skills/debank")
from exports import db_chain_list, db_user_total_balance, db_user_all_token_list
print(db_chain_list()[:3])
print(db_user_total_balance(user_addr="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"))
EOFRead exports.py for the full list of db_* functions and exact signatures. Common ones: db_chain_list, db_chain, db_token, db_user_total_balance, db_user_all_token_list, db_user_all_simple_protocol_list, db_user_all_complex_protocol_list, db_user_history_list, db_protocol, db_pre_exec_tx, db_explain_tx.
DeBank
DeBank provides comprehensive blockchain data including wallet portfolios, token balances, transaction history, DeFi protocol positions, NFTs, and transaction simulation.
Function Reference (signatures)
All functions are in exports.py. chain_id uses DeBank's lowercase codes: eth, bsc, arb, op, base, matic, avax, sol, era, scrl, linea, mnt, blast, etc. — use db_chain_list() to enumerate. user_addr is the wallet address (lowercase). protocol_id from db_protocol_list().
Chain & Token reference
| Function | Description |
|---|---|
db_chain_list() | List all supported chains. |
db_chain(chain_id) | One chain's metadata. |
db_gas_market(chain_id) | Gas prices for a chain. |
db_token(chain_id, token_id) | Token detail. token_id = contract address (or eth, bnb for native). |
db_token_list_by_ids(chain_id, token_ids) | Batch token lookup. |
db_token_history_price(chain_id, token_id, start_time, end_time=None) | Historical prices (unix timestamps). |
db_token_top_holders(chain_id, token_id, start=0) | Top holders. |
User portfolio (single-chain)
| Function | Description |
|---|---|
db_user_chain_balance(user_addr, chain_id) | USD value on one chain. |
db_user_token_list(user_addr, chain_id, is_all=None) | Tokens on one chain. |
db_user_token(user_addr, chain_id, token_id) | One token balance. |
db_user_simple_protocol_list(user_addr, chain_id) | DeFi positions (light) on one chain. |
db_user_complex_protocol_list(user_addr, chain_id) | DeFi positions (detailed) on one chain. |
db_user_nft_list(user_addr, chain_id, is_all=None) | NFTs on one chain. |
db_user_history_list(user_addr, chain_id, start_time=None, page_count=None) | Tx history on one chain. |
db_user_chain_net_curve(user_addr, chain_id) | Net worth curve on one chain. |
db_user_token_authorized_list(user_addr, chain_id) | Token approvals (security audit). |
db_user_nft_authorized_list(user_addr, chain_id) | NFT approvals. |
User portfolio (all-chain — heavier calls)
| Function | Description |
|---|---|
db_user_total_balance(user_addr) | Total USD across all chains + breakdown. |
db_user_total_net_curve(user_addr) | Net worth curve across all chains. |
db_user_used_chain_list(user_addr) | Which chains the address has used. |
db_user_all_token_list(user_addr, is_all=None) | All tokens across all chains. |
db_user_all_simple_protocol_list(user_addr) | All DeFi positions (light). |
db_user_all_complex_protocol_list(user_addr) | All DeFi positions (detailed). |
db_user_all_nft_list(user_addr, is_all=None) | All NFTs. |
db_user_all_history_list(user_addr, start_time=None, page_count=None) | All tx history. |
db_user_complex_app_list(user_addr) | All app-level positions (more granular). |
Protocol reference
| Function | Description |
|---|---|
db_protocol(protocol_id) | Protocol detail. |
db_protocol_list(chain_id) | Protocols on one chain. |
db_protocol_all_list() | All protocols across chains. |
db_app_protocol_list() | App-level protocols (groups). |
db_user_protocol(user_addr, protocol_id) | User's position in one protocol. |
db_pool(protocol_id, chain_id, pool_id) | One pool's detail. |
Tx simulation
| Function | Description |
|---|---|
db_pre_exec_tx(user_addr, chain_id, tx) | Simulate tx before sending. tx = standard tx dict. |
db_explain_tx(user_addr, chain_id, tx) | Human-readable explanation of a tx. |
DeBank uses snake_case (total_usd_value, chain_id, usd_value). USD values are floats. Token amounts are floats (already adjusted for decimals — no need to divide by 10**decimals).
When to Use DeBank
Use DeBank for:
- User Portfolio - Total balance, token holdings, NFTs across all chains
- Transaction History - Historical transactions on single or all chains
- DeFi Positions - Protocol balances and complex portfolio positions
- Token Data - Token details, prices, and top holders
- Transaction Simulation - Pre-execute and explain transactions before submission
- Authorization Tracking - View token and NFT approvals
- Analytics - 24-hour net worth curves and portfolio tracking
Common Workflows
Get User Portfolio
db_user_total_balance(user_addr="0x...") # Total balance across all chains
db_user_all_token_list(user_addr="0x...") # All token holdings
db_user_all_nft_list(user_addr="0x...") # All NFT collectionsCheck Token Balances on Specific Chain
db_user_token_list(user_addr="0x...", chain_id="eth") # Ethereum tokens
db_user_token_list(user_addr="0x...", chain_id="bsc") # BSC tokensGet Transaction History
db_user_history_list(user_addr="0x...", chain_id="eth") # Eth transactions
db_user_all_history_list(user_addr="0x...") # All chain transactionsCheck DeFi Protocol Positions
db_user_simple_protocol_list(user_addr="0x...", chain_id="eth") # Simple balances
db_user_complex_protocol_list(user_addr="0x...", chain_id="eth") # Detailed positions
db_user_all_complex_protocol_list(user_addr="0x...") # All chainsToken Information
db_token(chain_id="eth", token_id="0x...") # Token details
db_token_history_price(chain_id="eth", token_id="0x...", start_time=1234567890, end_time=1234567990)
db_token_top_holders(chain_id="eth", token_id="0x...") # Top 100 holdersTransaction Simulation
db_pre_exec_tx(user_addr="0x...", chain_id="eth", tx={...}) # Enhanced pre-execution
db_explain_tx(user_addr="0x...", chain_id="eth", tx={...}) # Explain transactionProtocol Data
db_protocol(protocol_id="uniswap") # Protocol details
db_protocol_list(chain_id="eth") # All protocols on chain
db_protocol_all_list() # All protocols across chainsChain Information
db_chain_list() # All supported chains
db_chain(chain_id="eth") # Specific chain details
db_gas_market(chain_id="eth") # Gas pricesImportant Notes
- API Key: Requires DEBANK_API_KEY environment variable (DeBank Cloud API)
- User Address: Most endpoints require a valid blockchain address (0x... format)
- Chain IDs: Use DeBank chain identifiers (eth, bsc, polygon, arbitrum, optimism, etc.)
- Rate Limits: Be mindful of API rate limits and unit costs
- Unit Costs: Different endpoints have different unit costs (see API documentation)
Chain ID Reference
Common chain identifiers:
- eth → Ethereum Mainnet
- bsc → BNB Smart Chain
- polygon → Polygon
- arbitrum → Arbitrum One
- optimism → Optimism
- avax → Avalanche C-Chain
- ftm → Fantom
- op → Optimism
- base → Base
Important: Use db_chain_list() to get the complete list of supported chains and their identifiers.
Address Format
All user addresses should be in Ethereum format (0x followed by 40 hexadecimal characters):
- Valid: 0x1234567890abcdef1234567890abcdef12345678
- Invalid: 1234567890abcdef1234567890abcdef12345678 (missing 0x prefix)
"""
DeBank Extension - Blockchain Data Tools
Provides comprehensive blockchain data including:
- User portfolios and balances
- Token data and prices
- Transaction history
- DeFi protocol positions
- NFT holdings
- Transaction simulation
Environment Variables Required:
- DEBANK_API_KEY: DeBank Cloud API key
Usage:
This extension is auto-loaded by the ExtensionLoader.
Tools are available to agents configured with these tools in agents.yaml.
"""
import os
import sys
import logging
from typing import List
try:
from core.tool import ToolRegistry
except Exception:
ToolRegistry = None # Standalone script usage
logger = logging.getLogger(__name__)
# Add local tools directory to path for imports
TOOLS_DIR = os.path.join(os.path.dirname(__file__), 'tools')
if TOOLS_DIR not in sys.path:
sys.path.insert(0, TOOLS_DIR)
def register(api) -> List[str]:
"""
Extension entry point - register all DeBank tools.
Args:
api: ExtensionApi instance with registry and config
Returns:
List of registered tool names
"""
registered = []
try:
from .debank import (
# Chain tools (3)
DebankChainListTool,
DebankChainTool,
DebankGasMarketTool,
# Token tools (4)
DebankTokenTool,
DebankTokenHistoryPriceTool,
DebankTokenListByIdsTool,
DebankTokenTopHoldersTool,
# User balance tools (3)
DebankUserTotalBalanceTool,
DebankUserTokenListTool,
DebankUserAllTokenListTool,
# User history tools (2)
DebankUserHistoryListTool,
DebankUserAllHistoryListTool,
# User protocol tools (5)
DebankUserSimpleProtocolListTool,
DebankUserAllSimpleProtocolListTool,
DebankUserComplexProtocolListTool,
DebankUserAllComplexProtocolListTool,
DebankUserComplexAppListTool,
# User NFT tools (2)
DebankUserNftListTool,
DebankUserAllNftListTool,
# User misc tools (8)
DebankUserChainBalanceTool,
DebankUserTokenTool,
DebankUserProtocolTool,
DebankUserUsedChainListTool,
DebankUserTokenAuthorizedListTool,
DebankUserNftAuthorizedListTool,
DebankUserChainNetCurveTool,
DebankUserTotalNetCurveTool,
# Wallet tools (2)
DebankPreExecTxTool,
DebankExplainTxTool,
# Protocol tools (5)
DebankProtocolTool,
DebankProtocolListTool,
DebankProtocolAllListTool,
DebankAppProtocolListTool,
DebankPoolTool,
)
# Register chain tools
api.register_tool(DebankChainListTool())
api.register_tool(DebankChainTool())
api.register_tool(DebankGasMarketTool())
# Register token tools
api.register_tool(DebankTokenTool())
api.register_tool(DebankTokenHistoryPriceTool())
api.register_tool(DebankTokenListByIdsTool())
api.register_tool(DebankTokenTopHoldersTool())
# Register user balance tools
api.register_tool(DebankUserTotalBalanceTool())
api.register_tool(DebankUserTokenListTool())
api.register_tool(DebankUserAllTokenListTool())
# Register user history tools
api.register_tool(DebankUserHistoryListTool())
api.register_tool(DebankUserAllHistoryListTool())
# Register user protocol tools
api.register_tool(DebankUserSimpleProtocolListTool())
api.register_tool(DebankUserAllSimpleProtocolListTool())
api.register_tool(DebankUserComplexProtocolListTool())
api.register_tool(DebankUserAllComplexProtocolListTool())
api.register_tool(DebankUserComplexAppListTool())
# Register user NFT tools
api.register_tool(DebankUserNftListTool())
api.register_tool(DebankUserAllNftListTool())
# Register user misc tools
api.register_tool(DebankUserChainBalanceTool())
api.register_tool(DebankUserTokenTool())
api.register_tool(DebankUserProtocolTool())
api.register_tool(DebankUserUsedChainListTool())
api.register_tool(DebankUserTokenAuthorizedListTool())
api.register_tool(DebankUserNftAuthorizedListTool())
api.register_tool(DebankUserChainNetCurveTool())
api.register_tool(DebankUserTotalNetCurveTool())
# Register wallet tools
api.register_tool(DebankPreExecTxTool())
api.register_tool(DebankExplainTxTool())
# Register protocol tools
api.register_tool(DebankProtocolTool())
api.register_tool(DebankProtocolListTool())
api.register_tool(DebankProtocolAllListTool())
api.register_tool(DebankAppProtocolListTool())
api.register_tool(DebankPoolTool())
registered.extend([
# Chain (3)
"db_chain_list",
"db_chain",
"db_gas_market",
# Token (4)
"db_token",
"db_token_history_price",
"db_token_list_by_ids",
"db_token_top_holders",
# User Balance (3)
"db_user_total_balance",
"db_user_token_list",
"db_user_all_token_list",
# User History (2)
"db_user_history_list",
"db_user_all_history_list",
# User Protocol (5)
"db_user_simple_protocol_list",
"db_user_all_simple_protocol_list",
"db_user_complex_protocol_list",
"db_user_all_complex_protocol_list",
"db_user_complex_app_list",
# User NFT (2)
"db_user_nft_list",
"db_user_all_nft_list",
# User Misc (8)
"db_user_chain_balance",
"db_user_token",
"db_user_protocol",
"db_user_used_chain_list",
"db_user_token_authorized_list",
"db_user_nft_authorized_list",
"db_user_chain_net_curve",
"db_user_total_net_curve",
# Wallet (2)
"db_pre_exec_tx",
"db_explain_tx",
# Protocol (5)
"db_protocol",
"db_protocol_list",
"db_protocol_all_list",
"db_app_protocol_list",
"db_pool",
])
logger.info("Registered DeBank tools (34 tools)")
except Exception as e:
logger.warning(f"Failed to load DeBank tools: {e}")
return registered
# Extension metadata
EXTENSION_INFO = {
"name": "debank",
"version": "1.0.0",
"description": "DeBank blockchain data tools",
"tools": [
# Chain (3)
"db_chain_list",
"db_chain",
"db_gas_market",
# Token (4)
"db_token",
"db_token_history_price",
"db_token_list_by_ids",
"db_token_top_holders",
# User Balance (3)
"db_user_total_balance",
"db_user_token_list",
"db_user_all_token_list",
# User History (2)
"db_user_history_list",
"db_user_all_history_list",
# User Protocol (5)
"db_user_simple_protocol_list",
"db_user_all_simple_protocol_list",
"db_user_complex_protocol_list",
"db_user_all_complex_protocol_list",
"db_user_complex_app_list",
# User NFT (2)
"db_user_nft_list",
"db_user_all_nft_list",
# User Misc (8)
"db_user_chain_balance",
"db_user_token",
"db_user_protocol",
"db_user_used_chain_list",
"db_user_token_authorized_list",
"db_user_nft_authorized_list",
"db_user_chain_net_curve",
"db_user_total_net_curve",
# Wallet (2)
"db_pre_exec_tx",
"db_explain_tx",
# Protocol (5)
"db_protocol",
"db_protocol_list",
"db_protocol_all_list",
"db_app_protocol_list",
"db_pool",
],
"env_vars": [
"DEBANK_API_KEY",
],
}
"""
DeBank Tool Wrappers
Wraps tools from /tools/debank/ for use in Agent framework.
Provides blockchain data, user portfolios, DeFi positions, and transaction simulation.
"""
import asyncio
import logging
from typing import Any, Dict, List, Optional
from core.tool import BaseTool, ToolContext, ToolResult
logger = logging.getLogger(__name__)
# Import tools from local tools directory
try:
from .tools.chain import (
get_chain_list,
get_chain,
get_gas_market,
)
from .tools.token import (
get_token,
get_token_history_price,
get_token_list_by_ids,
get_token_top_holders,
)
from .tools.user import (
get_user_total_balance,
get_user_token_list,
get_user_all_token_list,
get_user_history_list,
get_user_all_history_list,
get_user_simple_protocol_list,
get_user_all_simple_protocol_list,
get_user_complex_protocol_list,
get_user_all_complex_protocol_list,
get_user_complex_app_list,
get_user_nft_list,
get_user_all_nft_list,
get_user_chain_balance,
get_user_token,
get_user_protocol,
get_user_used_chain_list,
get_user_token_authorized_list,
get_user_nft_authorized_list,
get_user_chain_net_curve,
get_user_total_net_curve,
)
from .tools.wallet import (
pre_exec_tx,
explain_tx,
)
from .tools.protocol import (
get_protocol,
get_protocol_list,
get_protocol_all_list,
get_app_protocol_list,
get_pool,
)
DEBANK_AVAILABLE = True
except ImportError as e:
logger.warning(f"DeBank tools not available: {e}")
DEBANK_AVAILABLE = False
# ==================== Chain Tools ====================
class DebankChainListTool(BaseTool):
"""Get list of all supported chains."""
@property
def name(self) -> str:
return "db_chain_list"
@property
def description(self) -> str:
return "Get the list of all chains supported by DeBank."
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_chain_list)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankChainTool(BaseTool):
"""Get details of a specific chain."""
@property
def name(self) -> str:
return "db_chain"
@property
def description(self) -> str:
return "Get details of a specific blockchain by chain ID."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {
"type": "string",
"description": "Chain identifier (eth, bsc, polygon, etc.)"
}
},
"required": ["chain_id"]
}
async def execute(self, ctx: ToolContext, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_chain, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankGasMarketTool(BaseTool):
"""Get gas prices for a chain."""
@property
def name(self) -> str:
return "db_gas_market"
@property
def description(self) -> str:
return "Get current gas prices for a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {
"type": "string",
"description": "Chain identifier"
}
},
"required": ["chain_id"]
}
async def execute(self, ctx: ToolContext, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_gas_market, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Token Tools ====================
class DebankTokenTool(BaseTool):
"""Get token details."""
@property
def name(self) -> str:
return "db_token"
@property
def description(self) -> str:
return "Get token details including symbol, name, decimals, and price."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {"type": "string", "description": "Chain identifier"},
"token_id": {"type": "string", "description": "Token contract address"}
},
"required": ["chain_id", "token_id"]
}
async def execute(self, ctx: ToolContext, chain_id: str, token_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_token, chain_id, token_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankTokenHistoryPriceTool(BaseTool):
"""Get token price history."""
@property
def name(self) -> str:
return "db_token_history_price"
@property
def description(self) -> str:
return "Get historical price data for a token."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {"type": "string", "description": "Chain identifier"},
"token_id": {"type": "string", "description": "Token contract address"},
"start_time": {"type": "integer", "description": "Start timestamp (Unix)"},
"end_time": {"type": "integer", "description": "End timestamp (Unix, optional)"}
},
"required": ["chain_id", "token_id", "start_time"]
}
async def execute(
self,
ctx: ToolContext,
chain_id: str,
token_id: str,
start_time: int,
end_time: Optional[int] = None
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(
get_token_history_price, chain_id, token_id, start_time, end_time
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankTokenListByIdsTool(BaseTool):
"""Batch fetch multiple tokens."""
@property
def name(self) -> str:
return "db_token_list_by_ids"
@property
def description(self) -> str:
return "Batch fetch multiple tokens on a chain by their addresses."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {"type": "string", "description": "Chain identifier"},
"token_ids": {
"type": "array",
"items": {"type": "string"},
"description": "List of token contract addresses"
}
},
"required": ["chain_id", "token_ids"]
}
async def execute(self, ctx: ToolContext, chain_id: str, token_ids: List[str]) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_token_list_by_ids, chain_id, token_ids)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankTokenTopHoldersTool(BaseTool):
"""Get top holders of a token."""
@property
def name(self) -> str:
return "db_token_top_holders"
@property
def description(self) -> str:
return "Get top holders of a token on a chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {"type": "string", "description": "Chain identifier"},
"token_id": {"type": "string", "description": "Token contract address"},
"start": {"type": "integer", "description": "Start index for pagination", "default": 0}
},
"required": ["chain_id", "token_id"]
}
async def execute(
self,
ctx: ToolContext,
chain_id: str,
token_id: str,
start: int = 0
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_token_top_holders, chain_id, token_id, start)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== User Balance Tools ====================
class DebankUserTotalBalanceTool(BaseTool):
"""Get user total balance across all chains."""
@property
def name(self) -> str:
return "db_user_total_balance"
@property
def description(self) -> str:
return "Get user's total portfolio balance across all supported chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address (0x...)"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_total_balance, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserTokenListTool(BaseTool):
"""Get user token list on a chain."""
@property
def name(self) -> str:
return "db_user_token_list"
@property
def description(self) -> str:
return "Get user's token balances on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"is_all": {"type": "boolean", "description": "Include zero balances", "default": False}
},
"required": ["user_addr", "chain_id"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
is_all: Optional[bool] = None
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_token_list, user_addr, chain_id, is_all)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserAllTokenListTool(BaseTool):
"""Get user token list on all chains."""
@property
def name(self) -> str:
return "db_user_all_token_list"
@property
def description(self) -> str:
return "Get user's token balances across all supported chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"is_all": {"type": "boolean", "description": "Include zero balances"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str, is_all: Optional[bool] = None) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_all_token_list, user_addr, is_all)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== User History Tools ====================
class DebankUserHistoryListTool(BaseTool):
"""Get user transaction history on a chain."""
@property
def name(self) -> str:
return "db_user_history_list"
@property
def description(self) -> str:
return "Get user's transaction history on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"start_time": {"type": "integer", "description": "Start timestamp (Unix)"},
"page_count": {"type": "integer", "description": "Number of records (max 20)"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
start_time: Optional[int] = None,
page_count: Optional[int] = None
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(
get_user_history_list, user_addr, chain_id, start_time, page_count
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserAllHistoryListTool(BaseTool):
"""Get user transaction history on all chains."""
@property
def name(self) -> str:
return "db_user_all_history_list"
@property
def description(self) -> str:
return "Get user's transaction history across all supported chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"start_time": {"type": "integer", "description": "Start timestamp"},
"page_count": {"type": "integer", "description": "Number of records (max 20)"}
},
"required": ["user_addr"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
start_time: Optional[int] = None,
page_count: Optional[int] = None
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(
get_user_all_history_list, user_addr, start_time, page_count
)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== User Protocol Tools ====================
class DebankUserSimpleProtocolListTool(BaseTool):
"""Get user simple protocol list on a chain."""
@property
def name(self) -> str:
return "db_user_simple_protocol_list"
@property
def description(self) -> str:
return "Get user's simple protocol balances on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_simple_protocol_list, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserAllSimpleProtocolListTool(BaseTool):
"""Get user simple protocol list on all chains."""
@property
def name(self) -> str:
return "db_user_all_simple_protocol_list"
@property
def description(self) -> str:
return "Get user's simple protocol balances across all chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_all_simple_protocol_list, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserComplexProtocolListTool(BaseTool):
"""Get user detailed protocol positions on a chain."""
@property
def name(self) -> str:
return "db_user_complex_protocol_list"
@property
def description(self) -> str:
return "Get user's detailed protocol positions on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_complex_protocol_list, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserAllComplexProtocolListTool(BaseTool):
"""Get user detailed protocol positions on all chains."""
@property
def name(self) -> str:
return "db_user_all_complex_protocol_list"
@property
def description(self) -> str:
return "Get user's detailed protocol positions across all chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_all_complex_protocol_list, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserComplexAppListTool(BaseTool):
"""Get user app-chain protocol positions."""
@property
def name(self) -> str:
return "db_user_complex_app_list"
@property
def description(self) -> str:
return "Get user's detailed positions on app-chain protocols."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_complex_app_list, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== User NFT Tools ====================
class DebankUserNftListTool(BaseTool):
"""Get user NFT list on a chain."""
@property
def name(self) -> str:
return "db_user_nft_list"
@property
def description(self) -> str:
return "Get user's NFT collections on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"is_all": {"type": "boolean", "description": "Include all NFTs"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
is_all: Optional[bool] = None
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_nft_list, user_addr, chain_id, is_all)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserAllNftListTool(BaseTool):
"""Get user NFT list on all chains."""
@property
def name(self) -> str:
return "db_user_all_nft_list"
@property
def description(self) -> str:
return "Get user's NFT collections across all chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"is_all": {"type": "boolean", "description": "Include all NFTs"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str, is_all: Optional[bool] = None) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_all_nft_list, user_addr, is_all)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== User Misc Tools ====================
class DebankUserChainBalanceTool(BaseTool):
"""Get user balance on a specific chain."""
@property
def name(self) -> str:
return "db_user_chain_balance"
@property
def description(self) -> str:
return "Get user's total balance on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_chain_balance, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserTokenTool(BaseTool):
"""Get user balance of a specific token."""
@property
def name(self) -> str:
return "db_user_token"
@property
def description(self) -> str:
return "Get user's balance of a specific token."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"token_id": {"type": "string", "description": "Token contract address"}
},
"required": ["user_addr", "chain_id", "token_id"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
token_id: str
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_token, user_addr, chain_id, token_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserProtocolTool(BaseTool):
"""Get user realtime portfolio in a protocol."""
@property
def name(self) -> str:
return "db_user_protocol"
@property
def description(self) -> str:
return "Get user's realtime portfolio in a specific protocol."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"protocol_id": {"type": "string", "description": "Protocol identifier"}
},
"required": ["user_addr", "protocol_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, protocol_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_protocol, user_addr, protocol_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserUsedChainListTool(BaseTool):
"""Get list of chains used by user."""
@property
def name(self) -> str:
return "db_user_used_chain_list"
@property
def description(self) -> str:
return "Get list of chains the user has activity on."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_used_chain_list, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserTokenAuthorizedListTool(BaseTool):
"""Get user token authorization list."""
@property
def name(self) -> str:
return "db_user_token_authorized_list"
@property
def description(self) -> str:
return "Get user's current token approvals/authorizations on a chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_token_authorized_list, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserNftAuthorizedListTool(BaseTool):
"""Get user NFT authorization list."""
@property
def name(self) -> str:
return "db_user_nft_authorized_list"
@property
def description(self) -> str:
return "Get user's current NFT approvals/authorizations on a chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_nft_authorized_list, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserChainNetCurveTool(BaseTool):
"""Get user 24h net curve on a chain."""
@property
def name(self) -> str:
return "db_user_chain_net_curve"
@property
def description(self) -> str:
return "Get user's 24-hour net worth curve on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["user_addr", "chain_id"]
}
async def execute(self, ctx: ToolContext, user_addr: str, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_chain_net_curve, user_addr, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankUserTotalNetCurveTool(BaseTool):
"""Get user 24h net curve on all chains."""
@property
def name(self) -> str:
return "db_user_total_net_curve"
@property
def description(self) -> str:
return "Get user's 24-hour total net worth curve across all chains."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"}
},
"required": ["user_addr"]
}
async def execute(self, ctx: ToolContext, user_addr: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_user_total_net_curve, user_addr)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Wallet Tools ====================
class DebankPreExecTxTool(BaseTool):
"""Enhanced pre-execute transaction."""
@property
def name(self) -> str:
return "db_pre_exec_tx"
@property
def description(self) -> str:
return "Simulate a transaction before sending it to the blockchain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"tx": {
"type": "object",
"description": "Transaction object with from, to, value, data fields"
}
},
"required": ["user_addr", "chain_id", "tx"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
tx: Dict[str, Any]
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(pre_exec_tx, user_addr, chain_id, tx)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankExplainTxTool(BaseTool):
"""Explain transaction."""
@property
def name(self) -> str:
return "db_explain_tx"
@property
def description(self) -> str:
return "Get human-readable explanation of what a transaction does."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"user_addr": {"type": "string", "description": "User wallet address"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"tx": {
"type": "object",
"description": "Transaction object with from, to, value, data fields"
}
},
"required": ["user_addr", "chain_id", "tx"]
}
async def execute(
self,
ctx: ToolContext,
user_addr: str,
chain_id: str,
tx: Dict[str, Any]
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(explain_tx, user_addr, chain_id, tx)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
# ==================== Protocol Tools ====================
class DebankProtocolTool(BaseTool):
"""Get protocol details."""
@property
def name(self) -> str:
return "db_protocol"
@property
def description(self) -> str:
return "Get details of a DeFi protocol."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"protocol_id": {"type": "string", "description": "Protocol identifier (e.g., uniswap, aave)"}
},
"required": ["protocol_id"]
}
async def execute(self, ctx: ToolContext, protocol_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_protocol, protocol_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankProtocolListTool(BaseTool):
"""Get protocols on a chain."""
@property
def name(self) -> str:
return "db_protocol_list"
@property
def description(self) -> str:
return "Get list of protocols on a specific chain."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"chain_id": {"type": "string", "description": "Chain identifier"}
},
"required": ["chain_id"]
}
async def execute(self, ctx: ToolContext, chain_id: str) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_protocol_list, chain_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankProtocolAllListTool(BaseTool):
"""Get all protocols across all chains."""
@property
def name(self) -> str:
return "db_protocol_all_list"
@property
def description(self) -> str:
return "Get list of all protocols across all supported chains."
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_protocol_all_list)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankAppProtocolListTool(BaseTool):
"""Get all app-protocols."""
@property
def name(self) -> str:
return "db_app_protocol_list"
@property
def description(self) -> str:
return "Get list of all app-chain protocols."
@property
def parameters(self) -> dict:
return {"type": "object", "properties": {}}
async def execute(self, ctx: ToolContext) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_app_protocol_list)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
class DebankPoolTool(BaseTool):
"""Get pool details."""
@property
def name(self) -> str:
return "db_pool"
@property
def description(self) -> str:
return "Get details of a DeFi pool."
@property
def parameters(self) -> dict:
return {
"type": "object",
"properties": {
"protocol_id": {"type": "string", "description": "Protocol identifier"},
"chain_id": {"type": "string", "description": "Chain identifier"},
"pool_id": {"type": "string", "description": "Pool identifier (contract address)"}
},
"required": ["protocol_id", "chain_id", "pool_id"]
}
async def execute(
self,
ctx: ToolContext,
protocol_id: str,
chain_id: str,
pool_id: str
) -> ToolResult:
if not DEBANK_AVAILABLE:
return ToolResult(success=False, output=None, error="DeBank tools not available")
try:
result = await asyncio.to_thread(get_pool, protocol_id, chain_id, pool_id)
return ToolResult(success=True, output=result)
except Exception as e:
return ToolResult(success=False, output=None, error=str(e))
"""
DeBank skill exports — script-mode skill.
Usage from a bash block:
python3 - <<'EOF'
import sys
sys.path.insert(0, "/data/workspace/skills/debank")
from exports import db_chain_list, db_user_total_balance
print(db_chain_list())
EOF
IMPORTANT NOTE on imports:
This skill's tools/ contains files named token.py, chain.py, wallet.py,
user.py — several would shadow Python stdlib modules if we naively put
tools/ on sys.path. Specifically `import token` triggers a circular
import via stdlib `tokenize`.
Strategy: load tools/utils.py manually first (so its symbols are
discoverable), then load each module by file path via importlib. This
fully bypasses sys.path-based `import` resolution and avoids stdlib
shadowing entirely.
For tools/*.py that internally do `from utils import ...`, we register
the loaded utils module under sys.modules['utils'] BEFORE loading any
other tool, so their bare `from utils import ...` resolves to our copy
rather than failing or hitting some other utils on the path.
"""
import os
import sys
import importlib.util
_TOOLS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tools")
def _load(modname, register_as=None):
"""Load tools/<modname>.py and optionally register in sys.modules."""
path = os.path.join(_TOOLS_DIR, f"{modname}.py")
spec = importlib.util.spec_from_file_location(
register_as or f"_debank_{modname}", path
)
mod = importlib.util.module_from_spec(spec)
if register_as:
# Register first so `from <register_as> import ...` works even
# while this module is still being executed (avoids cycles).
sys.modules[register_as] = mod
spec.loader.exec_module(mod)
return mod
# Step 1: load utils first and register under bare name 'utils' so the
# subsequent tools/*.py files can do `from utils import debank_api_request`.
_utils = _load("utils", register_as="utils")
debank_api_request = _utils.debank_api_request
validate_chain_id = _utils.validate_chain_id
# Step 2: load each tool module. `_debank_*` namespace prevents stdlib
# `token` from being shadowed.
_chain = _load("chain")
_token = _load("token")
_user = _load("user")
_protocol = _load("protocol")
_wallet = _load("wallet")
# --- Chain ---
def db_chain_list():
"""Get list of supported chains."""
return _chain.get_chain_list()
def db_chain(chain_id):
"""Get details of a specific chain."""
return _chain.get_chain(chain_id=chain_id)
def db_gas_market(chain_id):
"""Get gas prices for a chain."""
return _chain.get_gas_market(chain_id=chain_id)
# --- Token ---
def db_token(chain_id, token_id):
"""Get token details."""
return _token.get_token(chain_id=chain_id, token_id=token_id)
def db_token_history_price(chain_id, token_id, start_time, end_time=None):
"""Get token historical price."""
return _token.get_token_history_price(chain_id=chain_id, token_id=token_id, start_time=start_time, end_time=end_time)
def db_token_list_by_ids(chain_id, token_ids):
"""Batch fetch multiple tokens on a chain."""
return _token.get_token_list_by_ids(chain_id=chain_id, token_ids=token_ids)
def db_token_top_holders(chain_id, token_id, start=0):
"""Get top holders of a token."""
return _token.get_token_top_holders(chain_id=chain_id, token_id=token_id, start=start)
# --- User ---
def db_user_total_balance(user_addr):
return _user.get_user_total_balance(user_addr=user_addr)
def db_user_token_list(user_addr, chain_id, is_all=None):
return _user.get_user_token_list(user_addr=user_addr, chain_id=chain_id, is_all=is_all)
def db_user_all_token_list(user_addr, is_all=None):
return _user.get_user_all_token_list(user_addr=user_addr, is_all=is_all)
def db_user_history_list(user_addr, chain_id, start_time=None, page_count=None):
return _user.get_user_history_list(user_addr=user_addr, chain_id=chain_id, start_time=start_time, page_count=page_count)
def db_user_all_history_list(user_addr, start_time=None, page_count=None):
return _user.get_user_all_history_list(user_addr=user_addr, start_time=start_time, page_count=page_count)
def db_user_simple_protocol_list(user_addr, chain_id):
return _user.get_user_simple_protocol_list(user_addr=user_addr, chain_id=chain_id)
def db_user_all_simple_protocol_list(user_addr):
return _user.get_user_all_simple_protocol_list(user_addr=user_addr)
def db_user_complex_protocol_list(user_addr, chain_id):
return _user.get_user_complex_protocol_list(user_addr=user_addr, chain_id=chain_id)
def db_user_all_complex_protocol_list(user_addr):
return _user.get_user_all_complex_protocol_list(user_addr=user_addr)
def db_user_complex_app_list(user_addr):
return _user.get_user_complex_app_list(user_addr=user_addr)
def db_user_nft_list(user_addr, chain_id, is_all=None):
return _user.get_user_nft_list(user_addr=user_addr, chain_id=chain_id, is_all=is_all)
def db_user_all_nft_list(user_addr, is_all=None):
return _user.get_user_all_nft_list(user_addr=user_addr, is_all=is_all)
def db_user_chain_balance(user_addr, chain_id):
return _user.get_user_chain_balance(user_addr=user_addr, chain_id=chain_id)
def db_user_token(user_addr, chain_id, token_id):
return _user.get_user_token(user_addr=user_addr, chain_id=chain_id, token_id=token_id)
def db_user_protocol(user_addr, protocol_id):
return _user.get_user_protocol(user_addr=user_addr, protocol_id=protocol_id)
def db_user_used_chain_list(user_addr):
return _user.get_user_used_chain_list(user_addr=user_addr)
def db_user_token_authorized_list(user_addr, chain_id):
return _user.get_user_token_authorized_list(user_addr=user_addr, chain_id=chain_id)
def db_user_nft_authorized_list(user_addr, chain_id):
return _user.get_user_nft_authorized_list(user_addr=user_addr, chain_id=chain_id)
def db_user_chain_net_curve(user_addr, chain_id):
return _user.get_user_chain_net_curve(user_addr=user_addr, chain_id=chain_id)
def db_user_total_net_curve(user_addr):
return _user.get_user_total_net_curve(user_addr=user_addr)
# --- Protocol ---
def db_protocol(protocol_id):
return _protocol.get_protocol(protocol_id=protocol_id)
def db_protocol_list(chain_id):
return _protocol.get_protocol_list(chain_id=chain_id)
def db_protocol_all_list():
return _protocol.get_protocol_all_list()
def db_app_protocol_list():
return _protocol.get_app_protocol_list()
def db_pool(protocol_id, chain_id, pool_id):
return _protocol.get_pool(protocol_id=protocol_id, chain_id=chain_id, pool_id=pool_id)
# --- Wallet / Tx ---
def db_pre_exec_tx(user_addr, chain_id, tx):
return _wallet.pre_exec_tx(user_addr=user_addr, chain_id=chain_id, tx=tx)
def db_explain_tx(user_addr, chain_id, tx):
return _wallet.explain_tx(user_addr=user_addr, chain_id=chain_id, tx=tx)
# DeBank Tools Module
#!/usr/bin/env python3
"""
DeBank Chain API Tools
Get information about supported blockchains.
"""
from typing import Dict, Any
try:
from .utils import debank_api_request, validate_chain_id
except ImportError:
from utils import debank_api_request, validate_chain_id
def get_chain_list() -> Dict[str, Any]:
"""
Get the list of current support chains.
Returns:
Dict with list of supported chains and their metadata
Example:
>>> chains = get_chain_list()
>>> print(chains)
"""
return debank_api_request("/v1/chain/list")
def get_chain(chain_id: str) -> Dict[str, Any]:
"""
Get details of a specific chain.
Args:
chain_id: Chain identifier (e.g., "eth", "bsc", "polygon")
Returns:
Dict with chain details including name, native token, etc.
Example:
>>> chain = get_chain("eth")
>>> print(chain)
"""
chain_id = validate_chain_id(chain_id)
params = {"id": chain_id}
return debank_api_request("/v1/chain", params=params)
def get_gas_market(chain_id: str) -> Dict[str, Any]:
"""
Get gas prices for a specific chain.
Args:
chain_id: Chain identifier (e.g., "eth", "bsc", "polygon")
Returns:
Dict with gas market data including slow, normal, fast, and rapid prices
Example:
>>> gas = get_gas_market("eth")
>>> print(f"Fast gas: {gas['fast']}")
"""
chain_id = validate_chain_id(chain_id)
params = {"chain_id": chain_id}
return debank_api_request("/v1/wallet/gas_market", params=params)
#!/usr/bin/env python3
"""
DeBank Protocol API Tools
Get DeFi protocol and pool information.
"""
from typing import Dict, Any
try:
from .utils import debank_api_request, validate_chain_id
except ImportError:
from utils import debank_api_request, validate_chain_id
def get_protocol(protocol_id: str) -> Dict[str, Any]:
"""
Get details of a protocol.
Args:
protocol_id: Protocol identifier (e.g., "uniswap", "aave", "compound")
Returns:
Dict with protocol details including name, logo, chains, TVL
Example:
>>> protocol = get_protocol("uniswap")
>>> print(f"{protocol['name']}: ${protocol['tvl']}")
"""
params = {"id": protocol_id}
return debank_api_request("/v1/protocol", params=params)
def get_protocol_list(chain_id: str) -> Dict[str, Any]:
"""
Get protocols of a chain.
Args:
chain_id: Chain identifier
Returns:
Dict with list of protocols on the chain
Example:
>>> protocols = get_protocol_list("eth")
"""
chain_id = validate_chain_id(chain_id)
params = {"chain_id": chain_id}
return debank_api_request("/v1/protocol/list", params=params)
def get_protocol_all_list() -> Dict[str, Any]:
"""
Get all protocols of supported chains.
Returns:
Dict with all protocols across all chains
Example:
>>> protocols = get_protocol_all_list()
"""
return debank_api_request("/v1/protocol/all_list")
def get_app_protocol_list() -> Dict[str, Any]:
"""
Get all app-protocols.
Returns:
Dict with app-chain protocols
Example:
>>> app_protocols = get_app_protocol_list()
"""
return debank_api_request("/v1/app_protocol/list")
def get_pool(
protocol_id: str,
chain_id: str,
pool_id: str
) -> Dict[str, Any]:
"""
Get details of a pool.
Args:
protocol_id: Protocol identifier
chain_id: Chain identifier
pool_id: Pool identifier (usually contract address)
Returns:
Dict with pool details including tokens, TVL, APY
Example:
>>> pool = get_pool("uniswap", "eth", "0x...")
>>> print(f"APY: {pool['apy']}%")
"""
chain_id = validate_chain_id(chain_id)
params = {
"protocol_id": protocol_id,
"chain_id": chain_id,
"id": pool_id
}
return debank_api_request("/v1/pool", params=params)
#!/usr/bin/env python3
"""
DeBank Token API Tools
Get token information, prices, and holder data.
"""
from typing import Dict, Any, Optional, List
try:
from .utils import debank_api_request, validate_chain_id
except ImportError:
from utils import debank_api_request, validate_chain_id
def get_token(chain_id: str, token_id: str) -> Dict[str, Any]:
"""
Get token details.
Args:
chain_id: Chain identifier (e.g., "eth", "bsc")
token_id: Token contract address
Returns:
Dict with token details including symbol, name, decimals, price
Example:
>>> token = get_token("eth", "0x6b175474e89094c44da98b954eedeac495271d0f")
>>> print(f"{token['symbol']}: ${token['price']}")
"""
chain_id = validate_chain_id(chain_id)
params = {
"chain_id": chain_id,
"id": token_id
}
return debank_api_request("/v1/token", params=params)
def get_token_history_price(
chain_id: str,
token_id: str,
start_time: int,
end_time: Optional[int] = None
) -> Dict[str, Any]:
"""
Get token history price.
Args:
chain_id: Chain identifier
token_id: Token contract address
start_time: Start timestamp (Unix timestamp in seconds)
end_time: End timestamp (Unix timestamp in seconds). If not provided, uses current time
Returns:
Dict with historical price data
Example:
>>> prices = get_token_history_price("eth", "0x...", 1640995200, 1672531200)
"""
chain_id = validate_chain_id(chain_id)
params = {
"chain_id": chain_id,
"id": token_id,
"start_time": start_time
}
if end_time is not None:
params["end_time"] = end_time
return debank_api_request("/v1/token/history_price", params=params)
def get_token_list_by_ids(chain_id: str, token_ids: List[str]) -> Dict[str, Any]:
"""
Batch fetch multiple tokens on a chain.
Args:
chain_id: Chain identifier
token_ids: List of token contract addresses
Returns:
Dict with token data for each requested token
Example:
>>> tokens = get_token_list_by_ids("eth", ["0x...", "0x..."])
"""
chain_id = validate_chain_id(chain_id)
params = {
"chain_id": chain_id,
"ids": ",".join(token_ids)
}
return debank_api_request("/v1/token/list_by_ids", params=params)
def get_token_top_holders(
chain_id: str,
token_id: str,
start: Optional[int] = 0
) -> Dict[str, Any]:
"""
Get top holders of token on a chain.
Args:
chain_id: Chain identifier
token_id: Token contract address
start: Start index for pagination (default: 0)
Returns:
Dict with top holders data
Example:
>>> holders = get_token_top_holders("eth", "0x...")
>>> print(f"Top holder: {holders[0]['address']}")
"""
chain_id = validate_chain_id(chain_id)
params = {
"chain_id": chain_id,
"id": token_id,
"start": start
}
return debank_api_request("/v1/token/top_holders", params=params)
#!/usr/bin/env python3
"""
DeBank User API Tools
Get user portfolio, balances, transactions, and DeFi positions.
"""
from typing import Dict, Any, Optional
try:
from .utils import debank_api_request, validate_address, validate_chain_id
except ImportError:
from utils import debank_api_request, validate_address, validate_chain_id
def get_user_total_balance(user_addr: str) -> Dict[str, Any]:
"""
Get user total balance on all supported chains.
Args:
user_addr: User wallet address
Returns:
Dict with total balance in USD
Example:
>>> balance = get_user_total_balance("0x...")
>>> print(f"Total: ${balance['total_usd_value']}")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/total_balance", params=params)
def get_user_token_list(
user_addr: str,
chain_id: str,
is_all: Optional[bool] = None
) -> Dict[str, Any]:
"""
Get user token balances on a chain.
Args:
user_addr: User wallet address
chain_id: Chain identifier
is_all: If true, return all tokens including zero balances
Returns:
Dict with token list and balances
Example:
>>> tokens = get_user_token_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
if is_all is not None:
params["is_all"] = is_all
return debank_api_request("/v1/user/token_list", params=params)
def get_user_all_token_list(
user_addr: str,
is_all: Optional[bool] = None
) -> Dict[str, Any]:
"""
Get user token balances on all supported chains.
Args:
user_addr: User wallet address
is_all: If true, return all tokens including zero balances
Returns:
Dict with token list across all chains
Example:
>>> tokens = get_user_all_token_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
if is_all is not None:
params["is_all"] = is_all
return debank_api_request("/v1/user/all_token_list", params=params)
def get_user_history_list(
user_addr: str,
chain_id: str,
start_time: Optional[int] = None,
page_count: Optional[int] = None
) -> Dict[str, Any]:
"""
Get user transaction history.
Args:
user_addr: User wallet address
chain_id: Chain identifier
start_time: Start timestamp for filtering (Unix timestamp)
page_count: Number of records per page (max 20)
Returns:
Dict with transaction history
Example:
>>> history = get_user_history_list("0x...", "eth", page_count=10)
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
if start_time is not None:
params["start_time"] = start_time
if page_count is not None:
params["page_count"] = min(page_count, 20)
return debank_api_request("/v1/user/history_list", params=params)
def get_user_all_history_list(
user_addr: str,
start_time: Optional[int] = None,
page_count: Optional[int] = None
) -> Dict[str, Any]:
"""
Get user transaction history on all supported chains.
Args:
user_addr: User wallet address
start_time: Start timestamp for filtering
page_count: Number of records per page (max 20)
Returns:
Dict with transaction history across all chains
Example:
>>> history = get_user_all_history_list("0x...", page_count=20)
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
if start_time is not None:
params["start_time"] = start_time
if page_count is not None:
params["page_count"] = min(page_count, 20)
return debank_api_request("/v1/user/all_history_list", params=params)
def get_user_simple_protocol_list(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get user balance on a chain in the protocol.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with simple protocol balances
Example:
>>> protocols = get_user_simple_protocol_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/simple_protocol_list", params=params)
def get_user_all_simple_protocol_list(user_addr: str) -> Dict[str, Any]:
"""
Get user balance on all supported chains in the protocol.
Args:
user_addr: User wallet address
Returns:
Dict with simple protocol balances across all chains
Example:
>>> protocols = get_user_all_simple_protocol_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/all_simple_protocol_list", params=params)
def get_user_complex_protocol_list(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get user detail portfolios on a chain in the protocol.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with detailed protocol positions
Example:
>>> positions = get_user_complex_protocol_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/complex_protocol_list", params=params)
def get_user_all_complex_protocol_list(user_addr: str) -> Dict[str, Any]:
"""
Get user detail portfolios on all supported chains in the protocol.
Args:
user_addr: User wallet address
Returns:
Dict with detailed protocol positions across all chains
Example:
>>> positions = get_user_all_complex_protocol_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/all_complex_protocol_list", params=params)
def get_user_complex_app_list(user_addr: str) -> Dict[str, Any]:
"""
Get user detail portfolios on all supported app-chain protocol.
Args:
user_addr: User wallet address
Returns:
Dict with app-chain protocol positions
Example:
>>> apps = get_user_complex_app_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/complex_app_list", params=params)
def get_user_nft_list(
user_addr: str,
chain_id: str,
is_all: Optional[bool] = None
) -> Dict[str, Any]:
"""
Get user nft list on a chain.
Args:
user_addr: User wallet address
chain_id: Chain identifier
is_all: If true, return all NFTs
Returns:
Dict with NFT list
Example:
>>> nfts = get_user_nft_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
if is_all is not None:
params["is_all"] = is_all
return debank_api_request("/v1/user/nft_list", params=params)
def get_user_all_nft_list(
user_addr: str,
is_all: Optional[bool] = None
) -> Dict[str, Any]:
"""
Get user nft list on all supported chains.
Args:
user_addr: User wallet address
is_all: If true, return all NFTs
Returns:
Dict with NFT list across all chains
Example:
>>> nfts = get_user_all_nft_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
if is_all is not None:
params["is_all"] = is_all
return debank_api_request("/v1/user/all_nft_list", params=params)
def get_user_chain_balance(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get the balance on a chain.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with chain balance
Example:
>>> balance = get_user_chain_balance("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/chain_balance", params=params)
def get_user_token(
user_addr: str,
chain_id: str,
token_id: str
) -> Dict[str, Any]:
"""
Get the balance of a specific token.
Args:
user_addr: User wallet address
chain_id: Chain identifier
token_id: Token contract address
Returns:
Dict with token balance
Example:
>>> token = get_user_token("0x...", "eth", "0x...")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id,
"token_id": token_id
}
return debank_api_request("/v1/user/token", params=params)
def get_user_protocol(
user_addr: str,
protocol_id: str
) -> Dict[str, Any]:
"""
Get user realtime portfolio in a protocol.
Args:
user_addr: User wallet address
protocol_id: Protocol identifier
Returns:
Dict with protocol portfolio
Example:
>>> protocol = get_user_protocol("0x...", "uniswap")
"""
user_addr = validate_address(user_addr)
params = {
"id": user_addr,
"protocol_id": protocol_id
}
return debank_api_request("/v1/user/protocol", params=params)
def get_user_used_chain_list(user_addr: str) -> Dict[str, Any]:
"""
Get the list of chains used by the user.
Args:
user_addr: User wallet address
Returns:
Dict with list of chains the user has activity on
Example:
>>> chains = get_user_used_chain_list("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/used_chain_list", params=params)
def get_user_token_authorized_list(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get user current token authorization list.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with authorized tokens/contracts
Example:
>>> auth = get_user_token_authorized_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/token_authorized_list", params=params)
def get_user_nft_authorized_list(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get user current nft authorization list.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with authorized NFT contracts
Example:
>>> auth = get_user_nft_authorized_list("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/nft_authorized_list", params=params)
def get_user_chain_net_curve(
user_addr: str,
chain_id: str
) -> Dict[str, Any]:
"""
Get user 24-hour net curve on a single chain.
Args:
user_addr: User wallet address
chain_id: Chain identifier
Returns:
Dict with 24h net worth curve data
Example:
>>> curve = get_user_chain_net_curve("0x...", "eth")
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"id": user_addr,
"chain_id": chain_id
}
return debank_api_request("/v1/user/chain_net_curve", params=params)
def get_user_total_net_curve(user_addr: str) -> Dict[str, Any]:
"""
Get user 24-hour net curve on all chains.
Args:
user_addr: User wallet address
Returns:
Dict with 24h total net worth curve across all chains
Example:
>>> curve = get_user_total_net_curve("0x...")
"""
user_addr = validate_address(user_addr)
params = {"id": user_addr}
return debank_api_request("/v1/user/total_net_curve", params=params)
#!/usr/bin/env python3
"""
DeBank API Utilities
This module provides utility functions for DeBank API tools including:
- API request helpers with authentication
- Input validation and normalization
- Error handling and retry logic
"""
import os
import time
from typing import Dict, Any, Optional
from dotenv import load_dotenv
import requests
from core.http_client import proxied_get, proxied_post
# Load environment variables
load_dotenv()
# DeBank API base URL
DEBANK_API_BASE = "https://pro-openapi.debank.com"
def get_debank_headers() -> Dict[str, str]:
"""
Get headers for DeBank API requests.
Returns:
Dict[str, str]: Headers including API key
Raises:
ValueError: If DEBANK_API_KEY is not set
"""
api_key = os.getenv("DEBANK_API_KEY")
if not api_key:
raise ValueError(
"DEBANK_API_KEY environment variable is required. "
"Get your API key from https://docs.cloud.debank.com/"
)
return {
"AccessKey": api_key,
"accept": "application/json"
}
def debank_api_request(
endpoint: str,
params: Optional[Dict[str, Any]] = None,
method: str = "GET",
max_retries: int = 3,
retry_delay: float = 1.0
) -> Dict[str, Any]:
"""
Make a request to DeBank API with retry logic.
Args:
endpoint: API endpoint path (e.g., "/v1/user/total_balance")
params: Query parameters
method: HTTP method (default: GET)
max_retries: Maximum number of retry attempts
retry_delay: Delay between retries in seconds
Returns:
Dict[str, Any]: API response data
Raises:
requests.RequestException: If API request fails after retries
"""
url = f"{DEBANK_API_BASE}{endpoint}"
headers = get_debank_headers()
for attempt in range(max_retries):
try:
if method == "GET":
response = proxied_get(url, headers=headers, params=params, timeout=30)
elif method == "POST":
response = proxied_post(url, headers=headers, json=params, timeout=30)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
if attempt == max_retries - 1:
raise requests.RequestException("Request timeout - DeBank API may be slow")
time.sleep(retry_delay)
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429: # Rate limit
if attempt == max_retries - 1:
raise requests.RequestException("Rate limit exceeded - please wait before retrying")
time.sleep(retry_delay * 2) # Longer delay for rate limits
elif e.response.status_code >= 500: # Server error
if attempt == max_retries - 1:
raise requests.RequestException(f"Server error: {e}")
time.sleep(retry_delay)
else:
raise requests.RequestException(f"HTTP error: {e}")
except requests.exceptions.ConnectionError:
if attempt == max_retries - 1:
raise requests.RequestException("Connection error - check internet connection")
time.sleep(retry_delay)
except Exception as e:
if attempt == max_retries - 1:
raise requests.RequestException(f"API request failed: {e}")
time.sleep(retry_delay)
raise requests.RequestException("Max retries exceeded")
def validate_address(address: str) -> str:
"""
Validate and normalize Ethereum address.
Args:
address: Ethereum address
Returns:
str: Normalized address (lowercase)
Raises:
ValueError: If address is invalid
"""
if not address or not isinstance(address, str):
raise ValueError("Address must be a non-empty string")
address = address.strip().lower()
if not address.startswith("0x"):
raise ValueError("Address must start with '0x'")
if len(address) != 42:
raise ValueError("Address must be 42 characters long (0x + 40 hex chars)")
# Check if valid hex
try:
int(address[2:], 16)
except ValueError:
raise ValueError("Address must contain only hexadecimal characters")
return address
def validate_chain_id(chain_id: str) -> str:
"""
Validate and normalize chain ID.
Args:
chain_id: Chain identifier
Returns:
str: Normalized chain ID (lowercase)
Raises:
ValueError: If chain_id is invalid
"""
if not chain_id or not isinstance(chain_id, str):
raise ValueError("Chain ID must be a non-empty string")
return chain_id.strip().lower()
def format_token_amount(amount: float, decimals: int) -> str:
"""
Format token amount with decimals.
Args:
amount: Raw token amount
decimals: Number of decimal places
Returns:
str: Formatted amount
"""
if decimals == 0:
return str(int(amount))
formatted = amount / (10 ** decimals)
return f"{formatted:.{min(decimals, 8)}f}"
def safe_get(data: Dict[str, Any], *keys, default=None) -> Any:
"""
Safely get nested dictionary values.
Args:
data: Dictionary to query
*keys: Sequence of keys to traverse
default: Default value if key path doesn't exist
Returns:
Value at key path or default
Example:
>>> safe_get({"a": {"b": {"c": 1}}}, "a", "b", "c")
1
>>> safe_get({"a": {"b": {}}}, "a", "b", "c", default=0)
0
"""
current = data
for key in keys:
if not isinstance(current, dict) or key not in current:
return default
current = current[key]
return current
#!/usr/bin/env python3
"""
DeBank Wallet API Tools
Transaction simulation and explanation.
"""
from typing import Dict, Any
try:
from .utils import debank_api_request, validate_address, validate_chain_id
except ImportError:
from utils import debank_api_request, validate_address, validate_chain_id
def pre_exec_tx(
user_addr: str,
chain_id: str,
tx: Dict[str, Any]
) -> Dict[str, Any]:
"""
Enhanced pre-execute transaction.
Simulates a transaction before sending it to the blockchain.
Args:
user_addr: User wallet address
chain_id: Chain identifier
tx: Transaction object with fields:
- from: Sender address
- to: Recipient address
- value: Amount in wei (hex or decimal)
- data: Transaction data (hex)
- gas: Gas limit (optional)
- gasPrice: Gas price (optional)
Returns:
Dict with simulation results including balance changes, gas estimates
Example:
>>> tx = {
... "from": "0x...",
... "to": "0x...",
... "value": "0x0",
... "data": "0x..."
... }
>>> result = pre_exec_tx("0x...", "eth", tx)
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"user_addr": user_addr,
"chain_id": chain_id,
"tx": tx
}
return debank_api_request("/v1/wallet/pre_exec_tx", params=params, method="POST")
def explain_tx(
user_addr: str,
chain_id: str,
tx: Dict[str, Any]
) -> Dict[str, Any]:
"""
Explain transaction.
Provides human-readable explanation of what a transaction does.
Args:
user_addr: User wallet address
chain_id: Chain identifier
tx: Transaction object with fields:
- from: Sender address
- to: Recipient address
- value: Amount in wei
- data: Transaction data (hex)
Returns:
Dict with transaction explanation
Example:
>>> tx = {
... "from": "0x...",
... "to": "0x...",
... "value": "0x0",
... "data": "0x..."
... }
>>> explanation = explain_tx("0x...", "eth", tx)
>>> print(explanation['description'])
"""
user_addr = validate_address(user_addr)
chain_id = validate_chain_id(chain_id)
params = {
"user_addr": user_addr,
"chain_id": chain_id,
"tx": tx
}
return debank_api_request("/v1/wallet/explain_tx", params=params, method="POST")