获取BNB/PancakeSwap最新上线代币的方案及报错解决咨询
获取BNB链/PancakeSwap最新上线代币的问题与解决方案
需求与当前方案
我想获取BNB链或PancakeSwap平台最新上线的代币名称,计划通过以下API组合实现:
- 调用BNB链的
eth_getBlockByNumberAPI获取最近区块中的交易列表,筛选合约创建交易; - 通过两种方式提取合约地址:
- 方式1:调用
eth_getTransactionReceiptAPI获取合约地址; - 方式2:判断交易的
to字段是否为None(认为是合约创建交易),并将blockHash当作代币地址;
- 方式1:调用
- 调用CoinGecko API获取代币名称、价格等详情。
当前代码如下:
import requests if __name__ == '__main__': get_latest_tokens_on_BNB() def get_latest_tokens_on_BNB (): API_KEY = "my_api_key" # step 1: get the list of recently created contracts latest_block_url = f'https://api.etherscan.io/v2/api?chainid=56&module=proxy&action=eth_getBlockByNumber&tag=latest&boolean=true&apikey={API_KEY}' response = requests.get(latest_block_url) latest_block_data = response.json() transactions = latest_block_data['result']['transactions'] for tx in transactions: # step 2: approach 1 transaction_receipt_url = f'https://api.etherscan.io/v2/api?chainid=56&module=proxy&action=eth_getTransactionReceipt&hash={tx["hash"]}&apikey={API_KEY}' transaction_response = requests.get(transaction_receipt_url) transaction_data = transaction_response.json() contractAddress = transaction_data['result']['contractAddress'] if contractAddress != None : # Contract creation token_id = get_token_id(contractAddress) if token_id: token_data = get_token_data(token_id) print(token_data) else: print("Token not found.") # # step 2: approach 2 (approach 1 and appproach 2 can't be activated in the same time!) # if tx['to'] is None: # Contract creation (Does this really show contract creation?) # contractAddress = tx['blockHash'] # Replace with your token address (I don't know why in the provided example blockHash was given as contract address!) # token_id = get_token_id(contractAddress) # # step 3: Use coingecko API to get more details about obtained address # if token_id: # token_data = get_token_data(token_id) # print(token_data) # else: # print("Token not found.") # else: # print('tx[to] is not None!') def get_token_id(token_address): url = 'https://api.coingecko.com/api/v3/coins/markets' params = { 'vs_currency': 'usd', 'order': 'market_cap_desc', 'per_page': 100, 'page': 1, 'sparkline': 'false' } response = requests.get(url, params=params) tokens = response.json() # Search for the token by address in returned tokens for token in tokens: if token['id'] == token_address: return token['id'] return None def get_token_data(token_id): url = f'https://api.coingecko.com/api/v3/coins/{token_id}' response = requests.get(url) return response.json()
遇到的问题
- 使用方式1时,报错:
{'jsonrpc': '2.0', 'id': 1, 'error': {'code': -32602, 'message': 'invalid argument 0: hex string has length 0, want 64 for common.Hash'}}
同时触发KeyError: 'result',因为返回的JSON中没有result字段。
- 使用方式2时,输出全是
tx[to] is not None!,没有找到合约创建交易。
我的疑问
- 这个方案是否适合获取最新上线代币?有没有更优的方案?
- 如果方案可行,如何解决上述报错?
解答
1. 方案适用性与更优方案
你的基础思路方向正确,但存在明显局限性,可优化空间很大:
- 当前方案的问题:
- 仅监控最新区块,容易错过合约创建交易;且BNB链单区块交易量大,多数是普通转账或非代币合约(如NFT、DEX合约),需要额外筛选BEP-20标准代币。
- CoinGecko的
coins/markets接口仅返回市值靠前的代币,新上线的代币基本不会出现在这里,无法通过该接口匹配地址。
- 更优方案:
- 用BscScan专用API:直接调用BscScan的
contract模块接口,可筛选最新创建的BEP-20代币,比手动解析区块更高效,还能直接获取代币基本信息。 - 监控PancakeSwap专属事件:监听PancakeSwap Factory合约的
PairCreated事件,能精准获取在该平台上线的新代币,避免全链监控的冗余。 - 用专业链上数据服务:比如DexScreener的新币追踪接口,这类服务已做好新币筛选和数据聚合,无需自己处理底层交易逻辑。
- 用BscScan专用API:直接调用BscScan的
2. 现有报错的解决方法
方式1的报错解决
报错核心原因:
- 混用Etherscan API处理BNB链请求,稳定性差;且未先筛选合约创建交易,直接对所有交易调用收据接口,导致大量无效请求;另外,普通交易的收据中没有
contractAddress字段,直接访问会触发KeyError。
修复步骤:
- 先筛选合约创建交易:合约创建交易的
to字段为空(None或空字符串),先判断再调用收据接口。 - 改用BscScan API:BNB链官方区块浏览器的API更适配链上数据,地址为
https://api.bscscan.com/api。 - 添加错误处理:捕获API返回的错误信息,避免程序崩溃。
修改后的方式1代码片段:
def get_latest_tokens_on_BNB (): API_KEY = "my_api_key" # 改用BscScan官方API latest_block_url = f'https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=latest&boolean=true&apikey={API_KEY}' response = requests.get(latest_block_url) latest_block_data = response.json() if 'result' not in latest_block_data: print("获取区块失败:", latest_block_data.get('error')) return transactions = latest_block_data['result']['transactions'] for tx in transactions: # 判断是否为合约创建交易:to字段为空 if tx['to'] is None or tx['to'] == "": transaction_receipt_url = f'https://api.bscscan.com/api?module=proxy&action=eth_getTransactionReceipt&hash={tx["hash"]}&apikey={API_KEY}' transaction_response = requests.get(transaction_receipt_url) transaction_data = transaction_response.json() # 处理API返回错误 if 'error' in transaction_data: print("获取收据失败:", transaction_data['error']) continue if 'result' not in transaction_data: continue contractAddress = transaction_data['result'].get('contractAddress') if contractAddress: print("找到新合约地址:", contractAddress) # 修正CoinGecko查询逻辑 token_id = get_token_id(contractAddress) if token_id: token_data = get_token_data(token_id) print(token_data) else: print("该代币未在CoinGecko收录")
方式2的错误修正
方式2的核心错误是把blockHash当作合约地址完全错误。合约创建交易的to字段为空,但合约地址只能从交易收据的contractAddress字段获取,blockHash是区块哈希,和合约地址无关。另外,BNB链返回的空to字段可能是字符串""而非None,需要同时判断。
修正后的方式2逻辑:
for tx in transactions: # 同时判断None和空字符串 if tx['to'] is None or tx['to'] == "": # 调用收据获取合约地址 transaction_receipt_url = f'https://api.bscscan.com/api?module=proxy&action=eth_getTransactionReceipt&hash={tx["hash"]}&apikey={API_KEY}' transaction_response = requests.get(transaction_receipt_url) transaction_data = transaction_response.json() if 'result' in transaction_data: contractAddress = transaction_data['result'].get('contractAddress') if contractAddress: print("找到新合约:", contractAddress) # 后续逻辑同方式1 else: print('不是合约创建交易')
CoinGecko查询逻辑修正
你当前的get_token_id函数逻辑错误:coins/markets返回的id是CoinGecko的内部代币ID(如binancecoin),不是合约地址。正确做法是调用CoinGecko的链上合约查询接口,直接通过BNB链合约地址获取代币信息。
修正后的get_token_id函数:
def get_token_id(token_address): # 直接查询BNB链合约对应的CoinGecko信息 url = f'https://api.coingecko.com/api/v3/coins/binance-smart-chain/contract/{token_address}' response = requests.get(url) if response.status_code == 200: token_data = response.json() return token_data.get('id') return None
内容的提问来源于stack exchange,提问作者user9805040
相关产品推荐
相关产品推荐

