ContractInvocationInfoExtractor.java
- /*
- * @copyright defined in LICENSE.txt
- */
- package hera.spec.transaction;
- import static hera.util.ValidationUtils.assertEquals;
- import static hera.util.ValidationUtils.assertTrue;
- import static org.slf4j.LoggerFactory.getLogger;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.ObjectReader;
- import com.fasterxml.jackson.databind.node.ArrayNode;
- import com.fasterxml.jackson.databind.node.BooleanNode;
- import com.fasterxml.jackson.databind.node.NullNode;
- import com.fasterxml.jackson.databind.node.NumericNode;
- import com.fasterxml.jackson.databind.node.ObjectNode;
- import com.fasterxml.jackson.databind.node.TextNode;
- import com.fasterxml.jackson.databind.node.ValueNode;
- import hera.api.model.BigNumber;
- import hera.api.model.ContractAddress;
- import hera.api.model.ContractFunction;
- import hera.api.model.ContractInvocation;
- import hera.api.model.Transaction;
- import hera.exception.HerajException;
- import hera.spec.AergoSpec;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import lombok.AccessLevel;
- import lombok.NoArgsConstructor;
- import org.slf4j.Logger;
- @NoArgsConstructor(access = AccessLevel.PACKAGE)
- public class ContractInvocationInfoExtractor
- implements TransactionInfoExtractor<ContractInvocation> {
- protected static final ObjectReader reader = new ObjectMapper().reader();
- protected final Logger logger = getLogger(getClass());
- @Override
- public ContractInvocation extract(final Transaction transaction) {
- try {
- final JsonNode jsonNode = reader.readTree(transaction.getPayload().getInputStream());
- final JsonNode nameNode = jsonNode.findValue("Name");
- final JsonNode argsNode = jsonNode.findValue("Args");
- final ContractFunction function = parseToContractFunction(nameNode);
- final List<Object> args = parseToList(argsNode);
- final ContractInvocation recovered = ContractInvocation.newBuilder()
- .address(transaction.getRecipient().adapt(ContractAddress.class))
- .function(function)
- .amount(transaction.getAmount())
- .args(args)
- .build();
- return recovered;
- } catch (Exception e) {
- throw new HerajException(e);
- }
- }
- protected ContractFunction parseToContractFunction(final JsonNode jsonNode) {
- final String functionName = jsonNode.asText();
- return new ContractFunction(functionName);
- }
- protected List<Object> parseToList(final JsonNode jsonNode) {
- assertTrue(jsonNode instanceof ArrayNode);
- final List<Object> ret = new ArrayList<>();
- final int size = jsonNode.size();
- for (int i = 0; i < size; ++i) {
- final JsonNode next = jsonNode.get(i);
- Object parsedValue = null;
- if (next instanceof ArrayNode) {
- parsedValue = parseToList((ArrayNode) next);
- } else if (next instanceof ObjectNode) {
- if (null != next.get(AergoSpec.BIGNUM_JSON_KEY)) {
- parsedValue = parseToBigNumber((ObjectNode) next);
- } else {
- parsedValue = parseToMap((ObjectNode) next);
- }
- } else {
- parsedValue = parseValue((ValueNode) next);
- }
- ret.add(parsedValue);
- }
- return ret;
- }
- protected Map<String, Object> parseToMap(final ObjectNode jsonNode) {
- assertTrue(jsonNode instanceof ObjectNode);
- final Map<String, Object> ret = new HashMap<>();
- final Iterator<Entry<String, JsonNode>> it = jsonNode.fields();
- while (it.hasNext()) {
- final Entry<String, JsonNode> nextObjectNode = it.next();
- final String key = nextObjectNode.getKey();
- final JsonNode value = nextObjectNode.getValue();
- Object parsedValue = null;
- if (value instanceof ArrayNode) {
- parsedValue = parseToList((ArrayNode) value);
- } else if (value instanceof ObjectNode) {
- if (null != value.get(AergoSpec.BIGNUM_JSON_KEY)) {
- parsedValue = parseToBigNumber((ObjectNode) value);
- } else {
- parsedValue = parseToMap((ObjectNode) value);
- }
- } else {
- parsedValue = parseValue((ValueNode) value);
- }
- ret.put(key, parsedValue);
- }
- return ret;
- }
- protected BigNumber parseToBigNumber(final ObjectNode jsonNode) {
- assertTrue(jsonNode instanceof ObjectNode);
- assertEquals(1, jsonNode.size());
- final JsonNode bigNumberValueNode = jsonNode.get(AergoSpec.BIGNUM_JSON_KEY);
- if (null == bigNumberValueNode) {
- throw new IllegalArgumentException("JsonNode is not bignum value: " + jsonNode.toString());
- }
- if (!(bigNumberValueNode instanceof TextNode)) {
- throw new IllegalArgumentException(
- "JsonNode value is not bignum value: " + bigNumberValueNode.toString());
- }
- return new BigNumber(bigNumberValueNode.asText());
- }
- protected Object parseValue(final ValueNode valueNode) {
- if (valueNode instanceof BooleanNode) {
- return parseToBoolean(valueNode);
- } else if (valueNode instanceof NullNode) {
- return parseToNull(valueNode);
- } else if (valueNode instanceof NumericNode) {
- return parseToNumber(valueNode);
- } else if (valueNode instanceof TextNode) {
- return parseToString(valueNode);
- } else {
- throw new UnsupportedOperationException(
- "Unsupported node type: " + valueNode.getClass().getName());
- }
- }
- protected String parseToString(final JsonNode jsonNode) {
- return jsonNode.asText();
- }
- protected Number parseToNumber(final JsonNode jsonNode) {
- return ((NumericNode) jsonNode).numberValue();
- }
- protected Boolean parseToBoolean(final JsonNode jsonNode) {
- return jsonNode.asBoolean();
- }
- protected String parseToNull(final JsonNode jsonNode) {
- return null;
- }
- }