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

如何使用Web3j库调用ERC721合约的tokenURI()函数?

修复tokenURI调用失败的问题

代码中的核心问题

  • 未指定返回值类型:tokenURI返回字符串,但构造Function时未声明返回值类型,导致Web3j无法正确解码响应。
  • 响应值未解码:直接使用response.value拿到的是ABI编码后的原始数据,需要解码才能得到实际的URI字符串。
  • 参数初始化不明确:Uint256.DEFAULT等价于0,如果你的NFT tokenID不是0,需要传入正确的ID值。
  • WebSocket连接容错不足:连接失败后仅打印日志,没有明确的错误状态反馈。
  • 同步调用冗余:sendAsync().get()是阻塞式调用,改用send()更简洁高效。

修正后的代码

private fun getNFTMetadata(tokenId: Long) = viewModelScope.launch(Dispatchers.IO) {
    val web3j = createWeb3j() ?: run {
        state.value = "Web3j连接失败"
        return@launch
    }

    // 传入目标NFT的tokenID,替换成你需要查询的具体ID
    val inputParams = listOf(Uint256(tokenId))
    // 声明返回值类型为Solidity string对应的Utf8String
    val outputParams = listOf(Utf8String())

    val function = org.web3j.abi.datatypes.Function(
        "tokenURI",
        inputParams,
        outputParams
    )

    val encodedFunction = FunctionEncoder.encode(function)
    return try {
        val response = web3j.ethCall(
            Transaction.createEthCallTransaction(null, CONTRACT_ADDRESS, encodedFunction),
            DefaultBlockParameterName.LATEST
        ).send()

        if (!response.isStatusOK) {
            state.value = "调用失败: ${response.error.message}"
            return@launch
        }

        // 解码ABI编码的响应结果
        val decodedResults = FunctionDecoder.decodeFunctionResult(function, response.value)
        val tokenUri = decodedResults.first().value as String
        state.value = tokenUri
        
        // 拿到URI后可继续请求元数据(示例:HTTP GET获取JSON)
        // fetchNFTMetadata(tokenUri)
    } catch (e: Exception) {
        state.value = "调用异常: ${e.message}"
        e.printStackTrace()
    }
}

private fun createWeb3j(): Web3j? {
    return try {
        val webSocketService = WebSocketService(WEB_SOCKET_URL, true)
        webSocketService.connect()
        Web3j.build(webSocketService)
    } catch (e: ConnectException) {
        e.printStackTrace()
        null
    }
}

关键修改说明

  1. 声明返回值类型:构造Function时传入listOf(Utf8String()),让Web3j明确知道要解码字符串类型的返回值。
  2. 解码响应数据:通过FunctionDecoder.decodeFunctionResult解析ABI编码的原始响应,得到可读的URI字符串。
  3. 动态传入tokenID:将tokenID作为函数参数,方便查询任意ID的NFT。
  4. 完善错误处理:检查响应状态码、捕获异常,给状态赋值明确的错误提示,便于排查问题。
  5. 简化EthCall构造:静态调用tokenURI无需签名,createEthCallTransaction的from参数可传null。
  6. 连接失败反馈:Web3j创建失败时直接更新状态,避免无意义的后续执行。

后续操作

拿到tokenURI后,可通过HTTP请求(如OkHttp、Retrofit)获取对应的JSON元数据,从中提取图片URL、NFT属性等信息。

内容的提问来源于stack exchange,提问作者Vando

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:31:49