当前位置: 首页 > 知识库问答 >
问题:

在web3j中,如何为运行时发现的数组类型创建TypeReference?

冀嘉木
2023-03-14

我试图用web3j编写一个Java应用程序,它可以读取任意的abi文件,向用户显示AbiDefinitions列表,并让用户调用自己选择的常量函数。我如何计算下面的输出类型?

AbiDefinition functionDef = ...; // found at runtime  
List<Type> args = ...; // I know how to do this  
List<NamedType> outputs = functionDef.getOutputs(); // list of output parameters  
List<TypeReference<?>> outTypes = ????;  
Function function = new Function(functionDef.getName(), args, outTypes);  

TypeReference 类对泛型类型使用技巧,当泛型类型在源代码中硬编码时,这些技巧可以正常工作,如下所示:

new TypeReference.StaticArrayTypeReference< StaticArray< Int256>>(2){}  

这就是生成的合约包装器要做的。

对于简单类型,我可以这样做:

Class<Type> type = (Class<Type>)AbiTypes.getType(typeName);
TypeReference<?> typeRef = TypeReference.create(type);

对于“int256[2]”这样的数组类型,该怎么办?

共有1个答案

凤修为
2023-03-14

uniswapV2路由器

函数getAmountsOut(uint amountIn,address[] calldata path)外部视图返回(uint[]内存量)

package com.test;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.http.HttpService;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class main {
    private static String EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
    static Web3j web3j;
    static String usdt = "0x55d398326f99059fF775485246999027B3197955";
    static String weth = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
    static String pancakeRouter = "0x10ed43c718714eb63d5aa57b78b54704e256024e";

    public static void main(String[] args) throws IOException {
        web3j = Web3j.build(new HttpService("https://bsc-dataseed.binance.org/"));
        String s = web3j.netVersion().send().getNetVersion();
        System.out.println(s);
        List<BigInteger> list1 = getAmountsOut(usdt, weth);
        System.out.println("result::: ");
        for (BigInteger a : list1) {
            System.out.println(a);
        }
    }

    public static List<BigInteger> getAmountsOut(String tokenInAddr, String tokenOutAddr) {
        String methodName = "getAmountsOut";
        String fromAddr = EMPTY_ADDRESS;
        List<Type> inputParameters = new ArrayList<Type>();
        Uint256 inAmount = new Uint256(new BigInteger("1000000000000000000"));
        Address inAddr = new Address(tokenInAddr);
        Address outAddr = new Address(tokenOutAddr);
        DynamicArray<Address> addrArr = new DynamicArray<Address>(inAddr, outAddr);

        inputParameters.add(inAmount);
        inputParameters.add(addrArr);

        List<TypeReference<?>> outputParameters = new ArrayList<TypeReference<?>>();
        TypeReference<DynamicArray<Uint256>> oa = new TypeReference<DynamicArray<Uint256>>() {
        };
        outputParameters.add(oa);

        Function function = new Function(methodName, inputParameters, outputParameters);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(fromAddr, pancakeRouter, data);

        EthCall ethCall;
        try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
            List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            System.out.println(results);
            List<BigInteger> resultArr = new ArrayList<>();
            if (results.size() > 0) {
                for (Type tt : results) {
                    DynamicArray<Uint256> da = (DynamicArray<Uint256>) tt;
                    List<Uint256> lu = da.getValue();
                    if (lu.size() > 0) {
                        for (Uint256 n : lu) {
                            resultArr.add((BigInteger) n.getValue());
                        }
                    }
                }
                return resultArr;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
 类似资料:
  • 如何从web3j库中引用数组类型?我有一个契约函数,它返回访问该契约的人的地址数组。我想把这些作为数组放到java/kotlin项目中。这是代码-

  • 问题内容: 据我所知,反射包中没有类型发现机制,该机制希望您已经具有要检查的类型或值的实例。 还有 其他 方法可以发现正在运行的go包中的所有导出类型(尤其是结构)吗? 这是我希望拥有的(但不存在): 最终目标是能够发现满足特定条件的程序包的所有结构,然后能够实例化这些结构的新实例。 顺便说一句,识别类型的注册功能对于我的用例 不是 有效的方法。 无论您是否认为这是一个好主意,这就是为什么我想要这

  • 问题内容: 如何创建泛型类型的数组?通用方法如何工作?它返回通用数组的副本。因此可以创建通用数组。但是如何?怎么能写一个类似的方法呢? 问题答案: 如果需要在运行时创建它,则至少需要在此时知道类型,因此可以使用以下方法: where 是泛型类型,是的类,并且是初始大小。 这里的文件

  • 我正在使用grpc protobuf消息定义,并在Go中实现它们。 我的最终目标是让我的rpc在用户上检索一些json并返回带有可选嵌套消息的Message,用于解组json的子集。 使用此rpc: 假设如下: 我想返回一个消息,该消息仅包含“foo”、“bar”或两者,作为基于grpc请求的传入运行时参数的嵌套消息(目前,将是包含用于将json子设置为相应消息的消息名称的字符串列表,例如)。 给

  • 本文向大家介绍C#在运行时动态创建类型的实现方法,包括了C#在运行时动态创建类型的实现方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#在运行时动态创建类型的实现方法。是C#项目开发中很实用的技巧。分享给大家供大家参考。具体分析如下: 具体来说,C# 在运行时动态的创建类型是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型的。 主要功能代码如下: 希望本文所述

  • 问题内容: 在目标c中,我可以创建一个类数组并在方法中使用它 但是,swift没有“类”功能。返回类的元类型会导致错误 最后一行导致“致命错误:数组元素无法桥接到Objective-C” 如何在Swift中创建类数组? 问题答案: 显然,此问题已在Beta 3中修复,因此不再需要解决方法 我发现了一个纯粹的Swift hack: 先前的答案 我无法在Swift中以任何方式获取实例。似乎无法直接从转