All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.youchain.abi.FunctionReturnDecoder Maven / Gradle / Ivy

package cc.youchain.abi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cc.youchain.abi.datatypes.Array;
import cc.youchain.abi.datatypes.Bytes;
import cc.youchain.abi.datatypes.BytesType;
import cc.youchain.abi.datatypes.DynamicArray;
import cc.youchain.abi.datatypes.DynamicBytes;
import cc.youchain.abi.datatypes.StaticArray;
import cc.youchain.abi.datatypes.Type;
import cc.youchain.abi.datatypes.Utf8String;
import cc.youchain.abi.datatypes.generated.Bytes32;
import cc.youchain.utils.Numeric;
import cc.youchain.utils.Strings;

import static cc.youchain.abi.TypeDecoder.MAX_BYTE_LENGTH_FOR_HEX_STRING;

/**
 * Decodes values returned by function or event calls.
 */
public class FunctionReturnDecoder {

    private FunctionReturnDecoder() { }

    /**
     * Decode ABI encoded return values from smart contract function call.
     *
     * @param rawInput ABI encoded input
     * @param outputParameters list of return types as {@link TypeReference}
     * @return {@link List} of values returned by function, {@link Collections#emptyList()} if
     *         invalid response
     */
    public static List decode(
            String rawInput, List> outputParameters) {
        String input = Numeric.cleanHexPrefix(rawInput);

        if (Strings.isEmpty(input)) {
            return Collections.emptyList();
        } else {
            return build(input, outputParameters);
        }
    }

    /**
     * 

Decodes an indexed parameter associated with an event. Indexed parameters are individually * encoded, unlike non-indexed parameters which are encoded as per ABI-encoded function * parameters and return values.

* *

If any of the following types are indexed, the Keccak-256 hashes of the values are * returned instead. These are returned as a bytes32 value.

* *
    *
  • Arrays
  • *
  • Strings
  • *
  • Bytes
  • *
* *

See the * * Solidity documentation for further information.

* * @param rawInput ABI encoded input * @param typeReference of expected result type * @param type of TypeReference * @return the decode value */ @SuppressWarnings("unchecked") public static Type decodeIndexedValue( String rawInput, TypeReference typeReference) { String input = Numeric.cleanHexPrefix(rawInput); try { Class type = typeReference.getClassType(); if (Bytes.class.isAssignableFrom(type)) { return TypeDecoder.decodeBytes(input, (Class) Class.forName(type.getName())); } else if (Array.class.isAssignableFrom(type) || BytesType.class.isAssignableFrom(type) || Utf8String.class.isAssignableFrom(type)) { return TypeDecoder.decodeBytes(input, Bytes32.class); } else { return TypeDecoder.decode(input, type); } } catch (ClassNotFoundException e) { throw new UnsupportedOperationException("Invalid class reference provided", e); } } private static List build( String input, List> outputParameters) { List results = new ArrayList<>(outputParameters.size()); int offset = 0; for (TypeReference typeReference:outputParameters) { try { @SuppressWarnings("unchecked") Class type = (Class) typeReference.getClassType(); int hexStringDataOffset = getDataOffset(input, offset, type); Type result; if (DynamicArray.class.isAssignableFrom(type)) { result = TypeDecoder.decodeDynamicArray( input, hexStringDataOffset, typeReference); offset += MAX_BYTE_LENGTH_FOR_HEX_STRING; } else if (typeReference instanceof TypeReference.StaticArrayTypeReference) { int length = ((TypeReference.StaticArrayTypeReference) typeReference).getSize(); result = TypeDecoder.decodeStaticArray( input, hexStringDataOffset, typeReference, length); offset += length * MAX_BYTE_LENGTH_FOR_HEX_STRING; } else if (StaticArray.class.isAssignableFrom(type)) { int length = Integer.parseInt(type.getSimpleName() .substring(StaticArray.class.getSimpleName().length())); result = TypeDecoder.decodeStaticArray( input, hexStringDataOffset, typeReference, length); offset += length * MAX_BYTE_LENGTH_FOR_HEX_STRING; } else { result = TypeDecoder.decode(input, hexStringDataOffset, type); offset += MAX_BYTE_LENGTH_FOR_HEX_STRING; } results.add(result); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException("Invalid class reference provided", e); } } return results; } private static int getDataOffset(String input, int offset, Class type) { if (DynamicBytes.class.isAssignableFrom(type) || Utf8String.class.isAssignableFrom(type) || DynamicArray.class.isAssignableFrom(type)) { return TypeDecoder.decodeUintAsInt(input, offset) << 1; } else { return offset; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy