You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取BNB/PancakeSwap最新上线代币的方案及报错解决咨询

获取BNB链/PancakeSwap最新上线代币的问题与解决方案

需求与当前方案

我想获取BNB链或PancakeSwap平台最新上线的代币名称,计划通过以下API组合实现:

  1. 调用BNB链的eth_getBlockByNumber API获取最近区块中的交易列表,筛选合约创建交易;
  2. 通过两种方式提取合约地址:
    • 方式1:调用eth_getTransactionReceipt API获取合约地址;
    • 方式2:判断交易的to字段是否为None(认为是合约创建交易),并将blockHash当作代币地址;
  3. 调用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. 这个方案是否适合获取最新上线代币?有没有更优的方案?
  2. 如果方案可行,如何解决上述报错?

解答

1. 方案适用性与更优方案

你的基础思路方向正确,但存在明显局限性,可优化空间很大:

  • 当前方案的问题:
    1. 仅监控最新区块,容易错过合约创建交易;且BNB链单区块交易量大,多数是普通转账或非代币合约(如NFT、DEX合约),需要额外筛选BEP-20标准代币。
    2. CoinGecko的coins/markets接口仅返回市值靠前的代币,新上线的代币基本不会出现在这里,无法通过该接口匹配地址。
  • 更优方案:
    • 用BscScan专用API:直接调用BscScan的contract模块接口,可筛选最新创建的BEP-20代币,比手动解析区块更高效,还能直接获取代币基本信息。
    • 监控PancakeSwap专属事件:监听PancakeSwap Factory合约的PairCreated事件,能精准获取在该平台上线的新代币,避免全链监控的冗余。
    • 用专业链上数据服务:比如DexScreener的新币追踪接口,这类服务已做好新币筛选和数据聚合,无需自己处理底层交易逻辑。

2. 现有报错的解决方法

方式1的报错解决

报错核心原因:

  • 混用Etherscan API处理BNB链请求,稳定性差;且未先筛选合约创建交易,直接对所有交易调用收据接口,导致大量无效请求;另外,普通交易的收据中没有contractAddress字段,直接访问会触发KeyError。

修复步骤:

  1. 先筛选合约创建交易:合约创建交易的to字段为空(None或空字符串),先判断再调用收据接口。
  2. 改用BscScan API:BNB链官方区块浏览器的API更适配链上数据,地址为https://api.bscscan.com/api。
  3. 添加错误处理:捕获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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 07:44:53