Skip to content

Commit

Permalink
chore: create separate classes for estimate and call
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Ivanov <[email protected]>
  • Loading branch information
0xivanov committed Nov 27, 2024
1 parent 817e474 commit 2bcf1d6
Show file tree
Hide file tree
Showing 10 changed files with 416 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*-
*
* Hedera Java SDK
*
* Copyright (C) 2023 - 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.hedera.hashgraph.sdk.examples;

import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Client;
import com.hedera.hashgraph.sdk.ContractCallQuery;
import com.hedera.hashgraph.sdk.ContractCreateTransaction;
import com.hedera.hashgraph.sdk.ContractFunctionParameters;
import com.hedera.hashgraph.sdk.FileCreateTransaction;
import com.hedera.hashgraph.sdk.FileId;
import com.hedera.hashgraph.sdk.Hbar;
import com.hedera.hashgraph.sdk.MirrorNodeContractCallQuery;
import com.hedera.hashgraph.sdk.MirrorNodeContractEstimateGasQuery;
import com.hedera.hashgraph.sdk.MirrorNodeContractQuery;
import com.hedera.hashgraph.sdk.PrivateKey;
import com.hedera.hashgraph.sdk.PublicKey;
import com.hedera.hashgraph.sdk.TransactionReceipt;
import com.hedera.hashgraph.sdk.TransactionResponse;
import com.hedera.hashgraph.sdk.logger.LogLevel;
import com.hedera.hashgraph.sdk.logger.Logger;
import io.github.cdimascio.dotenv.Dotenv;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class MirrorNodeContractQueriesExample {
/*
* See .env.sample in the examples folder root for how to specify values below
* or set environment variables with the same names.
*/

/**
* Operator's account ID.
* Used to sign and pay for operations on Hedera.
*/
private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID")));

/**
* Operator's private key.
*/
private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY")));

/**
* HEDERA_NETWORK defaults to testnet if not specified in dotenv file.
* Network can be: localhost, testnet, previewnet or mainnet.
*/
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");

/**
* SDK_LOG_LEVEL defaults to SILENT if not specified in dotenv file.
* Log levels can be: TRACE, DEBUG, INFO, WARN, ERROR, SILENT.
* <p>
* Important pre-requisite: set simple logger log level to same level as the SDK_LOG_LEVEL,
* for example via VM options: -Dorg.slf4j.simpleLogger.log.com.hedera.hashgraph=trace
*/
private static final String SDK_LOG_LEVEL = Dotenv.load().get("SDK_LOG_LEVEL", "SILENT");

private static final String SMART_CONTRACT_BYTECODE = "608060405234801561001057600080fd5b506040516104d73803806104d78339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b506040525050600080546001600160a01b0319163317905550805161010890600190602084019061010f565b50506101aa565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015057805160ff191683800117855561017d565b8280016001018555821561017d579182015b8281111561017d578251825591602001919060010190610162565b5061018992915061018d565b5090565b6101a791905b808211156101895760008155600101610193565b90565b61031e806101b96000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063368b87721461004657806341c0e1b5146100ee578063ce6d41de146100f6575b600080fd5b6100ec6004803603602081101561005c57600080fd5b81019060208101813564010000000081111561007757600080fd5b82018360208201111561008957600080fd5b803590602001918460018302840111640100000000831117156100ab57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610173945050505050565b005b6100ec6101a2565b6100fe6101ba565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610138578181015183820152602001610120565b50505050905090810190601f1680156101655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000546001600160a01b0316331461018a5761019f565b805161019d906001906020840190610250565b505b50565b6000546001600160a01b03163314156101b85733ff5b565b60018054604080516020601f600260001961010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156102455780601f1061021a57610100808354040283529160200191610245565b820191906000526020600020905b81548152906001019060200180831161022857829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061029157805160ff19168380011785556102be565b828001600101855582156102be579182015b828111156102be5782518255916020019190600101906102a3565b506102ca9291506102ce565b5090565b61024d91905b808211156102ca57600081556001016102d456fea264697066735822122084964d4c3f6bc912a9d20e14e449721012d625aa3c8a12de41ae5519752fc89064736f6c63430006000033";

public static void main(String[] args) throws Exception {
System.out.println("Mirror node contract query Example Start!");

/*
* Step 0:
* Create and configure the SDK Client.
*/
Client client = ClientHelper.forName(HEDERA_NETWORK);
// All generated transactions will be paid by this account and signed by this key.
client.setOperator(OPERATOR_ID, OPERATOR_KEY);
// Attach logger to the SDK Client.
client.setLogger(new Logger(LogLevel.valueOf(SDK_LOG_LEVEL)));

var operatorPublicKey = OPERATOR_KEY.getPublicKey();

/*
* Step 1:
* Create the contract
*/
System.out.println("Creating new file...");
TransactionResponse fileCreateTxResponse = new FileCreateTransaction()
// Use the same key as the operator to "own" this file.
.setKeys(operatorPublicKey)
.setContents(SMART_CONTRACT_BYTECODE)
// The default max fee of 1 Hbar is not enough to create a file (starts around ~1.1 Hbar).
.setMaxTransactionFee(Hbar.from(2))
.execute(client);

TransactionReceipt fileCreateTxReceipt = fileCreateTxResponse.getReceipt(client);
FileId newFileId = fileCreateTxReceipt.fileId;

Objects.requireNonNull(newFileId);
System.out.println("Created new file with ID: " + newFileId);

var response = new ContractCreateTransaction()
.setAdminKey(client.getOperatorPublicKey())
.setGas(200000)
.setConstructorParameters(new ContractFunctionParameters().addString("Hello from Hedera."))
.setBytecodeFileId(newFileId)
.setContractMemo("Simple contract with string field")
.execute(client);

var contractId = Objects.requireNonNull(response.getReceipt(client).contractId);

/*
* Step 3:
* Wait for mirror node to import data
*/
Thread.sleep(4000);

/*
* Step 4:
* Estimate the gas needed
*/
var gas = new MirrorNodeContractEstimateGasQuery()
.setContractId(contractId)
.setFunction("getMessage")
.execute(client);

System.out.println("Gas needed for this query: " + gas);

/*
* Step 5:
* Do the query against the consensus node using the estimated gas
*/
var callQuery = new ContractCallQuery()
.setContractId(contractId)
.setGas(gas)
.setFunction("getMessage")
.setQueryPayment(new Hbar(1));

var result = callQuery
.execute(client);

/*
* Step 5:
* Simulate the transaction for free, using the mirror node
*/
var simulationResult = new MirrorNodeContractCallQuery()
.setContractId(contractId)
.setFunction("getMessage")
.execute(client);

System.out.println("Simulation result: " + decodeABIHex(simulationResult.substring(2)));
System.out.println("Contract call result: " + result.getString(0));
}
private static String decodeABIHex(String hex) {
int length = Integer.parseInt(hex.substring(64, 128), 16);

String hexStringData = hex.substring(128, 128 + length * 2);

byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = (byte) Integer.parseInt(hexStringData.substring(i * 2, i * 2 + 2), 16);
}

return new String(bytes, StandardCharsets.UTF_8);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*-
*
* Hedera Java SDK
*
* Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.hedera.hashgraph.sdk;

import java.util.concurrent.ExecutionException;

public class MirrorNodeContractCallQuery extends MirrorNodeContractQuery<MirrorNodeContractCallQuery> {
/**
* Does transient simulation of read-write operations and returns the result in hexadecimal string format.
*
* @param client The Client instance to perform the operation with
* @return The result of the contract call
* @throws ExecutionException
* @throws InterruptedException
*/
public String execute(Client client) throws ExecutionException, InterruptedException {
return call(client);
}

@Override
public String toString() {
return "MirrorNodeContractCallQuery" + super.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*-
*
* Hedera Java SDK
*
* Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.hedera.hashgraph.sdk;

import java.util.concurrent.ExecutionException;

public class MirrorNodeContractEstimateGasQuery extends MirrorNodeContractQuery<MirrorNodeContractEstimateGasQuery> {

/**
* Returns gas estimation for the EVM execution.
*
* @param client The Client instance to perform the operation with
* @return The estimated gas cost
* @throws ExecutionException
* @throws InterruptedException
*/
public long execute(Client client) throws ExecutionException, InterruptedException {
return estimate(client);
}

@Override
public String toString() {
return "MirrorNodeContractEstimateGasQuery" + super.toString();
}
}
Loading

0 comments on commit 2bcf1d6

Please sign in to comment.