使用Etherscan API计算ETH地址代币余额不符的问题求助
解决Etherscan API代币余额计算不符的问题
核心问题原因
Etherscan的代币交易接口会返回所有关联目标地址的代币转移记录,其中包含合约内部调用产生的转账(比如流动性挖矿、代币兑换场景下的系统转账),这类记录并非用户主动发起的收支操作,会干扰最终余额的计算。
过滤规则与实现方法
要得到正确余额,需过滤掉非用户主动收支的交易,可通过以下规则实现:
- 排除零地址交易:如果交易的
to字段是0x0000000000000000000000000000000000000000,通常是代币销毁操作,不计入余额。 - 区分用户主动交易:
- 仅当
from是目标地址、to为非合约地址时,判定为用户主动转出; - 仅当
to是目标地址、from为非合约地址时,判定为用户主动转入;
- 仅当
- 识别合约地址:通过Etherscan的
eth_getCode接口判断地址是否为合约,过滤合约发起的非主动转账。
Python代码示例
import requests API_KEY = "你的Etherscan API密钥" TARGET_ADDR = "0x4c8CFE078a5B989CeA4B330197246ceD82764c63" def get_token_transactions(): """获取目标地址的所有代币交易记录""" url = f"https://api.etherscan.io/api?module=account&action=tokentx&address={TARGET_ADDR}&apikey={API_KEY}" resp = requests.get(url) return resp.json()["result"] def is_contract(address): """判断地址是否为合约地址""" url = f"https://api.etherscan.io/api?module=proxy&action=eth_getCode&address={address}&tag=latest&apikey={API_KEY}" code = requests.get(url).json()["result"] return code != "0x" def calculate_correct_balance(transactions, target_token_symbol): """计算目标代币的正确余额""" balance = 0.0 target_addr_lower = TARGET_ADDR.lower() for tx in transactions: # 只处理目标代币的交易 if tx["tokenSymbol"] != target_token_symbol: continue tx_from = tx["from"].lower() tx_to = tx["to"].lower() value = int(tx["value"]) / 10 ** int(tx["tokenDecimal"]) # 过滤零地址交易 if tx_to == "0x0000000000000000000000000000000000000000": continue # 过滤合约发起的非主动转账 if (tx_from != target_addr_lower and is_contract(tx_from)) or (tx_to != target_addr_lower and is_contract(tx_to)): continue # 计算收支 if tx_to == target_addr_lower: balance += value elif tx_from == target_addr_lower: balance -= value return balance # 调用示例 all_transactions = get_token_transactions() # 替换为你要查询的代币符号(比如黄色标记交易对应的代币) correct_balance = calculate_correct_balance(all_transactions, "TARGET_TOKEN_SYMBOL") print(f"计算出的正确余额: {correct_balance}")
基准验证方法
直接调用Etherscan的tokenbalance接口获取当前实际余额,用于验证计算结果:
def get_actual_token_balance(token_contract_addr): """获取目标地址的代币实际余额""" url = f"https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress={token_contract_addr}&address={TARGET_ADDR}&tag=latest&apikey={API_KEY}" balance = int(requests.get(url).json()["result"]) / 10 ** 18 # 替换为对应代币的小数位数 return balance
内容的提问来源于stack exchange,提问作者Ivan Lisi
相关产品推荐
相关产品推荐

