From ae475c82a471fce766cfabc74ae73254493a53d8 Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Tue, 19 Nov 2024 09:31:31 +0200 Subject: [PATCH] feat: init client with mirror network (#2085) Signed-off-by: Ivan Ivanov --- ...tializeClientWithMirrorNetworkExample.java | 92 +++++++++++++++++++ ...com.hedera.gradle.examples.java.gradle.kts | 1 + .../java/com/hedera/hashgraph/sdk/Client.java | 23 ++++- .../integration/ClientIntegrationTest.java | 14 +++ 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 examples/src/main/java/com/hedera/hashgraph/sdk/examples/InitializeClientWithMirrorNetworkExample.java diff --git a/examples/src/main/java/com/hedera/hashgraph/sdk/examples/InitializeClientWithMirrorNetworkExample.java b/examples/src/main/java/com/hedera/hashgraph/sdk/examples/InitializeClientWithMirrorNetworkExample.java new file mode 100644 index 000000000..20ba0e68b --- /dev/null +++ b/examples/src/main/java/com/hedera/hashgraph/sdk/examples/InitializeClientWithMirrorNetworkExample.java @@ -0,0 +1,92 @@ +/*- + * + * 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.examples; + +import com.hedera.hashgraph.sdk.AccountCreateTransaction; +import com.hedera.hashgraph.sdk.AccountId; +import com.hedera.hashgraph.sdk.Client; +import com.hedera.hashgraph.sdk.Hbar; +import com.hedera.hashgraph.sdk.PrivateKey; +import com.hedera.hashgraph.sdk.logger.LogLevel; +import com.hedera.hashgraph.sdk.logger.Logger; +import io.github.cdimascio.dotenv.Dotenv; +import java.util.List; +import java.util.Objects; + +public class InitializeClientWithMirrorNetworkExample { + /* + * 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"))); + + /** + * SDK_LOG_LEVEL defaults to SILENT if not specified in dotenv file. Log levels can be: TRACE, DEBUG, INFO, WARN, + * ERROR, SILENT. + *

+ * 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"); + + public static void main(String[] args) throws Exception { + /* + * Step 0: + * Create and configure the SDK Client. + */ + Client client = Client.forMirrorNetwork(List.of("testnet.mirrornode.hedera.com:443")); + // 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))); + + /* + * Step 1: + * Generate ED25519 key pair. + */ + System.out.println("Generating ED25519 key pair..."); + PrivateKey privateKey = PrivateKey.generateED25519(); + + /* + * Step 2: + * Create account + */ + AccountId aliceId = new AccountCreateTransaction() + .setKey(privateKey) + .setInitialBalance(Hbar.from(5)) + .execute(client) + .getReceipt(client) + .accountId; + Objects.requireNonNull(aliceId); + System.out.println("Alice's account ID: " + aliceId); + } +} diff --git a/gradle/plugins/src/main/kotlin/com.hedera.gradle.examples.java.gradle.kts b/gradle/plugins/src/main/kotlin/com.hedera.gradle.examples.java.gradle.kts index 220ceb189..e90786ea4 100644 --- a/gradle/plugins/src/main/kotlin/com.hedera.gradle.examples.java.gradle.kts +++ b/gradle/plugins/src/main/kotlin/com.hedera.gradle.examples.java.gradle.kts @@ -69,6 +69,7 @@ abstract class RunAllExample : DefaultTask() { .map { it.name.replace(".java", "") } .filter { it != "ValidateChecksumExample" } // disabled this example, because it needs user input (but it WORKS) .filter { it != "ConsensusPubSubChunkedExample" } // is flaky on local-node env, will be investigated + .filter { it != "InitializeClientWithMirrorNetworkExample" } // disabled - cannot run on localnode .toList() exampleClasses.forEach { className -> diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java index da66b5aa8..957b14ba5 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/Client.java @@ -185,6 +185,24 @@ public static Client forNetwork(Map networkMap) { return new Client(executor, network, mirrorNetwork, null, true, null); } + /** + * Set up the client from selected mirror network. + * + * @param mirrorNetworkList + * @return + */ + public static Client forMirrorNetwork(List mirrorNetworkList) throws InterruptedException, TimeoutException { + var executor = createExecutor(); + var network = Network.forNetwork(executor, new HashMap<>()); + var mirrorNetwork = MirrorNetwork.forNetwork(executor, mirrorNetworkList); + var client = new Client(executor, network, mirrorNetwork, null, true, null); + var addressBook = new AddressBookQuery() + .setFileId(FileId.ADDRESS_BOOK) + .execute(client); + client.setNetworkFromAddressBook(addressBook); + return client; + } + /** * Set up the client for the selected network. * @@ -1418,8 +1436,8 @@ private Client toClient() throws Exception, InterruptedException { private Client initializeWithNetwork() throws Exception { if (network == null) { throw new Exception("Network is not set in provided json object"); - } - + } + Client client; if (network.isJsonObject()) { client = clientFromNetworkJson(); @@ -1501,7 +1519,6 @@ private void setOperatorOn(Client client) { if (operator != null) { AccountId operatorAccount = AccountId.fromString(operator.accountId); PrivateKey privateKey = PrivateKey.fromString(operator.privateKey); - client.setOperator(operatorAccount, privateKey); } } diff --git a/sdk/src/testIntegration/java/com/hedera/hashgraph/sdk/test/integration/ClientIntegrationTest.java b/sdk/src/testIntegration/java/com/hedera/hashgraph/sdk/test/integration/ClientIntegrationTest.java index 5ec000e6b..08da7ffbb 100644 --- a/sdk/src/testIntegration/java/com/hedera/hashgraph/sdk/test/integration/ClientIntegrationTest.java +++ b/sdk/src/testIntegration/java/com/hedera/hashgraph/sdk/test/integration/ClientIntegrationTest.java @@ -21,6 +21,7 @@ import com.hedera.hashgraph.sdk.*; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.time.Duration; @@ -248,4 +249,17 @@ void pingAllAsync() throws Exception { } } + + @Test + @DisplayName("`forMirrorNetwork()`") + void testClientInitWithMirrorNetwork() throws Exception { + var mirrorNetworkString = "testnet.mirrornode.hedera.com:443"; + var client = Client.forMirrorNetwork(List.of(mirrorNetworkString)); + var mirrorNetwork = client.getMirrorNetwork(); + + assertThat(mirrorNetwork).hasSize(1); + assertThat(mirrorNetwork.get(0)).isEqualTo(mirrorNetworkString); + assertThat(client.getNetwork()).isNotNull(); + assertThat(client.getNetwork()).isNotEmpty(); + } }