From b43f8491bf63660decf7ed4f375e737fe0c0c7a8 Mon Sep 17 00:00:00 2001 From: Mohit Date: Sun, 14 Jun 2026 18:30:45 +0530 Subject: [PATCH 1/6] fix: improve windows include comments Signed-off-by: Mohit --- src/sdk/main/include/impl/BaseNode.h | 2 +- src/sdk/main/src/AccountId.cc | 2 +- src/sdk/main/src/FeeEstimateQuery.cc | 2 +- src/tck/src/TckServer.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sdk/main/include/impl/BaseNode.h b/src/sdk/main/include/impl/BaseNode.h index 0f38ac32b..db897d450 100644 --- a/src/sdk/main/include/impl/BaseNode.h +++ b/src/sdk/main/include/impl/BaseNode.h @@ -2,7 +2,7 @@ #ifndef HIERO_SDK_CPP_IMPL_BASE_NODE_H_ #define HIERO_SDK_CPP_IMPL_BASE_NODE_H_ -#include // This is needed for Windows to build for some reason. +#include // Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. #include "BaseNodeAddress.h" #include "Defaults.h" diff --git a/src/sdk/main/src/AccountId.cc b/src/sdk/main/src/AccountId.cc index 14f6665e9..c274620d2 100644 --- a/src/sdk/main/src/AccountId.cc +++ b/src/sdk/main/src/AccountId.cc @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Windows build requires this to be included first for some reason. +// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. #include // NOLINT #include "AccountId.h" diff --git a/src/sdk/main/src/FeeEstimateQuery.cc b/src/sdk/main/src/FeeEstimateQuery.cc index 656b10c8d..b0a071c97 100644 --- a/src/sdk/main/src/FeeEstimateQuery.cc +++ b/src/sdk/main/src/FeeEstimateQuery.cc @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Windows build requires this to be included first for some reason. +// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. #include // NOLINT #include "Client.h" diff --git a/src/tck/src/TckServer.cc b/src/tck/src/TckServer.cc index 7bf3fe5b5..b0dd85dd9 100644 --- a/src/tck/src/TckServer.cc +++ b/src/tck/src/TckServer.cc @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Windows build requires this to be included first for some reason. +// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers reached transitively from this header. #include // NOLINT #include "TckServer.h" From 17b60034cea1cecba3f8710829077797b3c25481 Mon Sep 17 00:00:00 2001 From: Mohit Date: Sun, 14 Jun 2026 18:47:11 +0530 Subject: [PATCH 2/6] docs: move orphaned operator== Doxygen block to public declaration in FeeComponents.h Signed-off-by: Mohit --- src/sdk/main/include/FeeComponents.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/sdk/main/include/FeeComponents.h b/src/sdk/main/include/FeeComponents.h index b48109ba8..5046f0b58 100644 --- a/src/sdk/main/include/FeeComponents.h +++ b/src/sdk/main/include/FeeComponents.h @@ -268,6 +268,13 @@ class FeeComponents * @return The price for data retrieved from disk. */ [[nodiscard]] inline int64_t getResponseDiskByte() const { return mResponseDiskByte; } + + /** + * Compare this FeeComponents to another and determine if they are equal. + * + * @param rhs The other FeeComponents with which to compare this FeeComponents. + * @return \c TRUE if this FeeComponents is the same as the input, otherwise \c FALSE. + */ [[nodiscard]] bool operator==(const FeeComponents& rhs) const; private: @@ -326,12 +333,6 @@ class FeeComponents */ int64_t mResponseDiskByte = 0LL; - /** - * Compare two FeeComponents instances and determine if they represent an equivalent set of fees. - * - * @param rhs The right-hand side FeeComponents to compare. - * @return \c TRUE if this FeeComponents and \p rhs represent equivalent fee component values, otherwise \c FALSE. - */ }; } // namespace Hiero From c93fd168b715fcdbf06d12228ebd30be0bc5c063 Mon Sep 17 00:00:00 2001 From: Mohit Yadav Date: Sun, 14 Jun 2026 18:57:44 +0530 Subject: [PATCH 3/6] Delete src/sdk/main/include/impl/BaseNode.h Signed-off-by: Mohit Yadav --- src/sdk/main/include/impl/BaseNode.h | 259 --------------------------- 1 file changed, 259 deletions(-) delete mode 100644 src/sdk/main/include/impl/BaseNode.h diff --git a/src/sdk/main/include/impl/BaseNode.h b/src/sdk/main/include/impl/BaseNode.h deleted file mode 100644 index db897d450..000000000 --- a/src/sdk/main/include/impl/BaseNode.h +++ /dev/null @@ -1,259 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#ifndef HIERO_SDK_CPP_IMPL_BASE_NODE_H_ -#define HIERO_SDK_CPP_IMPL_BASE_NODE_H_ - -#include // Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. - -#include "BaseNodeAddress.h" -#include "Defaults.h" - -#include -#include -#include -#include - -namespace Hiero::internal -{ -template -class BaseNode -{ -public: - /** - * Get this BaseNode's key. - * - * @return This BaseNode's key. - */ - [[nodiscard]] virtual KeyType getKey() const = 0; - - /** - * Close this BaseNode's connection to its remote node. - */ - void close(); - - /** - * Increase the backoff of this BaseNode. - */ - void increaseBackoff(); - - /** - * Decrease the backoff of this BaseNode. - */ - void decreaseBackoff(); - - /** - * Is this BaseNode currently considered healthy? - * - * @return \c TRUE if this BaseNode is healthy, otherwise \c FALSE. - */ - [[nodiscard]] bool isHealthy() const; - - /** - * Has this BaseNode failed to connect to its remote node? - * - * @return \c TRUE if this BaseNode has failed to connect to its remote node, otherwise \c FALSE. - */ - [[nodiscard]] bool channelFailedToConnect(); - - /** - * Get the remaining amount of time this BaseNode has in its backoff. - * - * @return The remaining amount of time this BaseNode has in its backoff. - */ - [[nodiscard]] std::chrono::system_clock::duration getRemainingTimeForBackoff() const; - - /** - * Set the minimum amount of time for this BaseNode to backoff after a bad gRPC status is received. - * - * @param backoff The minimum backoff time for this BaseNode after a bad gRPC status is received. - * @return A reference to this derived BaseNode object with the newly-set minimum backoff. - */ - NodeType& setMinNodeBackoff(const std::chrono::system_clock::duration& backoff); - - /** - * Set the maximum amount of time for this BaseNode to backoff after a bad gRPC status is received. - * - * @param backoff The maximum backoff time for this BaseNode after a bad gRPC status is received. - * @return A reference to this derived BaseNode object with the newly-set maximum backoff. - */ - NodeType& setMaxNodeBackoff(const std::chrono::system_clock::duration& backoff); - - /** - * Get this BaseNode's BaseNodeAddress. - * - * @return address The BaseNodeAddress of this BaseNode. - */ - [[nodiscard]] inline BaseNodeAddress getAddress() const - { - std::unique_lock lock(*mMutex); - return mAddress; - } - - /** - * Get the minimum amount of time for this BaseNode to backoff after a bad gRPC status is received. - * - * @return The minimum amount of time for this BaseNode to backoff after a bad gRPC status is received. - */ - [[nodiscard]] inline std::chrono::system_clock::duration getMinNodeBackoff() const - { - std::unique_lock lock(*mMutex); - return mMinNodeBackoff; - } - - /** - * Get the maximum amount of time for this BaseNode to backoff after a bad gRPC status is received. - * - * @return The maximum amount of time for this BaseNode to backoff after a bad gRPC status is received. - */ - [[nodiscard]] inline std::chrono::system_clock::duration getMaxNodeBackoff() const - { - std::unique_lock lock(*mMutex); - return mMaxNodeBackoff; - } - - /** - * Get the number of times this BaseNode has received a bad gRPC status when attempting to submit a request. - * - * @return The number of times this BaseNode has received a bad gRPC status. - */ - [[nodiscard]] inline unsigned int getBadGrpcStatusCount() const - { - std::unique_lock lock(*mMutex); - return mBadGrpcStatusCount; - } - - /** - * Get the time at which this BaseNode will be considered "healthy". - * - * @return The time at which this BaseNode will be considered "healthy". - */ - [[nodiscard]] inline std::chrono::system_clock::time_point getReadmitTime() const - { - std::unique_lock lock(*mMutex); - return mReadmitTime; - } - - /** - * Get this BaseNode's mutex. - * - * @return This BaseNode's mutex. - */ - [[nodiscard]] inline std::shared_ptr getLock() const { return mMutex; } - -protected: - ~BaseNode() = default; - - /** - * Construct with a BaseNodeAddress. - * - * @param address The BaseNodeAddress of this BaseNode. - */ - explicit BaseNode(BaseNodeAddress address); - - /** - * Set the BaseNodeAddress of this BaseNode. This will also close this BaseNode's current connection. - * - * @param address The BaseNodeAddress to set. - */ - NodeType& setAddress(const BaseNodeAddress& address); - - /** - * Get this BaseNode's gRPC channel. Creates and initializes a new channel if one isn't already created. - * - * @return A pointer to this BaseNode's gRPC channel. - */ - [[nodiscard]] std::shared_ptr getChannel(); - -private: - /** - * How often to query for the state of the channel when determining if this BaseNode has connected to its remote node. - */ - static constexpr auto GET_STATE_INTERVAL = std::chrono::milliseconds(50); - - /** - * How long to try and let the channel connect before calling the connection a failure. - */ - static constexpr auto GET_STATE_TIMEOUT = std::chrono::seconds(10); - - /** - * Get the TLS credentials for this BaseNode's gRPC channel. - * - * @return A pointer to the TLS credentials for this BaseNode's gRPC channel. - */ - [[nodiscard]] virtual std::shared_ptr getTlsChannelCredentials() const; - - /** - * Initialize the stubs in this derived BaseNode with this BaseNode's gRPC channel. - */ - virtual void initializeStubs() - { // Intentionally unimplemented, derived BaseNodes that don't use stubs require no functionality. - } - - /** - * Close the stubs in this derived BaseNode. - */ - virtual void closeStubs() - { // Intentionally unimplemented, derived BaseNodes that don't use stubs require no functionality. - } - - /** - * Get the authority of this BaseNode. - * - * @return The authority of this BaseNode. - */ - [[nodiscard]] virtual inline std::string getAuthority() const { return "127.0.0.1"; } - - /** - * Close this BaseNode's channel and any stubs using that channel. - */ - void closeChannel(); - - /** - * The address of this BaseNode. - */ - BaseNodeAddress mAddress; - - /** - * Pointer to the gRPC channel used to communicate with the gRPC server living on the remote node. - */ - std::shared_ptr mChannel = nullptr; - - /** - * The minimum amount of time to wait to use this BaseNode after it has received a bad gRPC status. - */ - std::chrono::system_clock::duration mMinNodeBackoff = DEFAULT_MIN_NODE_BACKOFF; - - /** - * The maximum amount of time to wait to use this BaseNode after it has received a bad gRPC status. - */ - std::chrono::system_clock::duration mMaxNodeBackoff = DEFAULT_MAX_NODE_BACKOFF; - - /** - * The current amount of time to wait to use this BaseNode after it has received a bad gRPC status. This will increase - * exponentially until mMaxNodeBackoff is reached. - */ - std::chrono::system_clock::duration mCurrentBackoff = DEFAULT_MIN_NODE_BACKOFF; - - /** - * The time at which this BaseNode will be considered "healthy". - */ - std::chrono::system_clock::time_point mReadmitTime = std::chrono::system_clock::now(); - - /** - * The number of times this BaseNode has received a bad gRPC status. - */ - unsigned int mBadGrpcStatusCount = 0U; - - /** - * Is the gRPC channel being utilized by this BaseNode to communicate with its remote node initialized? - */ - bool mIsConnected = false; - - /** - * The mutex for this BaseNode, kept inside a std::shared_ptr to keep BaseNetwork copyable/movable. - */ - std::shared_ptr mMutex = std::make_shared(); -}; - -} // namespace Hiero::internal - -#endif // HIERO_SDK_CPP_IMPL_BASE_NODE_H_ From 6d14a74a46d26796d83feb63e4513f4c29166016 Mon Sep 17 00:00:00 2001 From: Mohit Yadav Date: Sun, 14 Jun 2026 18:58:29 +0530 Subject: [PATCH 4/6] Delete src/sdk/main/src/AccountId.cc Signed-off-by: Mohit Yadav --- src/sdk/main/src/AccountId.cc | 327 ---------------------------------- 1 file changed, 327 deletions(-) delete mode 100644 src/sdk/main/src/AccountId.cc diff --git a/src/sdk/main/src/AccountId.cc b/src/sdk/main/src/AccountId.cc deleted file mode 100644 index c274620d2..000000000 --- a/src/sdk/main/src/AccountId.cc +++ /dev/null @@ -1,327 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. -#include // NOLINT - -#include "AccountId.h" -#include "Client.h" -#include "LedgerId.h" -#include "PublicKey.h" -#include "exceptions/BadKeyException.h" -#include "exceptions/IllegalStateException.h" -#include "exceptions/UninitializedException.h" - -#include "impl/EntityIdHelper.h" -#include "impl/HttpClient.h" -#include "impl/MirrorNetwork.h" -#include "impl/Utilities.h" - -#include - -#include -#include - -using json = nlohmann::json; - -namespace Hiero -{ -//----- -AccountId::AccountId(uint64_t num) - : mAccountNum(num) -{ -} - -//----- -AccountId::AccountId(const std::shared_ptr& alias) - : mPublicKeyAlias(alias) -{ -} - -//----- -AccountId::AccountId(const EvmAddress& address) - : mEvmAddressAlias(address) -{ -} - -//----- -AccountId::AccountId(uint64_t shard, uint64_t realm, uint64_t num, std::string_view checksum) - : mShardNum(shard) - , mRealmNum(realm) - , mAccountNum(num) - , mChecksum(checksum) -{ -} - -//----- -AccountId::AccountId(uint64_t shard, uint64_t realm, const std::shared_ptr& alias) - : mShardNum(shard) - , mRealmNum(realm) - , mPublicKeyAlias(alias) -{ -} - -//----- -AccountId::AccountId(uint64_t shard, uint64_t realm, const EvmAddress& address) - : mShardNum(shard) - , mRealmNum(realm) - , mEvmAddressAlias(address) -{ -} - -//----- -bool AccountId::operator==(const AccountId& other) const -{ - return (mShardNum == other.mShardNum) && (mRealmNum == other.mRealmNum) && - ((mAccountNum && other.mAccountNum && mAccountNum == other.mAccountNum) || - (mPublicKeyAlias && other.mPublicKeyAlias && - mPublicKeyAlias->toStringDer() == other.mPublicKeyAlias->toStringDer()) || - (mEvmAddressAlias && other.mEvmAddressAlias && - mEvmAddressAlias->toString() == other.mEvmAddressAlias->toString()) || - (!mAccountNum && !other.mAccountNum && !mPublicKeyAlias && !other.mPublicKeyAlias && !mEvmAddressAlias && - !other.mEvmAddressAlias)); -} - -//----- -AccountId AccountId::fromString(std::string_view id) -{ - // First try the input id as an EvmAddress. If not an EvmAddress, process as normal. - try - { - return fromEvmAddress(id); - } - catch (const std::invalid_argument&) - { - // Get the shard and realm numbers. - const uint64_t shard = internal::EntityIdHelper::getShardNum(id); - const uint64_t realm = internal::EntityIdHelper::getRealmNum(id); - - // Determine what the entity ID number is. First try to see if it's just an account number. Get the entity number - // string before the try-block to verify the input ID isn't malformed. - const std::string_view entityNum = internal::EntityIdHelper::getEntityNumStr(id); - const std::string_view checksum = internal::EntityIdHelper::getChecksum(id); - try - { - return AccountId(shard, realm, internal::EntityIdHelper::getNum(entityNum), checksum); - } - catch (const std::invalid_argument&) - { - // If the entity number isn't an account number, it's an alias. Aliases cannot have checksums, so verify that - // first. - if (!checksum.empty()) - { - throw std::invalid_argument("Account ID aliases can't have checksums"); - } - - // First try the alias as a PublicKey. - try - { - return AccountId(shard, realm, PublicKey::fromStringDer(entityNum)); - } - catch (const BadKeyException&) - { - // If not a PublicKey, it must be an EVM address. - try - { - return AccountId(shard, realm, EvmAddress::fromString(entityNum)); - } - catch (const std::invalid_argument&) - { - // If not an EVM address, the entity ID cannot be realized. - throw std::invalid_argument(std::string("Account number/alias cannot be realized from ") + entityNum.data()); - } - } - } - } -} - -//----- -AccountId AccountId::fromEvmAddress(std::string_view evmAddress, uint64_t shard, uint64_t realm) -{ - return fromEvmAddress(EvmAddress::fromString(evmAddress), shard, realm); -} - -//----- -AccountId AccountId::fromEvmAddress(const EvmAddress& evmAddress, uint64_t shard, uint64_t realm) -{ - return AccountId(shard, realm, evmAddress); -} - -//----- -AccountId AccountId::fromSolidityAddress(std::string_view address) -{ - return fromEvmAddress(address); -} - -//----- -AccountId AccountId::fromProtobuf(const proto::AccountID& proto) -{ - AccountId accountId; - accountId.mShardNum = static_cast(proto.shardnum()); - accountId.mRealmNum = static_cast(proto.realmnum()); - - switch (proto.account_case()) - { - case proto::AccountID::kAccountNum: - { - accountId.mAccountNum = static_cast(proto.accountnum()); - break; - } - case proto::AccountID::kAlias: - { - if (proto.alias().size() == EvmAddress::NUM_BYTES) - { - accountId.mEvmAddressAlias = EvmAddress::fromBytes(internal::Utilities::stringToByteVector(proto.alias())); - } - else - { - accountId.mPublicKeyAlias = PublicKey::fromAliasBytes(internal::Utilities::stringToByteVector(proto.alias())); - } - break; - } - default: - break; - } - - return accountId; -} - -//----- -AccountId AccountId::fromBytes(const std::vector& bytes) -{ - proto::AccountID proto; - proto.ParseFromArray(bytes.data(), static_cast(bytes.size())); - return fromProtobuf(proto); -} - -//----- -void AccountId::validateChecksum(const Client& client) const -{ - if (mAccountNum.has_value() && !mChecksum.empty()) - { - internal::EntityIdHelper::validate(mShardNum, mRealmNum, mAccountNum.value(), client, mChecksum); - } -} - -//----- -std::unique_ptr AccountId::toProtobuf() const -{ - auto proto = std::make_unique(); - proto->set_shardnum(static_cast(mShardNum)); - proto->set_realmnum(static_cast(mRealmNum)); - - if (mAccountNum) - { - proto->set_accountnum(static_cast(*mAccountNum)); - } - else if (mPublicKeyAlias) - { - proto->set_alias(mPublicKeyAlias->toProtobufKey()->SerializeAsString()); - } - else if (mEvmAddressAlias) - { - proto->set_alias(internal::Utilities::byteVectorToString(mEvmAddressAlias->toBytes())); - } - - return proto; -} - -//----- -std::string AccountId::toSolidityAddress() const -{ - if (mEvmAddressAlias.has_value()) - { - return mEvmAddressAlias.value().toString(); - } - else if (mAccountNum.has_value()) - { - return internal::EntityIdHelper::toSolidityAddress(mShardNum, mRealmNum, mAccountNum.value()); - } - else - { - throw IllegalStateException("AccountId must contain an account number to generate a Solidity address"); - } -} - -//----- -AccountId& AccountId::populateAccountEvmAddress(const Client& client) -{ - if (!mAccountNum.has_value()) - { - throw new IllegalStateException("member `mAccountNum` should not be empty"); - } - - std::vector mirrorNetworks = client.getClientMirrorNetwork()->getNetwork(); - if (mirrorNetworks.empty()) - { - throw new UninitializedException("mirrorNetworks vector not populated!"); - } - - // build url for Mirror Node - std::string url = "https://" + mirrorNetworks.front() + "/api/v1/accounts/" + toString(); - - // fetch account data for this account from Mirror Node - std::string response = internal::HttpClient::invokeREST(url, "GET"); - json responseData = json::parse(response); - - if (responseData["account"].empty() || responseData["evm_address"].empty()) - { - throw new IllegalStateException("No such account in MirrorNetwork: " + responseData.dump()); - } - - std::string evmAddress = responseData["evm_address"].dump(); - // json dump returns strings in dquotes, so we need to trim first and last characters - evmAddress = evmAddress.substr(1, evmAddress.length() - 2); - - mEvmAddressAlias = EvmAddress::fromString(evmAddress); - - return *this; -} - -//----- -std::string AccountId::toString() const -{ - std::string str = std::to_string(mShardNum) + '.' + std::to_string(mRealmNum) + '.'; - - if (mPublicKeyAlias) - { - return str + mPublicKeyAlias->toStringDer(); - } - else if (mEvmAddressAlias.has_value()) - { - return str + mEvmAddressAlias->toString(); - } - else if (mAccountNum.has_value()) - { - return str + std::to_string(*mAccountNum); - } - else - { - // Uninitialized case - return str + '0'; - } -} - -//----- -std::string AccountId::toStringWithChecksum(const Client& client) const -{ - // Checksums are only valid for accounts not using an alias. - if (!mAccountNum.has_value()) - { - throw IllegalStateException("Checksums can only be generated for AccountIds that have an account number"); - } - - if (mChecksum.empty()) - { - mChecksum = internal::EntityIdHelper::checksum( - internal::EntityIdHelper::toString(mShardNum, mRealmNum, mAccountNum.value()), client.getLedgerId()); - } - - return internal::EntityIdHelper::toString(mShardNum, mRealmNum, mAccountNum.value(), mChecksum); -} - -//----- -std::vector AccountId::toBytes() const -{ - return internal::Utilities::stringToByteVector(toProtobuf()->SerializeAsString()); -} - -} // namespace Hiero From 261a48e7870cbf758180fedc5ee2ad34d941b9df Mon Sep 17 00:00:00 2001 From: Mohit Yadav Date: Sun, 14 Jun 2026 18:59:00 +0530 Subject: [PATCH 5/6] Delete src/tck/src/TckServer.cc Signed-off-by: Mohit Yadav --- src/tck/src/TckServer.cc | 298 --------------------------------------- 1 file changed, 298 deletions(-) delete mode 100644 src/tck/src/TckServer.cc diff --git a/src/tck/src/TckServer.cc b/src/tck/src/TckServer.cc deleted file mode 100644 index b0dd85dd9..000000000 --- a/src/tck/src/TckServer.cc +++ /dev/null @@ -1,298 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers reached transitively from this header. -#include // NOLINT - -#include "TckServer.h" -#include "account/AccountService.h" -#include "account/params/ApproveAllowanceParams.h" -#include "account/params/CreateAccountParams.h" -#include "account/params/DeleteAccountParams.h" -#include "account/params/DeleteAllowanceParams.h" -#include "account/params/GetAccountBalanceParams.h" -#include "account/params/GetAccountInfoParams.h" -#include "account/params/TransferCryptoParams.h" -#include "account/params/UpdateAccountParams.h" -#include "contract/ContractService.h" -#include "contract/params/ContractByteCodeQueryParams.h" -#include "contract/params/ContractCallQueryParams.h" -#include "contract/params/ContractInfoQueryParams.h" -#include "contract/params/CreateContractParams.h" -#include "contract/params/DeleteContractParams.h" -#include "contract/params/ExecuteContractParams.h" -#include "contract/params/UpdateContractParams.h" -#include "file/FileService.h" -#include "file/params/AppendFileParams.h" -#include "file/params/CreateFileParams.h" -#include "file/params/DeleteFileParams.h" -#include "file/params/GetFileContentsParams.h" -#include "file/params/GetFileInfoParams.h" -#include "file/params/UpdateFileParams.h" -#include "key/KeyService.h" -#include "key/params/GenerateKeyParams.h" -#include "schedule/ScheduleService.h" -#include "schedule/params/CreateScheduleParams.h" -#include "schedule/params/DeleteScheduleParams.h" -#include "schedule/params/GetScheduleInfoParams.h" -#include "schedule/params/SignScheduleParams.h" -#include "sdk/SdkClient.h" -#include "sdk/params/ResetParams.h" -#include "sdk/params/SetupParams.h" -#include "token/TokenService.h" -#include "token/params/AirdropTokenParams.h" -#include "token/params/AssociateTokenParams.h" -#include "token/params/BurnTokenParams.h" -#include "token/params/CancelAirdropParams.h" -#include "token/params/ClaimAirdropParams.h" -#include "token/params/CreateTokenParams.h" -#include "token/params/DeleteTokenParams.h" -#include "token/params/DissociateTokenParams.h" -#include "token/params/FreezeTokenParams.h" -#include "token/params/GrantTokenKycParams.h" -#include "token/params/MintTokenParams.h" -#include "token/params/PauseTokenParams.h" -#include "token/params/RevokeTokenKycParams.h" -#include "token/params/TokenRejectParams.h" -#include "token/params/UnfreezeTokenParams.h" -#include "token/params/UnpauseTokenParams.h" -#include "token/params/UpdateTokenFeeScheduleParams.h" -#include "token/params/UpdateTokenParams.h" -#include "token/params/WipeTokenParams.h" -#include "topic/TopicService.h" -#include "topic/params/CreateTopicParams.h" -#include "topic/params/DeleteTopicParams.h" -#include "topic/params/GetTopicInfoQueryParams.h" -#include "topic/params/TopicMessageSubmitParams.h" -#include "json/JsonUtils.h" - -namespace Hiero::TCK -{ - -//----- -TckServer::TckServer() - : TckServer(DEFAULT_HTTP_PORT) -{ -} - -//----- -TckServer::TckServer(int port) -{ - // Register Methods with the new JsonRpcParser - - // Add the SDK client functions. - mJsonRpcParser.addMethod("setup", getHandle(SdkClient::setup)); - mJsonRpcParser.addMethod("reset", getHandle(SdkClient::reset)); - - // Add the KeyService functions. - mJsonRpcParser.addMethod("generateKey", getHandle(KeyService::generateKey)); - - // Add the AccountService functions. - mJsonRpcParser.addMethod("approveAllowance", getHandle(AccountService::approveAllowance)); - mJsonRpcParser.addMethod("createAccount", getHandle(AccountService::createAccount)); - mJsonRpcParser.addMethod("deleteAllowance", getHandle(AccountService::deleteAllowance)); - mJsonRpcParser.addMethod("deleteAccount", getHandle(AccountService::deleteAccount)); - mJsonRpcParser.addMethod("getAccountBalance", getHandle(AccountService::getAccountBalance)); - mJsonRpcParser.addMethod("getAccountInfo", getHandle(AccountService::getAccountInfo)); - mJsonRpcParser.addMethod("transferCrypto", getHandle(AccountService::transferCrypto)); - mJsonRpcParser.addMethod("updateAccount", getHandle(AccountService::updateAccount)); - - mJsonRpcParser.addMethod("airdropToken", getHandle(TokenService::airdropToken)); - mJsonRpcParser.addMethod("associateToken", getHandle(TokenService::associateToken)); - mJsonRpcParser.addMethod("burnToken", getHandle(TokenService::burnToken)); - mJsonRpcParser.addMethod("cancelAirdrop", getHandle(TokenService::cancelAirdrop)); - mJsonRpcParser.addMethod("claimAirdrop", getHandle(TokenService::claimAirdrop)); - mJsonRpcParser.addMethod("createToken", getHandle(TokenService::createToken)); - mJsonRpcParser.addMethod("deleteToken", getHandle(TokenService::deleteToken)); - mJsonRpcParser.addMethod("dissociateToken", getHandle(TokenService::dissociateToken)); - mJsonRpcParser.addMethod("freezeToken", getHandle(TokenService::freezeToken)); - mJsonRpcParser.addMethod("grantTokenKyc", getHandle(TokenService::grantTokenKyc)); - mJsonRpcParser.addMethod("mintToken", getHandle(TokenService::mintToken)); - mJsonRpcParser.addMethod("pauseToken", getHandle(TokenService::pauseToken)); - mJsonRpcParser.addMethod("rejectToken", getHandle(TokenService::rejectToken)); - mJsonRpcParser.addMethod("revokeTokenKyc", getHandle(TokenService::revokeTokenKyc)); - mJsonRpcParser.addMethod("unfreezeToken", getHandle(TokenService::unfreezeToken)); - mJsonRpcParser.addMethod("unpauseToken", getHandle(TokenService::unpauseToken)); - mJsonRpcParser.addMethod("updateToken", getHandle(TokenService::updateToken)); - mJsonRpcParser.addMethod("updateTokenFeeSchedule", getHandle(TokenService::updateTokenFeeSchedule)); - mJsonRpcParser.addMethod("wipeToken", getHandle(TokenService::wipeToken)); - - // Topic Service - mJsonRpcParser.addMethod("createTopic", getHandle(TopicService::createTopic)); - mJsonRpcParser.addMethod("deleteTopic", getHandle(TopicService::deleteTopic)); - mJsonRpcParser.addMethod("getTopicInfo", getHandle(TopicService::getTopicInfo)); - mJsonRpcParser.addMethod("submitTopicMessage", getHandle(TopicService::submitTopicMessage)); - - // Contract Service - mJsonRpcParser.addMethod("createContract", getHandle(ContractService::createContract)); - mJsonRpcParser.addMethod("contractByteCodeQuery", getHandle(ContractService::contractByteCodeQuery)); - mJsonRpcParser.addMethod("contractCallQuery", getHandle(ContractService::contractCallQuery)); - mJsonRpcParser.addMethod("contractInfoQuery", getHandle(ContractService::contractInfoQuery)); - mJsonRpcParser.addMethod("deleteContract", getHandle(ContractService::deleteContract)); - mJsonRpcParser.addMethod("executeContract", getHandle(ContractService::executeContract)); - mJsonRpcParser.addMethod("updateContract", getHandle(ContractService::updateContract)); - - // Add the FileService functions. - mJsonRpcParser.addMethod("appendFile", getHandle(FileService::appendFile)); - mJsonRpcParser.addMethod("createFile", getHandle(FileService::createFile)); - mJsonRpcParser.addMethod("deleteFile", getHandle(FileService::deleteFile)); - mJsonRpcParser.addMethod("getFileContents", getHandle(FileService::getFileContents)); - mJsonRpcParser.addMethod("getFileInfo", getHandle(FileService::getFileInfo)); - mJsonRpcParser.addMethod("updateFile", getHandle(FileService::updateFile)); - - // Schedule Service - mJsonRpcParser.addMethod("createSchedule", getHandle(ScheduleService::createSchedule)); - mJsonRpcParser.addMethod("deleteSchedule", getHandle(ScheduleService::deleteSchedule)); - mJsonRpcParser.addMethod("getScheduleInfo", getHandle(ScheduleService::getScheduleInfo)); - mJsonRpcParser.addMethod("signSchedule", getHandle(ScheduleService::signSchedule)); - - setupHttpHandler(); - mServer.listen("localhost", port); -} - -//----- -template -TckServer::MethodHandle TckServer::getHandle(nlohmann::json (*method)(const ParamsType&)) -{ - return [method](const nlohmann::json& params) { return method(params.get()); }; -} - -//----- -template -TckServer::NotificationHandle TckServer::getHandle(void (*notification)(const ParamsType&)) -{ - return [notification](const nlohmann::json& params) { notification(params.get()); }; -} - -//----- -void TckServer::setupHttpHandler() -{ - mServer.Post("/", - [this](const httplib::Request& request, httplib::Response& response) - { handleHttpRequest(request, response); }); -} - -//----- -void TckServer::handleHttpRequest(const httplib::Request& request, httplib::Response& response) -{ - const std::string jsonResponse = handleJsonRequest(request.body); - if (jsonResponse.empty()) - { - response.status = 204; - } - else - { - response.status = 200; - response.set_content(jsonResponse, "application/json"); - } -} - -//----- -std::string TckServer::handleJsonRequest(const std::string& request) -{ - return mJsonRpcParser.handle(request); -} - -// Explicit template instantiations -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const SdkClient::SetupParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const SdkClient::ResetParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::CreateAccountParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::UpdateAccountParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::DeleteAccountParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::GetAccountBalanceParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::GetAccountInfoParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::TransferCryptoParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::ApproveAllowanceParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const AccountService::DeleteAllowanceParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::CreateContractParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::ContractByteCodeQueryParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::ContractCallQueryParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::ContractInfoQueryParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::DeleteContractParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::ExecuteContractParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ContractService::UpdateContractParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const KeyService::GenerateKeyParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::CreateTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::UpdateTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::MintTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::BurnTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::AssociateTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::DissociateTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::UpdateTokenFeeScheduleParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::UnpauseTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::PauseTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::FreezeTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::UnfreezeTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::WipeTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::DeleteTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::GrantTokenKycParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::RevokeTokenKycParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::RejectTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::AirdropTokenParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::CancelAirdropParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TokenService::ClaimAirdropParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::AppendFileParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::CreateFileParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::DeleteFileParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::GetFileContentsParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::GetFileInfoParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const FileService::UpdateFileParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TopicService::CreateTopicParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TopicService::DeleteTopicParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TopicService::GetTopicInfoQueryParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const TopicService::TopicMessageSubmitParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ScheduleService::CreateScheduleParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ScheduleService::DeleteScheduleParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ScheduleService::GetScheduleInfoParams&)); -template TckServer::MethodHandle TckServer::getHandle( - nlohmann::json (*method)(const ScheduleService::SignScheduleParams&)); - -} // namespace Hiero::TCK From d9d294ef8b9b48656fa32c1d525bd7c9f6b0e0d5 Mon Sep 17 00:00:00 2001 From: Mohit Yadav Date: Sun, 14 Jun 2026 18:59:32 +0530 Subject: [PATCH 6/6] Delete src/sdk/main/src/FeeEstimateQuery.cc Signed-off-by: Mohit Yadav --- src/sdk/main/src/FeeEstimateQuery.cc | 368 --------------------------- 1 file changed, 368 deletions(-) delete mode 100644 src/sdk/main/src/FeeEstimateQuery.cc diff --git a/src/sdk/main/src/FeeEstimateQuery.cc b/src/sdk/main/src/FeeEstimateQuery.cc deleted file mode 100644 index b0a071c97..000000000 --- a/src/sdk/main/src/FeeEstimateQuery.cc +++ /dev/null @@ -1,368 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Must be included before any header that pulls in , whose macros (e.g. GetMessage) collide with identifiers in the generated protobuf code. -#include // NOLINT - -#include "Client.h" -#include "FeeEstimateQuery.h" -#include "FileAppendTransaction.h" -#include "TopicMessageSubmitTransaction.h" -#include "exceptions/IllegalStateException.h" -#include "impl/HttpClient.h" -#include "impl/MirrorNetwork.h" - -#include -#include -#include -#include -#include - -#include -#include - -namespace Hiero -{ -namespace -{ -constexpr uint16_t MAX_HIGH_VOLUME_THROTTLE = 10000; -constexpr int HTTP_OK = 200; -constexpr uint64_t BACKOFF_INITIAL_MS = 250; -constexpr uint64_t BACKOFF_CAP_MS = 8000; -constexpr uint16_t LOCAL_MIRROR_REST_PORT = 8084; -constexpr std::string_view HTTP_SCHEME = "http://"; -constexpr std::string_view HTTPS_SCHEME = "https://"; - -//----- -// Generic auto-freeze: visit the variant and call freezeWith() on whichever transaction is held. -void freezeIfNeeded(WrappedTransaction& wrapped, const Client& client) -{ - std::visit( - [&client](auto& tx) - { - if (!tx.isFrozen()) - { - tx.freezeWith(&client); - } - }, - wrapped.getVariant()); -} - -//----- -// Result of a single mirror-node HTTP attempt. statusCode == 200 indicates success and `body` is the -// response body. Otherwise `errorMessage` describes why the attempt failed and `statusCode` / -// `isTimeout` drive the retry decision. -struct AttemptResult -{ - std::string body; - int statusCode = 0; - bool isTimeout = false; - std::string errorMessage; -}; - -//----- -AttemptResult performSingleAttempt(const std::string& url, const std::string& txBytes) -{ - AttemptResult result; - try - { - result.body = internal::HttpClient::invokeRESTWithStatus( - url, "POST", txBytes, "application/protobuf", result.statusCode, result.isTimeout); - if (result.statusCode != HTTP_OK) - { - result.errorMessage = "HTTP " + std::to_string(result.statusCode) + " - " + result.body; - } - } - catch (const std::exception& e) - { - result.errorMessage = e.what(); - } - return result; -} - -//----- -FeeEstimateResponse parseFeeEstimateJson(const std::string& body) -{ - try - { - return FeeEstimateResponse::fromJson(nlohmann::json::parse(body)); - } - catch (const nlohmann::json::exception& e) - { - throw IllegalStateException(std::string("Failed to parse fee estimate response: ") + e.what()); - } -} - -//----- -void backoffSleep(uint64_t attempt) -{ - auto delayMs = static_cast(static_cast(BACKOFF_INITIAL_MS) * static_cast(1ULL << attempt)); - if (delayMs > BACKOFF_CAP_MS) - { - delayMs = BACKOFF_CAP_MS; - } - std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); -} - -//----- -bool hasHttpScheme(std::string_view url) -{ - // string_view::substr clamps n to the remaining length, so this is bounds-safe even when url is - // shorter than the scheme prefix. - return url.substr(0, HTTP_SCHEME.size()) == HTTP_SCHEME || url.substr(0, HTTPS_SCHEME.size()) == HTTPS_SCHEME; -} - -//----- -bool isLocalHostUrl(std::string_view url) -{ - return url.find("localhost") != std::string_view::npos || url.find("127.0.0.1") != std::string_view::npos; -} - -//----- -// Apply scheme prefix and (for local solo networks) rewrite the port to the mirror REST port 8084. -std::string normalizeMirrorBaseUrl(std::string_view mirrorUrl) -{ - constexpr std::string_view SCHEME_SEPARATOR = "://"; - const bool localHost = isLocalHostUrl(mirrorUrl); - - std::string url; - if (!hasHttpScheme(mirrorUrl)) - { - url.append(localHost ? HTTP_SCHEME : HTTPS_SCHEME); - } - url.append(mirrorUrl); - - if (localHost) - { - // Search for the host:port colon strictly after the scheme separator so we never accidentally - // match the colon inside "://". - const size_t schemeEnd = url.find(SCHEME_SEPARATOR); - const size_t searchFrom = (schemeEnd == std::string::npos) ? 0 : schemeEnd + SCHEME_SEPARATOR.size(); - const size_t portPos = url.find(':', searchFrom); - if (portPos != std::string::npos) - { - url.replace(portPos, std::string::npos, ":" + std::to_string(LOCAL_MIRROR_REST_PORT)); - } - } - return url; -} - -} // namespace - -//----- -FeeEstimateResponse FeeEstimateQuery::execute(const Client& client) -{ - if (!mTransaction.has_value()) - { - throw std::invalid_argument("FeeEstimateQuery requires a transaction to be set via setTransaction()"); - } - - if (client.getMirrorNetwork().empty()) - { - throw IllegalStateException("Mirror network is not set on the client"); - } - - freezeIfNeeded(*mTransaction, client); - - // Detect chunked transactions and dispatch to the per-chunk aggregation path when more than one chunk is - // required. - if (auto* fileAppend = mTransaction->getTransaction()) - { - if (fileAppend->getNumberOfChunksRequired() > 1) - { - return estimateChunkedTransaction(client, fileAppend->getChunkedTransactionProtobufObjects()); - } - } - else if (auto* topicSubmit = mTransaction->getTransaction()) - { - if (topicSubmit->getNumberOfChunksRequired() > 1) - { - return estimateChunkedTransaction(client, topicSubmit->getChunkedTransactionProtobufObjects()); - } - } - - return estimateSingleTransaction(client); -} - -//----- -FeeEstimateQuery& FeeEstimateQuery::setMode(FeeEstimateMode mode) -{ - mMode = mode; - return *this; -} - -//----- -FeeEstimateMode FeeEstimateQuery::getMode() const -{ - return mMode; -} - -//----- -FeeEstimateQuery& FeeEstimateQuery::setTransaction(const WrappedTransaction& transaction) -{ - mTransaction = transaction; - return *this; -} - -//----- -const WrappedTransaction* FeeEstimateQuery::getTransaction() const -{ - return mTransaction.has_value() ? &mTransaction.value() : nullptr; -} - -//----- -FeeEstimateQuery& FeeEstimateQuery::setHighVolumeThrottle(uint16_t throttle) -{ - if (throttle > MAX_HIGH_VOLUME_THROTTLE) - { - throw std::invalid_argument("highVolumeThrottle must be in [0, 10000] basis points"); - } - mHighVolumeThrottle = throttle; - return *this; -} - -//----- -uint16_t FeeEstimateQuery::getHighVolumeThrottle() const -{ - return mHighVolumeThrottle; -} - -//----- -FeeEstimateQuery& FeeEstimateQuery::setMaxAttempts(uint64_t maxAttempts) -{ - mMaxAttempts = maxAttempts; - return *this; -} - -//----- -uint64_t FeeEstimateQuery::getMaxAttempts() const -{ - return mMaxAttempts; -} - -//----- -FeeEstimateResponse FeeEstimateQuery::callGetFeeEstimate(const Client& client, const proto::Transaction& protoTx) -{ - const std::string url = buildMirrorNodeUrl(client); - const std::string txBytes = protoTx.SerializeAsString(); - - std::string lastError; - for (mAttempt = 0; mAttempt < mMaxAttempts; ++mAttempt) - { - const AttemptResult attempt = performSingleAttempt(url, txBytes); - if (attempt.statusCode == HTTP_OK) - { - return parseFeeEstimateJson(attempt.body); - } - if (!shouldRetry(attempt.statusCode, attempt.isTimeout)) - { - throw IllegalStateException("Fee estimate API returned status " + std::to_string(attempt.statusCode) + ": " + - attempt.errorMessage); - } - lastError = attempt.errorMessage; - backoffSleep(mAttempt); - } - - throw IllegalStateException("Failed to call fee estimate API after " + std::to_string(mMaxAttempts) + - " attempts: " + lastError); -} - -//----- -FeeEstimateResponse FeeEstimateQuery::estimateSingleTransaction(const Client& client) -{ - std::unique_ptr protoTx = mTransaction->toProtobufTransaction(); - if (!protoTx) - { - throw IllegalStateException("Failed to build protobuf transaction"); - } - return callGetFeeEstimate(client, *protoTx); -} - -//----- -FeeEstimateResponse FeeEstimateQuery::estimateChunkedTransaction(const Client& client, - std::vector chunkProtos) -{ - std::vector perChunk; - perChunk.reserve(chunkProtos.size()); - for (const auto& chunk : chunkProtos) - { - perChunk.push_back(callGetFeeEstimate(client, chunk)); - } - return aggregateChunkResponses(perChunk); -} - -//----- -FeeEstimateResponse FeeEstimateQuery::aggregateChunkResponses(const std::vector& chunks) -{ - FeeEstimateResponse aggregated; - if (chunks.empty()) - { - return aggregated; - } - - uint64_t aggregatedNodeTotal = 0; - uint64_t aggregatedServiceTotal = 0; - uint64_t maxHighVolumeMultiplier = 0; - - for (const auto& chunk : chunks) - { - aggregatedNodeTotal += chunk.mNode.subtotal(); - aggregatedServiceTotal += chunk.mService.subtotal(); - maxHighVolumeMultiplier = std::max(maxHighVolumeMultiplier, chunk.mHighVolumeMultiplier); - - aggregated.mNode.mExtras.insert( - aggregated.mNode.mExtras.end(), chunk.mNode.mExtras.cbegin(), chunk.mNode.mExtras.cend()); - aggregated.mService.mExtras.insert( - aggregated.mService.mExtras.end(), chunk.mService.mExtras.cbegin(), chunk.mService.mExtras.cend()); - aggregated.mNode.mBase += chunk.mNode.mBase; - aggregated.mService.mBase += chunk.mService.mBase; - } - - aggregated.mNetwork.mMultiplier = chunks.front().mNetwork.mMultiplier; - aggregated.mNetwork.mSubtotal = aggregatedNodeTotal * aggregated.mNetwork.mMultiplier; - aggregated.mHighVolumeMultiplier = maxHighVolumeMultiplier; - aggregated.mTotal = aggregated.mNetwork.mSubtotal + aggregatedNodeTotal + aggregatedServiceTotal; - - return aggregated; -} - -//----- -bool FeeEstimateQuery::shouldRetry(int statusCode, bool isTimeout) -{ - if (isTimeout) - { - return true; - } - - // Retry only on 500 / 503 per the HIP-1261 retry policy. - if (statusCode == 500 || statusCode == 503) - { - return true; - } - - // Do not retry on 400 (or any other 4xx — malformed transaction body). - if (statusCode >= 400 && statusCode < 500) - { - return false; - } - - return false; -} - -//----- -std::string FeeEstimateQuery::buildMirrorNodeUrl(const Client& client) const -{ - const auto mirrorNetwork = client.getMirrorNetwork(); - if (mirrorNetwork.empty()) - { - throw IllegalStateException("Mirror network is not set"); - } - - std::string url = - normalizeMirrorBaseUrl(mirrorNetwork[0]) + "/api/v1/network/fees?mode=" + gFeeEstimateModeToString.at(mMode); - if (mHighVolumeThrottle != 0) - { - url += "&high_volume_throttle=" + std::to_string(mHighVolumeThrottle); - } - return url; -} - -} // namespace Hiero