diff --git a/src/sdk/main/include/impl/EntityIdHelper.h b/src/sdk/main/include/impl/EntityIdHelper.h index da9a4ffe..7db025c9 100644 --- a/src/sdk/main/include/impl/EntityIdHelper.h +++ b/src/sdk/main/include/impl/EntityIdHelper.h @@ -20,6 +20,7 @@ #ifndef HEDERA_SDK_CPP_IMPL_ENTITY_ID_HELPER_H_ #define HEDERA_SDK_CPP_IMPL_ENTITY_ID_HELPER_H_ +#include #include #include #include @@ -55,12 +56,23 @@ template [[nodiscard]] EntityType fromSolidityAddress(const std::vector& address); /** - * Convert a string to a uint64_t. E.g. "123" will return 123. + * Convert a string to a number type. E.g. "123" will return 123. * * @param str The string to convert. - * @return The uint64_t contained in the string. + * @return The number type contained in the string. */ -[[nodiscard]] uint64_t getNum(std::string_view str); +template +[[nodiscard]] T getNum(std::string_view str) +{ + T num; + if (auto result = std::from_chars(str.data(), str.data() + str.size(), num); + result.ec != std::errc() || result.ptr != str.data() + str.size()) + { + throw std::invalid_argument("Input entity ID string is malformed"); + } + + return num; +} /** * Get the shard from an entity ID. diff --git a/src/sdk/main/src/impl/EntityIdHelper.cc b/src/sdk/main/src/impl/EntityIdHelper.cc index bc451451..b850017c 100644 --- a/src/sdk/main/src/impl/EntityIdHelper.cc +++ b/src/sdk/main/src/impl/EntityIdHelper.cc @@ -33,7 +33,6 @@ #include "impl/HexConverter.h" #include "impl/Utilities.h" -#include #include #include #include @@ -55,19 +54,6 @@ EntityType fromSolidityAddress(const std::vector& address) *internal::Utilities::toTypePtr(address.data() + 12)); } -//----- -uint64_t getNum(std::string_view str) -{ - uint64_t num; - if (auto result = std::from_chars(str.data(), str.data() + str.size(), num); - result.ec != std::errc() || result.ptr != str.data() + str.size()) - { - throw std::invalid_argument("Input entity ID string is malformed"); - } - - return num; -} - //----- uint64_t getShardNum(std::string_view id) { diff --git a/src/tck/include/CustomFeeSerializer.h b/src/tck/include/CustomFeeSerializer.h index 559848a5..e2715948 100644 --- a/src/tck/include/CustomFeeSerializer.h +++ b/src/tck/include/CustomFeeSerializer.h @@ -27,8 +27,10 @@ #include "CustomFractionalFee.h" #include "CustomRoyaltyFee.h" #include "JsonRpcException.h" +#include "impl/EntityIdHelper.h" #include +#include namespace nlohmann { @@ -152,13 +154,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: amount is REQUIRED for fixedFee fee types."); } - if (!jsonFrom["fixedFee"]["amount"].is_number_integer()) + if (!jsonFrom["fixedFee"]["amount"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: amount MUST be an int64."); + "invalid parameters: amount MUST be a string."); } - fixedFee->setAmount(jsonFrom["fixedFee"]["amount"].get()); + try + { + fixedFee->setAmount( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fixedFee"]["amount"].get())); + } + catch (const std::invalid_argument&) + { + fixedFee->setAmount( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fixedFee"]["amount"].get())); + } if (jsonFrom["fixedFee"].contains("denominatingTokenId")) { @@ -187,13 +198,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: numerator is REQUIRED for fractionalFee fee types."); } - if (!jsonFrom["fractionalFee"]["numerator"].is_number_integer()) + if (!jsonFrom["fractionalFee"]["numerator"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: numerator MUST be an int64."); + "invalid parameters: numerator MUST be a string."); } - fractionalFee->setNumerator(jsonFrom["fractionalFee"]["numerator"].get()); + try + { + fractionalFee->setNumerator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fractionalFee"]["numerator"].get())); + } + catch (const std::invalid_argument&) + { + fractionalFee->setNumerator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fractionalFee"]["numerator"].get())); + } if (!jsonFrom["fractionalFee"].contains("denominator")) { @@ -201,13 +221,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: denominator is REQUIRED for fractionalFee fee types."); } - if (!jsonFrom["fractionalFee"]["denominator"].is_number_integer()) + if (!jsonFrom["fractionalFee"]["denominator"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: denominator MUST be an int64."); + "invalid parameters: denominator MUST be a string."); } - fractionalFee->setDenominator(jsonFrom["fractionalFee"]["denominator"].get()); + try + { + fractionalFee->setDenominator(Hedera::internal::EntityIdHelper::getNum( + jsonFrom["fractionalFee"]["denominator"].get())); + } + catch (const std::invalid_argument&) + { + fractionalFee->setDenominator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fractionalFee"]["denominator"].get())); + } if (!jsonFrom["fractionalFee"].contains("minimumAmount")) { @@ -216,13 +245,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: minimumAmount is REQUIRED for fractionalFee fee types."); } - if (!jsonFrom["fractionalFee"]["minimumAmount"].is_number_integer()) + if (!jsonFrom["fractionalFee"]["minimumAmount"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: minimumAmount MUST be an int64."); + "invalid parameters: minimumAmount MUST be a string."); } - fractionalFee->setMinimumAmount(jsonFrom["fractionalFee"]["minimumAmount"].get()); + try + { + fractionalFee->setMinimumAmount(Hedera::internal::EntityIdHelper::getNum( + jsonFrom["fractionalFee"]["minimumAmount"].get())); + } + catch (const std::invalid_argument&) + { + fractionalFee->setMinimumAmount( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fractionalFee"]["minimumAmount"].get())); + } if (!jsonFrom["fractionalFee"].contains("maximumAmount")) { @@ -231,13 +269,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: maximumAmount is REQUIRED for fractionalFee fee types."); } - if (!jsonFrom["fractionalFee"]["maximumAmount"].is_number_integer()) + if (!jsonFrom["fractionalFee"]["maximumAmount"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: maximumAmount MUST be an int64."); + "invalid parameters: maximumAmount MUST be a string."); } - fractionalFee->setMaximumAmount(jsonFrom["fractionalFee"]["maximumAmount"].get()); + try + { + fractionalFee->setMaximumAmount(Hedera::internal::EntityIdHelper::getNum( + jsonFrom["fractionalFee"]["maximumAmount"].get())); + } + catch (const std::invalid_argument&) + { + fractionalFee->setMaximumAmount( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["fractionalFee"]["maximumAmount"].get())); + } if (!jsonFrom["fractionalFee"].contains("assessmentMethod")) { @@ -274,13 +321,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: numerator is REQUIRED for royaltyFee fee types."); } - if (!jsonFrom["royaltyFee"]["numerator"].is_number_integer()) + if (!jsonFrom["royaltyFee"]["numerator"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: numerator MUST be an int64."); + "invalid parameters: numerator MUST be a string."); } - royaltyFee->setNumerator(jsonFrom["royaltyFee"]["numerator"].get()); + try + { + royaltyFee->setNumerator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["royaltyFee"]["numerator"].get())); + } + catch (const std::invalid_argument&) + { + royaltyFee->setNumerator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["royaltyFee"]["numerator"].get())); + } if (!jsonFrom["royaltyFee"].contains("denominator")) { @@ -288,13 +344,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: denominator is REQUIRED for royaltyFee fee types."); } - if (!jsonFrom["royaltyFee"]["denominator"].is_number_integer()) + if (!jsonFrom["royaltyFee"]["denominator"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: denominator MUST be an int64."); + "invalid parameters: denominator MUST be a string."); } - royaltyFee->setDenominator(jsonFrom["royaltyFee"]["denominator"].get()); + try + { + royaltyFee->setDenominator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["royaltyFee"]["denominator"].get())); + } + catch (const std::invalid_argument&) + { + royaltyFee->setDenominator( + Hedera::internal::EntityIdHelper::getNum(jsonFrom["royaltyFee"]["denominator"].get())); + } if (jsonFrom["royaltyFee"].contains("fallbackFee")) { @@ -306,13 +371,22 @@ struct [[maybe_unused]] adl_serializer> "invalid parameters: amount is REQUIRED for a fallback fee."); } - if (!jsonFrom["royaltyFee"]["fallbackFee"]["amount"].is_number_integer()) + if (!jsonFrom["royaltyFee"]["fallbackFee"]["amount"].is_string()) { throw Hedera::TCK::JsonRpcException(Hedera::TCK::JsonErrorType::INVALID_PARAMS, - "invalid parameters: amount MUST be an int64."); + "invalid parameters: amount MUST be a string."); } - fallbackFee.setAmount(jsonFrom["royaltyFee"]["fallbackFee"]["amount"].get()); + try + { + fallbackFee.setAmount(Hedera::internal::EntityIdHelper::getNum( + jsonFrom["royaltyFee"]["fallbackFee"]["amount"].get())); + } + catch (const std::invalid_argument&) + { + fallbackFee.setAmount(Hedera::internal::EntityIdHelper::getNum( + jsonFrom["royaltyFee"]["fallbackFee"]["amount"].get())); + } if (jsonFrom["royaltyFee"]["fallbackFee"].contains("denominatingTokenId")) { diff --git a/src/tck/include/SdkClient.h b/src/tck/include/SdkClient.h index 1cb23289..6b6e59cd 100644 --- a/src/tck/include/SdkClient.h +++ b/src/tck/include/SdkClient.h @@ -95,7 +95,7 @@ nlohmann::json createAccount(const std::optional& key, nlohmann::json createToken(const std::optional& name, const std::optional& symbol, const std::optional& decimals, - const std::optional& initialSupply, + const std::optional& initialSupply, const std::optional& treasuryAccountId, const std::optional& adminKey, const std::optional& kycKey, @@ -103,13 +103,13 @@ nlohmann::json createToken(const std::optional& name, const std::optional& wipeKey, const std::optional& supplyKey, const std::optional& freezeDefault, - const std::optional& expirationTime, + const std::optional& expirationTime, const std::optional& autoRenewAccountId, - const std::optional& autoRenewPeriod, + const std::optional& autoRenewPeriod, const std::optional& memo, const std::optional& tokenType, const std::optional& supplyType, - const std::optional& maxSupply, + const std::optional& maxSupply, const std::optional& feeScheduleKey, const std::optional>>& customFees, const std::optional& pauseKey, diff --git a/src/tck/src/KeyHelper.cc b/src/tck/src/KeyHelper.cc index 6aabb0ff..52871d35 100644 --- a/src/tck/src/KeyHelper.cc +++ b/src/tck/src/KeyHelper.cc @@ -78,20 +78,21 @@ KeyRequest::KeyRequest(const std::string& type, //----- std::shared_ptr getHederaKey(const std::string& key) { + const std::vector keyBytes = internal::HexConverter::hexToBytes(key); try { - return PublicKey::fromStringDer(key); + return PublicKey::fromBytesDer(keyBytes); } catch (const BadKeyException&) { try { - return PrivateKey::fromStringDer(key); + return PrivateKey::fromBytesDer(keyBytes); } catch (const BadKeyException&) { proto::Key protoKey; - protoKey.ParseFromString(internal::Utilities::byteVectorToString(internal::HexConverter::hexToBytes(key))); + protoKey.ParseFromString(internal::Utilities::byteVectorToString(keyBytes)); return Hedera::Key::fromProtobuf(protoKey); } } diff --git a/src/tck/src/SdkClient.cc b/src/tck/src/SdkClient.cc index 177374df..09b2e7bb 100644 --- a/src/tck/src/SdkClient.cc +++ b/src/tck/src/SdkClient.cc @@ -35,7 +35,9 @@ #include "TokenType.h" #include "TransactionReceipt.h" #include "TransactionResponse.h" +#include "impl/EntityIdHelper.h" #include "impl/HexConverter.h" +#include "impl/Utilities.h" #include #include @@ -138,7 +140,7 @@ nlohmann::json SdkClient::createAccount(const std::optional& key, nlohmann::json SdkClient::createToken(const std::optional& name, const std::optional& symbol, const std::optional& decimals, - const std::optional& initialSupply, + const std::optional& initialSupply, const std::optional& treasuryAccountId, const std::optional& adminKey, const std::optional& kycKey, @@ -146,13 +148,13 @@ nlohmann::json SdkClient::createToken(const std::optional& name, const std::optional& wipeKey, const std::optional& supplyKey, const std::optional& freezeDefault, - const std::optional& expirationTime, + const std::optional& expirationTime, const std::optional& autoRenewAccountId, - const std::optional& autoRenewPeriod, + const std::optional& autoRenewPeriod, const std::optional& memo, const std::optional& tokenType, const std::optional& supplyType, - const std::optional& maxSupply, + const std::optional& maxSupply, const std::optional& feeScheduleKey, const std::optional>>& customFees, const std::optional& pauseKey, @@ -180,7 +182,14 @@ nlohmann::json SdkClient::createToken(const std::optional& name, if (initialSupply.has_value()) { - tokenCreateTransaction.setInitialSupply(initialSupply.value()); + try + { + tokenCreateTransaction.setInitialSupply(Hedera::internal::EntityIdHelper::getNum(initialSupply.value())); + } + catch (const std::invalid_argument&) + { + tokenCreateTransaction.setInitialSupply(Hedera::internal::EntityIdHelper::getNum(initialSupply.value())); + } } if (treasuryAccountId.has_value()) @@ -220,8 +229,18 @@ nlohmann::json SdkClient::createToken(const std::optional& name, if (expirationTime.has_value()) { - tokenCreateTransaction.setExpirationTime(std::chrono::system_clock::from_time_t(0) + - std::chrono::seconds(expirationTime.value())); + try + { + tokenCreateTransaction.setExpirationTime( + std::chrono::system_clock::from_time_t(0) + + std::chrono::seconds(Hedera::internal::EntityIdHelper::getNum(expirationTime.value()))); + } + catch (const std::invalid_argument&) + { + tokenCreateTransaction.setExpirationTime( + std::chrono::system_clock::from_time_t(0) + + std::chrono::seconds(Hedera::internal::EntityIdHelper::getNum(expirationTime.value()))); + } } if (autoRenewAccountId.has_value()) @@ -231,7 +250,16 @@ nlohmann::json SdkClient::createToken(const std::optional& name, if (autoRenewPeriod.has_value()) { - tokenCreateTransaction.setAutoRenewPeriod(std::chrono::seconds(autoRenewPeriod.value())); + try + { + tokenCreateTransaction.setAutoRenewPeriod( + std::chrono::seconds(Hedera::internal::EntityIdHelper::getNum(autoRenewPeriod.value()))); + } + catch (const std::invalid_argument&) + { + tokenCreateTransaction.setAutoRenewPeriod( + std::chrono::seconds(Hedera::internal::EntityIdHelper::getNum(autoRenewPeriod.value()))); + } } if (memo.has_value()) @@ -264,7 +292,14 @@ nlohmann::json SdkClient::createToken(const std::optional& name, if (maxSupply.has_value()) { - tokenCreateTransaction.setMaxSupply(maxSupply.value()); + try + { + tokenCreateTransaction.setMaxSupply(Hedera::internal::EntityIdHelper::getNum(maxSupply.value())); + } + catch (const std::invalid_argument&) + { + tokenCreateTransaction.setMaxSupply(Hedera::internal::EntityIdHelper::getNum(maxSupply.value())); + } } if (feeScheduleKey.has_value()) @@ -284,7 +319,7 @@ nlohmann::json SdkClient::createToken(const std::optional& name, if (metadata.has_value()) { - tokenCreateTransaction.setMetadata(internal::HexConverter::hexToBytes(metadata.value())); + tokenCreateTransaction.setMetadata(internal::Utilities::stringToByteVector(metadata.value())); } if (metadataKey.has_value()) @@ -339,7 +374,9 @@ nlohmann::json SdkClient::generateKey(const std::string& type, const std::optional>& keys) { nlohmann::json response; - response["key"] = processKeyRequest({ type, fromKey, threshold, keys }, response); + std::string key = processKeyRequest({ type, fromKey, threshold, keys }, response); + std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c) { return std::tolower(c); }); + response["key"] = key; return response; }