Skip to content

Commit

Permalink
521: Add ConstructClientExample
Browse files Browse the repository at this point in the history
Signed-off-by: Rob Walworth <[email protected]>
Signed-off-by: Deyan Zhekov <[email protected]>
Co-authored-by: Deyan Zhekov <[email protected]>
  • Loading branch information
rwalworth and deyanzz authored Oct 16, 2023
1 parent ebb8ab7 commit 0e1198f
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 49 deletions.
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

0 comments on commit 0e1198f

Please sign in to comment.