Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ConstructClientExample #523

Merged
merged 9 commits into from
Oct 16, 2023
6 changes: 6 additions & 0 deletions sdk/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME ${PROJECT_NAME}-auto-c
set(CONSENSUS_PUB_SUB_EXAMPLE_NAME ${PROJECT_NAME}-consensus-pub-sub-example)
set(CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME ${PROJECT_NAME}-consensus-pub-sub-chunked-example)
set(CONSENSUS_PUB_SUB_WITH_SUBMIT_KEY_EXAMPLE_NAME ${PROJECT_NAME}-consensus-pub-sub-with-submit-key-example)
set(CONSTRUCT_CLIENT_EXAMPLE_NAME ${PROJECT_NAME}-construct-client-example)
set(CREATE_ACCOUNT_EXAMPLE_NAME ${PROJECT_NAME}-create-account-example)
set(CREATE_SIMPLE_CONTRACT_EXAMPLE_NAME ${PROJECT_NAME}-create-simple-contract-example)
set(CREATE_STATEFUL_CONTRACT_EXAMPLE_NAME ${PROJECT_NAME}-create-stateful-contract-example)
Expand Down Expand Up @@ -39,6 +40,7 @@ add_executable(${AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME} AutoCrea
add_executable(${CONSENSUS_PUB_SUB_EXAMPLE_NAME} ConsensusPubSubExample.cc)
add_executable(${CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME} ConsensusPubSubChunkedExample.cc)
add_executable(${CONSENSUS_PUB_SUB_WITH_SUBMIT_KEY_EXAMPLE_NAME} ConsensusPubSubWithSubmitKeyExample.cc)
add_executable(${CONSTRUCT_CLIENT_EXAMPLE_NAME} ConstructClientExample.cc)
add_executable(${CREATE_ACCOUNT_EXAMPLE_NAME} CreateAccountExample.cc)
add_executable(${CREATE_SIMPLE_CONTRACT_EXAMPLE_NAME} CreateSimpleContractExample.cc)
add_executable(${CREATE_STATEFUL_CONTRACT_EXAMPLE_NAME} CreateStatefulContractExample.cc)
Expand Down Expand Up @@ -73,6 +75,8 @@ file(COPY ${PROJECT_SOURCE_DIR}/addressbook/testnet.pb

file(COPY ${PROJECT_SOURCE_DIR}/config/hello_world.json
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
file(COPY ${PROJECT_SOURCE_DIR}/config/local_node.json
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
file(COPY ${PROJECT_SOURCE_DIR}/config/stateful.json
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})

Expand All @@ -90,6 +94,7 @@ target_link_libraries(${AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME} P
target_link_libraries(${CONSENSUS_PUB_SUB_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CONSENSUS_PUB_SUB_WITH_SUBMIT_KEY_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CONSTRUCT_CLIENT_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CREATE_ACCOUNT_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CREATE_SIMPLE_CONTRACT_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
target_link_libraries(${CREATE_STATEFUL_CONTRACT_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME})
Expand Down Expand Up @@ -126,6 +131,7 @@ install(TARGETS
${CONSENSUS_PUB_SUB_EXAMPLE_NAME}
${CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME}
${CONSENSUS_PUB_SUB_WITH_SUBMIT_KEY_EXAMPLE_NAME}
${CONSTRUCT_CLIENT_EXAMPLE_NAME}
${CREATE_ACCOUNT_EXAMPLE_NAME}
${CREATE_SIMPLE_CONTRACT_EXAMPLE_NAME}
${CREATE_STATEFUL_CONTRACT_EXAMPLE_NAME}
Expand Down
104 changes: 104 additions & 0 deletions sdk/examples/ConstructClientExample.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*-
*
* Hedera C++ SDK
*
* Copyright (C) 2020 - 2023 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.
*
*/
#include "AccountId.h"
#include "Client.h"
#include "ED25519PrivateKey.h"
#include "LedgerId.h"

#include <iostream>
#include <string>
#include <unordered_map>

using namespace Hedera;

int main(int argc, char** argv)
{
if (argc < 3)
{
std::cout << "Please enter a network name and a configuration filepath" << std::endl;
return 1;
}

/*
* Here are some ways you can construct and configure a client. A client has a network and an operator.
*
* A Hedera network is made up of nodes -- individual servers who participate in the process of reaching consensus
* on the order and validity of transactions on the network. Three networks you likely know of are previewnet,
* testnet, and mainnet.
*
* For the purpose of connecting to it, each node has an IP address or URL and a port number. Each node also has an
* AccountId used to refer to that node for several purposes, including the paying of fees to that node when a
* client submits requests to it.
*
* You can configure what network you want a client to use -- in other words, you can specify a list of URLS and
* port numbers with associated AccountIds, and when that client is used to execute queries and transactions, the
* client will submit requests only to nodes in that list.
*
* A Client has an operator, which has an AccountId and a PublicKey, and which can sign requests. A client's
* operator can also be configured.
*/

// Here's the simplest way to construct a client. These clients' networks are filled with default lists of nodes that
// are baked into the SDK. Their operators are not yet set, and trying to use them now will result in exceptions.
Client previewClient = Client::forPreviewnet();
Client testClient = Client::forTestnet();
Client mainClient = Client::forMainnet();

// We can also construct a client for previewnet, testnet, or mainnet depending on the value of a network name string.
// If, for example, the input string equals "testnet", this client will be configured to connect to the Hedera
// Testnet.
Client namedNetworkClient = Client::forName(argv[1]);

// Set the operator on testClient (the AccountId and PrivateKey here are fake, this is just an example).
testClient.setOperator(
AccountId::fromString("0.0.3"),
ED25519PrivateKey::fromString(
"302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10"));

// Create a Client with a custom network.
const std::unordered_map<std::string, AccountId> network = {
{"2.testnet.hedera.com:50211", AccountId(5ULL)},
{ "3.testnet.hedera.com:50211", AccountId(6ULL)}
};
Client customClient = Client::forNetwork(network);

// Since the customClient's network is in this case a subset of the Hedera Testnet, we should set the LedgerId of the
// Client to testnet's LedgerId. If we don't do this, checksum validation won't work (See ValidateChecksumExample.cc).
// You can use customClient.getLedgerId() to check the ledger ID. If you attempt to validate a checksum against a
// client whose ledger ID is not set, an IllegalStateException will be thrown.
customClient.setLedgerId(LedgerId::TESTNET);

// Let's generate a client from a config.json file. A config file may specify a network by name, or it may provide a
// custom network in the form of a list of nodes. The config file should specify the operator, so you can use a client
// constructed using fromConfigFile() immediately.
Client configClient = Client::fromConfigFile(argv[2]);
configClient.close();

// Always close a Client when you're done with it.
previewClient.close();
testClient.close();
mainClient.close();
namedNetworkClient.close();
customClient.close();

std::cout << "Success!" << std::endl;

return 0;
}
37 changes: 37 additions & 0 deletions sdk/main/include/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
#define HEDERA_SDK_CPP_CLIENT_H_

#include <chrono>
#include <filesystem>
#include <functional>
#include <memory>
#include <nlohmann/json.hpp>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

Expand Down Expand Up @@ -73,6 +77,15 @@ class Client
*/
[[nodiscard]] static Client forNetwork(const std::unordered_map<std::string, AccountId>& networkMap);

/**
* Construct a Client by a name. The name must be one of "mainnet", "testnet", or "previewnet", otherwise this will
* throw std::invalid_argument.
*
* @param name The name of the Client to construct.
* @return A Client object that is set-up to communicate with the input network name.
*/
[[nodiscard]] static Client forName(std::string_view name);

/**
* Construct a Client pre-configured for Hedera Mainnet access.
*
Expand All @@ -94,6 +107,30 @@ class Client
*/
[[nodiscard]] static Client forPreviewnet();

/**
* Construct a Client from a JSON configuration string.
*
* @param json The JSON configuration string.
* @return A Client object initialized with the properties specified in the JSON configuration string.
*/
[[nodiscard]] static Client fromConfig(std::string_view json);

/**
* Construct a Client from a JSON configuration object.
*
* @param json The JSON configuration object.
* @return A Client object initialized with the properties specified in the JSON configuration object.
*/
[[nodiscard]] static Client fromConfig(const nlohmann::json& json);

/**
* Construct a Client from a JSON configuration file.
*
* @param path The filepath to the JSON configuration file.
* @return A Client object initialized with the properties specified in the JSON configuration file.
*/
[[nodiscard]] static Client fromConfigFile(std::string_view path);

/**
* Set the mirror network with which this Client should communicate.
*
Expand Down
20 changes: 20 additions & 0 deletions sdk/main/include/PrivateKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ class PrivateKey : public Key
*/
~PrivateKey() override;

/**
* Construct a PrivateKey object from a hex-encoded, DER-encoded key string.
*
* @param key The DER-encoded hex string from which to construct a PrivateKey.
* @return A pointer to an PrivateKey representing the input DER-encoded hex string.
* @throws BadKeyException If the private key type (ED25519 or ECDSAsecp256k1) is unable to be determined or realized
* from the input hex string.
*/
[[nodiscard]] static std::unique_ptr<PrivateKey> fromStringDer(std::string_view key);

/**
* Construct a PrivateKey object from a DER-encoded byte vector.
*
* @param bytes The vector of DER-encoded bytes from which to construct a PrivateKey.
* @return A pointer to a PrivateKey representing the input DER-encoded bytes.
* @throws BadKeyException If the private key type (ED25519 or ECDSAsecp256k1) is unable to be determined or realized
* from the input byte array.
*/
[[nodiscard]] static std::unique_ptr<PrivateKey> fromBytesDer(const std::vector<std::byte>& bytes);

/**
* Derive a child PrivateKey from this PrivateKey.
*
Expand Down
Loading
Loading