Contract Api

ContractApi provides java interface based smart contract call. ContractApi automatically fill nonce for signer. It commit fails by nonce error, it automatically fetch right nonce and retry with it.

Prepare

To use ContractApi, first you have to deploy smart contract. Then, write an interface corresponding to smart contract functions.

Write a smart contract. For more about writing lua smart contract, see Programming Guide.

function constructor(key, arg1, arg2)
  if key ~= nil then
    system.setItem(key, {intVal=arg1, stringVal=arg2})
  end
end

function set(key, arg1, arg2)
  contract.event("set", key, arg1, arg2)
  system.setItem(key, {intVal=arg1, stringVal=arg2})
end

function get(key)
  return system.getItem(key)
end

function check_delegation()
  return true
end

abi.register_view(get)
abi.register(set)
abi.fee_delegation(set)
abi.payable(set)

Deploy smart contract.

// make a contract definition
String encodedContract = contractPayload;
ContractDefinition contractDefinition = ContractDefinition.newBuilder()
    .encodedContract(encodedContract)
    .build();

// deploy contract
walletApi.unlock(authentication);
TxHash txHash = walletApi.with(client).transaction()
    .deploy(contractDefinition, Fee.INFINITY);
walletApi.lock();

// sleep
Thread.sleep(2000L);

// get ContractTxReceipt
ContractTxReceipt contractTxReceipt = walletApi.with(client).query()
    .getContractTxReceipt(txHash);

// get contract address
ContractAddress contractAddress = contractTxReceipt.getContractAddress();
System.out.println("Deployed contract address: " + contractPayload);

Write an interface. Interface methods should matches with smart contract functions.

// interface for smart contract
interface CustomInterface1 {

  /*
    Matches with

      function set(key, arg1, arg2)
        ...
      end

      ...

      abi.register(set)

    And it also uses provided fee when making transaction.
   */
  TxHash set(String key, int arg1, String args2, Fee fee);

  /*
    Matches with

      function set(key, arg1, arg2)
        ...
      end

      ...

      abi.register(set)

    And it also uses Fee.INFINITY when making transaction.
   */
  TxHash set(String key, int arg1, String args2);

  /*
    Matches with

      function get(key)
        ...
        -- returns lua table which can be binded with Data class
        return someVal
      end

      ...

      abi.register_view(get)
   */
  Data get(String key);

}

// java bean
class Data {

  protected int intVal;

  protected String stringVal;

  public int getIntVal() {
    return intVal;
  }

  public void setIntVal(int intVal) {
    this.intVal = intVal;
  }

  public String getStringVal() {
    return stringVal;
  }

  public void setStringVal(String stringVal) {
    this.stringVal = stringVal;
  }

  @Override
  public String toString() {
    return "Data{" +
        "intVal=" + intVal +
        ", stringVal=" + stringVal +
        '}';
  }
}

Make

Given deployed smart contract and an java interface to use it, you can make a ContractApi for it.

Make a ContractApi with implicit retry count and interval on nonce failure.

// create a contract api
ContractAddress contractAddress = deployedContractAddress;
ContractApi<CustomInterface1> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface1.class);
System.out.println("ContractApi: " + contractApi);

Make a ContractApi with explicit retry count and interval on nonce failure.

// create a contract api with retry count 5 and interval 1000ms
ContractAddress contractAddress = deployedContractAddress;
TryCountAndInterval tryCountAndInterval = TryCountAndInterval.of(5, Time.of(1000L));
ContractApi<CustomInterface1> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface1.class, tryCountAndInterval);
System.out.println("ContractApi: " + contractApi);

Execute

With an AergoKey.

// prepare an signer
AergoKey signer = richKey;

// create a contract api
ContractAddress contractAddress = deployedContractAddress;
ContractApi<CustomInterface1> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface1.class);

// execute contract with a contract api
TxHash executeTxHash = contractApi.with(client).execution(signer)
    .set("key", 123, "test", Fee.INFINITY);
System.out.println("Execute tx hash: " + executeTxHash);

With a WalletApi.

// create a contract api
ContractAddress contractAddress = deployedContractAddress;
ContractApi<CustomInterface1> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface1.class);

// execute contract with a contract api
walletApi.unlock(authentication);
TxHash executeTxHash = contractApi.with(client).execution(walletApi)
    .set("key", 123, "test", Fee.INFINITY);
walletApi.lock();
System.out.println("Execute tx hash: " + executeTxHash);

Query

With a model binded.

// create a contract api
ContractAddress contractAddress = deployedContractAddress;
ContractApi<CustomInterface1> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface1.class);

// query contract with a contract api
Data data = contractApi.with(client).query().get("key");
System.out.println("Queried data: " + data);

Without binded model.

// create a contract api
ContractAddress contractAddress = deployedContractAddress;
ContractApi<CustomInterface2> contractApi = new ContractApiFactory()
    .create(contractAddress, CustomInterface2.class);

// query contract with a contract api
ContractResult contractResult = contractApi.with(client).query().get("key");
System.out.println("Queried data: " + contractResult);