diff --git a/sdk/examples/CMakeLists.txt b/sdk/examples/CMakeLists.txt index ea7a5dfd6..07b179fb0 100644 --- a/sdk/examples/CMakeLists.txt +++ b/sdk/examples/CMakeLists.txt @@ -4,6 +4,7 @@ set(ACCOUNT_CREATE_WITH_HTS_EXAMPLE_NAME ${PROJECT_NAME}-account-create-with-hts set(ACCOUNT_CREATION_WAYS_EXAMPLE_NAME ${PROJECT_NAME}-account-creation-ways-example) set(AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME ${PROJECT_NAME}-auto-create-account-transfer-transaction-example) 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(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) @@ -33,6 +34,7 @@ add_executable(${ACCOUNT_CREATE_WITH_HTS_EXAMPLE_NAME} AccountCreateWithHtsExamp add_executable(${ACCOUNT_CREATION_WAYS_EXAMPLE_NAME} AccountCreationWaysExample.cc) add_executable(${AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME} AutoCreateAccountTransferTransactionExample.cc) add_executable(${CONSENSUS_PUB_SUB_EXAMPLE_NAME} ConsensusPubSubExample.cc) +add_executable(${CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME} ConsensusPubSubChunkedExample.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) @@ -80,6 +82,7 @@ target_link_libraries(${ACCOUNT_CREATE_WITH_HTS_EXAMPLE_NAME} PUBLIC ${PROJECT_N target_link_libraries(${ACCOUNT_CREATION_WAYS_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) target_link_libraries(${AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME} PUBLIC ${PROJECT_NAME}) 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(${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}) @@ -112,6 +115,7 @@ install(TARGETS ${ACCOUNT_CREATION_WAYS_EXAMPLE_NAME} ${AUTO_CREATE_ACCOUNT_TRANSFER_TRANSACTION_EXAMPLE_NAME} ${CONSENSUS_PUB_SUB_EXAMPLE_NAME} + ${CONSENSUS_PUB_SUB_CHUNKED_EXAMPLE_NAME} ${CREATE_ACCOUNT_EXAMPLE_NAME} ${CREATE_SIMPLE_CONTRACT_EXAMPLE_NAME} ${CREATE_STATEFUL_CONTRACT_EXAMPLE_NAME} diff --git a/sdk/examples/ConsensusPubSubChunkedExample.cc b/sdk/examples/ConsensusPubSubChunkedExample.cc new file mode 100644 index 000000000..bce68dd3c --- /dev/null +++ b/sdk/examples/ConsensusPubSubChunkedExample.cc @@ -0,0 +1,279 @@ +/*- + * + * 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 "Client.h" +#include "ECDSAsecp256k1PrivateKey.h" +#include "ED25519PrivateKey.h" +#include "SubscriptionHandle.h" +#include "TopicCreateTransaction.h" +#include "TopicId.h" +#include "TopicMessage.h" +#include "TopicMessageQuery.h" +#include "TopicMessageSubmitTransaction.h" +#include "TransactionReceipt.h" +#include "TransactionResponse.h" +#include "WrappedTransaction.h" +#include "impl/Utilities.h" + +#include +#include +#include + +using namespace Hedera; + +int main(int argc, char** argv) +{ + if (argc < 3) + { + std::cout << "Please input account ID and private key" << std::endl; + return 1; + } + + const AccountId operatorAccountId = AccountId::fromString(argv[1]); + const std::shared_ptr operatorPrivateKey = ED25519PrivateKey::fromString(argv[2]); + + // Get a client for the Hedera testnet, and set the operator account ID and key such that all generated transactions + // will be paid for by this account and be signed by this key. + Client client = Client::forTestnet(); + client.setOperator(operatorAccountId, operatorPrivateKey.get()); + + // Generate a submit key for the topic. + const std::shared_ptr submitKey = ECDSAsecp256k1PrivateKey::generatePrivateKey(); + + // Generate a topic. + const TopicId topicId = TopicCreateTransaction() + .setMemo("hedera-sdk-cpp/ConsensusPubSubChunkedExample") + .setSubmitKey(submitKey) + .execute(client) + .getReceipt(client) + .mTopicId.value(); + std::cout << "Created topic " << topicId.toString() << std::endl; + + // Wait for topic to propagate to the mirror nodes. + std::cout << "Waiting to propagate to mirror nodes"; + for (int i = 0; i < 10; ++i) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << '.'; + } + std::cout << std::endl; + + // Set up a mirror client to print out messages as they are received. + SubscriptionHandle handle = TopicMessageQuery().setTopicId(topicId).subscribe( + client, + [](const TopicMessage& message) + { + std::cout + << "Received message " << message.mSequenceNumber << " which reached consensus at " + << std::chrono::duration_cast(message.mConsensusTimestamp.time_since_epoch()).count() + << " and contains " << message.mContents.size() << " bytes." << std::endl; + }); + + const std::string bigContents = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur aliquam augue sem, ut mattis dui laoreet a. " + "Curabitur consequat est euismod, scelerisque metus et, tristique dui. Nulla commodo mauris ut faucibus ultricies. " + "Quisque venenatis nisl nec augue tempus, at efficitur elit eleifend. Duis pharetra felis metus, sed dapibus urna " + "vehicula id. Duis non venenatis turpis, sit amet ornare orci. Donec non interdum quam. Sed finibus nunc et risus " + "finibus, non sagittis lorem cursus. Proin pellentesque tempor aliquam. Sed congue nisl in enim bibendum, " + "condimentum vehicula nisi feugiat.\n" + "\n" + "Suspendisse non sodales arcu. Suspendisse sodales, lorem ac mollis blandit, ipsum neque porttitor nulla, et " + "sodales arcu ante fermentum tellus. Integer sagittis dolor sed augue fringilla accumsan. Cras vitae finibus arcu, " + "sit amet varius dolor. Etiam id finibus dolor, vitae luctus velit. Proin efficitur augue nec pharetra accumsan. " + "Aliquam lobortis nisl diam, vel fermentum purus finibus id. Etiam at finibus orci, et tincidunt turpis. Aliquam " + "imperdiet congue lacus vel facilisis. Phasellus id magna vitae enim dapibus vestibulum vitae quis augue. Morbi eu " + "consequat enim. Maecenas neque nulla, pulvinar sit amet consequat sed, tempor sed magna. Mauris lacinia sem " + "feugiat faucibus aliquet. Etiam congue non turpis at commodo. Nulla facilisi.\n" + "\n" + "Nunc velit turpis, cursus ornare fringilla eu, lacinia posuere leo. Mauris rutrum ultricies dui et suscipit. " + "Curabitur in euismod ligula. Curabitur vitae faucibus orci. Phasellus volutpat vestibulum diam sit amet " + "vestibulum. In vel purus leo. Nulla condimentum lectus vestibulum lectus faucibus, id lobortis eros consequat. " + "Proin mollis libero elit, vel aliquet nisi imperdiet et. Morbi ornare est velit, in vehicula nunc malesuada quis. " + "Donec vehicula convallis interdum.\n" + "\n" + "Integer pellentesque in nibh vitae aliquet. Ut at justo id libero dignissim hendrerit. Interdum et malesuada " + "fames ac ante ipsum primis in faucibus. Praesent quis ornare lectus. Nam malesuada non diam quis cursus. " + "Phasellus a libero ligula. Suspendisse ligula elit, congue et nisi sit amet, cursus euismod dolor. Morbi aliquam, " + "nulla a posuere pellentesque, diam massa ornare risus, nec eleifend neque eros et elit.\n" + "\n" + "Pellentesque a sodales dui. Sed in efficitur ante. Duis eget volutpat elit, et ornare est. Nam felis dolor, " + "placerat mattis diam id, maximus lobortis quam. Sed pellentesque lobortis sem sed placerat. Pellentesque augue " + "odio, molestie sed lectus sit amet, congue volutpat massa. Quisque congue consequat nunc id fringilla. Duis " + "semper nulla eget enim venenatis dapibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per " + "inceptos himenaeos. Pellentesque varius turpis nibh, sit amet malesuada mauris malesuada quis. Vivamus dictum " + "egestas placerat. Vivamus id augue elit.\n" + "\n" + "Cras fermentum volutpat eros, vitae euismod lorem viverra nec. Donec lectus augue, porta eleifend odio sit amet, " + "condimentum rhoncus urna. Nunc sed odio velit. Morbi non cursus odio, eget imperdiet erat. Nunc rhoncus massa non " + "neque volutpat, sit amet faucibus ante congue. Phasellus nec lorem vel leo accumsan lobortis. Maecenas id ligula " + "bibendum purus suscipit posuere ac eget diam. Nam in quam pretium, semper erat auctor, iaculis odio. Maecenas " + "placerat, nisi ac elementum tempor, felis nulla porttitor orci, ac rhoncus diam justo in elit. Etiam lobortis " + "fermentum ligula in tincidunt. Donec quis vestibulum nunc. Sed eros diam, interdum in porta lobortis, gravida eu " + "magna. Donec diam purus, finibus et sollicitudin quis, fringilla nec nisi. Pellentesque habitant morbi tristique " + "senectus et netus et malesuada fames ac turpis egestas. Curabitur ultricies sagittis dapibus. Etiam ullamcorper " + "aliquet libero, eu venenatis mauris suscipit id.\n" + "\n" + "Ut interdum eleifend sem, vel bibendum ipsum volutpat eget. Nunc ac dignissim augue. Aliquam ornare aliquet magna " + "id dignissim. Vestibulum velit sem, lacinia eu rutrum in, rhoncus vitae mauris. Pellentesque scelerisque pulvinar " + "mauris non cursus. Integer id dolor porta, bibendum sem vel, pretium tortor. Fusce a nisi convallis, interdum " + "quam condimentum, suscipit dolor. Sed magna diam, efficitur non nunc in, tincidunt varius mi. Aliquam ullamcorper " + "nulla eu fermentum bibendum. Vivamus a felis pretium, hendrerit enim vitae, hendrerit leo. Suspendisse lacinia " + "lectus a diam consectetur suscipit. Aenean hendrerit nisl sed diam venenatis pellentesque. Nullam egestas lectus " + "a consequat pharetra. Vivamus ornare tellus auctor, facilisis lacus id, feugiat dui. Nam id est ut est rhoncus " + "varius.\n" + "\n" + "Aenean vel vehicula erat. Aenean gravida risus vitae purus sodales, quis dictum enim porta. Ut elit elit, " + "fermentum sed posuere non, accumsan eu justo. Integer porta malesuada quam, et elementum massa suscipit nec. " + "Donec in elit diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. " + "Duis suscipit vel ante volutpat vestibulum.\n" + "\n" + "Pellentesque ex arcu, euismod et sapien ut, vulputate suscipit enim. Donec mattis sagittis augue, et mattis " + "lacus. Cras placerat consequat lorem sed luctus. Nam suscipit aliquam sem ac imperdiet. Mauris a semper augue, " + "pulvinar fringilla magna. Integer pretium massa non risus commodo hendrerit. Sed dictum libero id erat sodales " + "mattis. Etiam auctor dolor lectus, ut sagittis enim lobortis vitae. Orci varius natoque penatibus et magnis dis " + "parturient montes, nascetur ridiculus mus. Curabitur nec orci lobortis, cursus risus eget, sollicitudin massa. " + "Integer vel tincidunt mi, id eleifend quam. Nullam facilisis nisl eu mauris congue, vitae euismod nisi malesuada. " + "Vivamus sit amet urna et libero sagittis dictum.\n" + "\n" + "In hac habitasse platea dictumst. Aliquam erat volutpat. Ut dictum, mi a viverra venenatis, mi urna pulvinar " + "nisi, nec gravida lectus diam eget urna. Ut dictum sit amet nisl ut dignissim. Sed sed mauris scelerisque, " + "efficitur augue in, vulputate turpis. Proin dolor justo, bibendum et sollicitudin feugiat, imperdiet sed mi. Sed " + "elementum vitae massa vel lobortis. Cras vitae massa sit amet libero dictum tempus.\n" + "\n" + "Vivamus ut mauris lectus. Curabitur placerat ornare scelerisque. Cras malesuada nunc quis tortor pretium bibendum " + "vel sed dui. Cras lobortis nibh eu erat blandit, sit amet consequat neque fermentum. Phasellus imperdiet molestie " + "tristique. Cras auctor purus erat, id mollis ligula porttitor eget. Mauris porta pharetra odio et finibus. " + "Suspendisse eu est a ligula bibendum cursus. Mauris ac laoreet libero. Nullam volutpat sem quis rhoncus " + "gravida.\n" + "\n" + "Donec malesuada lacus ac iaculis cursus. Sed sem orci, feugiat ac est ut, ultricies posuere nisi. Suspendisse " + "potenti. Phasellus ut ultricies purus. Etiam sem tortor, fermentum quis aliquam eget, consequat ut nulla. Aliquam " + "dictum metus in mi fringilla, vel gravida nulla accumsan. Cras aliquam eget leo vel posuere. Vivamus vitae " + "malesuada nunc. Morbi placerat magna mi, id suscipit lacus auctor quis. Nam at lorem vel odio finibus fringilla " + "ut ac velit. Donec laoreet at nibh quis vehicula.\n" + "\n" + "Fusce ac tristique nisi. Donec leo nisi, consectetur at tellus sit amet, consectetur ultrices dui. Quisque " + "gravida mollis tempor. Maecenas semper, sapien ut dignissim feugiat, massa enim viverra dolor, non varius eros " + "nulla nec felis. Nunc massa lacus, ornare et feugiat id, bibendum quis purus. Praesent viverra elit sit amet " + "purus consectetur venenatis. Maecenas nibh risus, elementum sit amet enim sagittis, ultrices malesuada lectus. " + "Vivamus non felis ante. Ut vulputate ex arcu. Aliquam porta gravida porta. Aliquam eros leo, malesuada quis eros " + "non, maximus tristique neque. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus " + "mus. Etiam ligula orci, mollis vel luctus nec, venenatis vitae est. Fusce rutrum convallis nisi.\n" + "\n" + "Nunc laoreet eget nibh in feugiat. Pellentesque nec arcu cursus, gravida dolor a, pellentesque nisi. Praesent vel " + "justo blandit, placerat risus eget, consectetur orci. Sed maximus metus mi, ut euismod augue ultricies in. Nunc " + "id risus hendrerit, aliquet lorem nec, congue justo. Vestibulum vel nunc ac est euismod mattis ac vitae nulla. " + "Donec blandit luctus mauris, sit amet bibendum dui egestas et. Aenean nec lorem nec elit ornare rutrum nec eget " + "ligula. Fusce a ipsum vitae neque elementum pharetra. Pellentesque ullamcorper ullamcorper libero, vitae porta " + "sem sagittis vel. Interdum et malesuada fames ac ante ipsum primis in faucibus.\n" + "\n" + "Duis at massa sit amet risus pellentesque varius sit amet vitae eros. Cras tempor aliquet sapien, vehicula varius " + "neque volutpat et. Donec purus nibh, pellentesque ut lobortis nec, ultricies ultricies nisl. Sed accumsan ut dui " + "sit amet vulputate. Suspendisse eu facilisis massa, a hendrerit mauris. Nulla elementum molestie tincidunt. Donec " + "mi justo, ornare vel tempor id, gravida et orci. Nam molestie erat nec nisi bibendum accumsan. Duis vitae tempor " + "ante. Morbi congue mauris vel sagittis facilisis. Vivamus vehicula odio orci, a tempor nibh euismod in. Proin " + "mattis, nibh at feugiat porta, purus velit posuere felis, quis volutpat sapien dui vel odio. Nam fermentum sem " + "nec euismod aliquet. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis " + "egestas. Aliquam erat volutpat.\n" + "\n" + "Mauris congue lacus tortor. Pellentesque arcu eros, accumsan imperdiet porttitor vitae, mattis nec justo. Nullam " + "ac aliquam mauris. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. " + "Suspendisse potenti. Fusce accumsan tempus felis a sagittis. Maecenas et velit odio. Vestibulum ante ipsum primis " + "in faucibus orci luctus et ultrices posuere cubilia curae; Aliquam eros lacus, volutpat non urna sed, tincidunt " + "ullamcorper elit. Sed sit amet gravida libero. In varius mi vel diam sollicitudin mollis.\n" + "\n" + "Aenean varius, diam vitae hendrerit feugiat, libero augue ultrices odio, eget consequat sem tellus eu nisi. Nam " + "dapibus enim et auctor sollicitudin. Nunc iaculis eros orci, ac accumsan eros malesuada ut. Ut semper augue " + "felis, nec sodales lorem consectetur non. Cras gravida eleifend est, et sagittis eros imperdiet congue. Fusce id " + "tellus dapibus nunc scelerisque tempus. Donec tempor placerat libero, in commodo nisi bibendum eu. Donec id eros " + "non est sollicitudin luctus. Duis bibendum bibendum tellus nec viverra. Aliquam non faucibus ex, nec luctus dui. " + "Curabitur efficitur varius urna non dignissim. Suspendisse elit elit, ultrices in elementum eu, tempor at " + "magna.\n" + "\n" + "Nunc in purus sit amet mi laoreet pulvinar placerat eget sapien. Donec vel felis at dui ultricies euismod quis " + "vel neque. Donec tincidunt urna non eros pretium blandit. Nullam congue tincidunt condimentum. Curabitur et " + "libero nibh. Proin ultricies risus id imperdiet scelerisque. Suspendisse purus mi, viverra vitae risus ut, tempus " + "tincidunt enim. Ut luctus lobortis nisl, eget venenatis tortor cursus non. Mauris finibus nisl quis gravida " + "ultricies. Fusce elementum lacus sit amet nunc congue, in porta nulla tincidunt.\n" + "\n" + "Mauris ante risus, imperdiet blandit posuere in, blandit eu ipsum. Integer et auctor arcu. Integer quis elementum " + "purus. Nunc in ultricies nisl, sed rutrum risus. Suspendisse venenatis eros nec lorem rhoncus, in scelerisque " + "velit condimentum. Etiam condimentum quam felis, in elementum odio mattis et. In ut nibh porttitor, hendrerit " + "tellus vel, luctus magna. Vestibulum et ligula et dolor pellentesque porta. Aenean efficitur porta massa et " + "bibendum. Nulla vehicula sem in risus volutpat, a eleifend elit maximus.\n" + "\n" + "Proin orci lorem, auctor a felis eu, pretium lobortis nulla. Phasellus aliquam efficitur interdum. Sed sit amet " + "velit rutrum est dictum facilisis. Duis cursus enim at nisl tincidunt, eu molestie elit vehicula. Cras " + "pellentesque nisl id enim feugiat fringilla. In quis tincidunt neque. Nam eu consectetur dolor. Ut id interdum " + "mauris. Mauris nunc tortor, placerat in tempor ut, vestibulum eu nisl. Integer vel dapibus ipsum. Nunc id erat " + "pulvinar, tincidunt magna id, condimentum massa. Pellentesque consequat est eget odio placerat vehicula. Etiam " + "augue neque, sagittis non leo eu, tristique scelerisque dui. Ut dui urna, blandit quis urna ac, tincidunt " + "tristique turpis.\n" + "\n" + "Suspendisse venenatis rhoncus ligula ultrices condimentum. In id laoreet eros. Suspendisse suscipit fringilla leo " + "id euismod. Sed in quam libero. Ut at ligula tellus. Sed tristique gravida dui, at egestas odio aliquam iaculis. " + "Praesent imperdiet velit quis nibh consequat, quis pretium sem sagittis. Donec tortor ex, congue sit amet " + "pulvinar ac, rutrum non est. Praesent ipsum magna, venenatis sit amet vulputate id, eleifend ac ipsum.\n" + "\n" + "In consequat, nisi iaculis laoreet elementum, massa mauris varius nisi, et porta nisi velit at urna. Maecenas sit " + "amet aliquet eros, a rhoncus nisl. Maecenas convallis enim nunc. Morbi purus nisl, aliquam ac tincidunt sed, " + "mattis in augue. Quisque et elementum quam, vitae maximus orci. Suspendisse hendrerit risus nec vehicula " + "placerat. Nulla et lectus nunc. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac " + "turpis egestas.\n" + "\n" + "Etiam ut sodales ex. Nulla luctus, magna eu scelerisque sagittis, nibh quam consectetur neque, non rutrum dolor " + "metus nec ex. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed " + "egestas augue elit, sollicitudin accumsan massa lobortis ac. Curabitur placerat, dolor a aliquam maximus, velit " + "ipsum laoreet ligula, id ullamcorper lacus nibh eget nisl. Donec eget lacus venenatis enim consequat auctor vel " + "in.\n"; + + // Prepare to send a large message to the topic. + TopicMessageSubmitTransaction topicMessageSubmitTransaction = TopicMessageSubmitTransaction() + .setTopicId(topicId) + .setMaxChunks(15U) + .setMessage(bigContents) + .freezeWith(&client) + .sign(operatorPrivateKey.get()); + + // "Send" the message to be signed again "elsewhere" by the submit key. + std::vector txBytes = topicMessageSubmitTransaction.toBytes(); + + // "Receive" the "sent" bytes. + const WrappedTransaction deserializedTx = Transaction::fromBytes(txBytes); + topicMessageSubmitTransaction = *deserializedTx.getTransaction(); + + // Sign the message with the submit key. + topicMessageSubmitTransaction.sign(submitKey.get()); + + // Submit the transaction + const std::vector txResponses = topicMessageSubmitTransaction.executeAll(client); + for (const auto& txResp : txResponses) + { + txResp.getReceipt(client); + } + + // Get the messages from the subscription. + while (true) + { + std::cout << "Receiving..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + + return 0; +} diff --git a/sdk/main/CMakeLists.txt b/sdk/main/CMakeLists.txt index 1c2ca6763..d208906d6 100644 --- a/sdk/main/CMakeLists.txt +++ b/sdk/main/CMakeLists.txt @@ -132,6 +132,9 @@ add_library(${PROJECT_NAME} STATIC src/TransferTransaction.cc src/WrappedTransaction.cc + src/impl/BaseNetwork.cc + src/impl/BaseNode.cc + src/impl/BaseNodeAddress.cc src/impl/DerivationPathUtils.cc src/impl/Endpoint.cc src/impl/DurationConverter.cc diff --git a/sdk/main/include/AccountAllowanceApproveTransaction.h b/sdk/main/include/AccountAllowanceApproveTransaction.h index 0bd758da5..430547473 100644 --- a/sdk/main/include/AccountAllowanceApproveTransaction.h +++ b/sdk/main/include/AccountAllowanceApproveTransaction.h @@ -84,6 +84,15 @@ class AccountAllowanceApproveTransaction : public Transaction>& transactions); + /** * Add an Hbar allowance to this AccountAllowanceApproveTransaction. * @@ -179,33 +188,21 @@ class AccountAllowanceApproveTransaction : public Transaction& /*node*/) const override; /** - * Derived from Executable. Submit this AccountAllowanceApproveTransaction to a Node. + * Derived from Executable. Submit a Transaction protobuf object which contains this + * AccountAllowanceApproveTransaction's data to a Node. * - * @param client The Client submitting this AccountAllowanceApproveTransaction. - * @param deadline The deadline for submitting this AccountAllowanceApproveTransaction. - * @param node Pointer to the Node to which this AccountAllowanceApproveTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the AccountAllowanceApproveTransaction protobuf representation to the @@ -215,6 +212,11 @@ class AccountAllowanceApproveTransaction : public Transaction + namespace proto { class CryptoDeleteAllowanceTransactionBody; @@ -31,6 +33,7 @@ class TransactionBody; namespace Hedera { +class AccountId; class NftId; } @@ -55,6 +58,15 @@ class AccountAllowanceDeleteTransaction : public Transaction>& transactions); + /** * Remove all NFT allowances from an account. * @@ -77,33 +89,21 @@ class AccountAllowanceDeleteTransaction : public Transaction& /*node*/) const override; /** - * Derived from Executable. Submit this AccountAllowanceDeleteTransaction to a Node. + * Derived from Executable. Submit a Transaction protobuf object which contains this + * AccountAllowanceDeleteTransaction's data to a Node. * - * @param client The Client submitting this AccountAllowanceDeleteTransaction. - * @param deadline The deadline for submitting this AccountAllowanceDeleteTransaction. - * @param node Pointer to the Node to which this AccountAllowanceDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the AccountAllowanceDeleteTransaction protobuf representation to the @@ -113,6 +113,11 @@ class AccountAllowanceDeleteTransaction : public Transaction [[nodiscard]] inline std::optional getContractId() { return mContractId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this AccountBalanceQuery object. - * - * @param client The Client trying to construct this AccountBalanceQuery. This is unused. - * @param node The Node to which this AccountBalanceQuery will be sent. This is unused. - * @return A Query protobuf object filled with this AccountBalanceQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& /*client*/, - const std::shared_ptr& /*node*/) const override; - /** * Derived from Executable. Construct an AccountBalance object from a Response protobuf object. * @@ -96,28 +86,42 @@ class AccountBalanceQuery : public Query [[nodiscard]] AccountBalance mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted AccountBalanceQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this AccountBalanceQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the AccountBalanceQuery status response code. - * @return The AccountBalanceQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this AccountBalanceQuery to a Node. - * - * @param client The Client submitting this AccountBalanceQuery. - * @param deadline The deadline for submitting this AccountBalanceQuery. - * @param node Pointer to the Node to which this AccountBalanceQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this AccountBalanceQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; + + /** + * Derived from Query. Does this AccountBalanceQuery require payment? + * + * @return \c FALSE, AccountBalanceQuery is free. + */ + [[nodiscard]] inline bool isPaymentRequired() const override { return false; } /** * The ID of the account of which this query should get the balance. diff --git a/sdk/main/include/AccountCreateTransaction.h b/sdk/main/include/AccountCreateTransaction.h index 7f0f09dcf..0bdcd61f0 100644 --- a/sdk/main/include/AccountCreateTransaction.h +++ b/sdk/main/include/AccountCreateTransaction.h @@ -83,6 +83,15 @@ class AccountCreateTransaction : public Transaction */ explicit AccountCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit AccountCreateTransaction( + const std::map>& transactions); + /** * Set the key for the new account. The key that must sign each transfer out of the account. If * mReceiverSignatureRequired is true, then it must also sign any transfer into the account. @@ -259,30 +268,19 @@ class AccountCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this AccountCreateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this AccountCreateTransaction's data + * to a Node. * - * @param client The Client trying to construct this AccountCreateTransaction. - * @param node The Node to which this AccountCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this AccountCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * AccountAllowanceApproveTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this AccountCreateTransaction to a Node. - * - * @param client The Client submitting this AccountCreateTransaction. - * @param deadline The deadline for submitting this AccountCreateTransaction. - * @param node Pointer to the Node to which this AccountCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the AccountCreateTransaction protobuf representation to the Transaction @@ -292,6 +290,11 @@ class AccountCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this AccountCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a CryptoCreateTransactionBody protobuf object from this AccountCreateTransaction object. * diff --git a/sdk/main/include/AccountDeleteTransaction.h b/sdk/main/include/AccountDeleteTransaction.h index 2a1cd3287..60be33f70 100644 --- a/sdk/main/include/AccountDeleteTransaction.h +++ b/sdk/main/include/AccountDeleteTransaction.h @@ -51,6 +51,15 @@ class AccountDeleteTransaction : public Transaction */ explicit AccountDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit AccountDeleteTransaction( + const std::map>& transactions); + /** * Sets the ID of the account to delete. * @@ -90,39 +99,33 @@ class AccountDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this AccountDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this AccountDeleteTransaction's data + * to a Node. * - * @param client The Client trying to construct this AccountDeleteTransaction. - * @param node The Node to which this AccountDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this AccountDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * AccountDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this AccountDeleteTransaction to a Node. - * - * @param client The Client submitting this AccountDeleteTransaction. - * @param deadline The deadline for submitting this AccountDeleteTransaction. - * @param node Pointer to the Node to which this AccountDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** - * Derived from Transaction. Build and add the AccountCreateTransaction protobuf representation to the Transaction + * Derived from Transaction. Build and add the AccountDeleteTransaction protobuf representation to the Transaction * protobuf object. * * @param body The TransactionBody protobuf object being built. */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this AccountDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a CryptoDeleteTransactionBody protobuf object from this AccountDeleteTransaction object. * diff --git a/sdk/main/include/AccountId.h b/sdk/main/include/AccountId.h index 7ff8115be..d3c6a0b2b 100644 --- a/sdk/main/include/AccountId.h +++ b/sdk/main/include/AccountId.h @@ -227,11 +227,23 @@ template<> struct hash { /** - * Operator override to enable use of AccountId as map key + * Operator override to enable use of AccountId as map key. */ size_t operator()(const Hedera::AccountId& id) const { return hash()(id.toString()); } }; +template<> +struct less +{ + /** + * Operator override to enable use of AccountId in a std::map, which requires fair ordering. + */ + bool operator()(const Hedera::AccountId& lhs, const Hedera::AccountId& rhs) const + { + return lhs.toString() < rhs.toString(); + } +}; + } // namespace std #endif // HEDERA_SDK_CPP_ACCOUNT_ID_H_ diff --git a/sdk/main/include/AccountInfoQuery.h b/sdk/main/include/AccountInfoQuery.h index f0d019178..d78ca069a 100644 --- a/sdk/main/include/AccountInfoQuery.h +++ b/sdk/main/include/AccountInfoQuery.h @@ -55,47 +55,44 @@ class AccountInfoQuery : public Query [[nodiscard]] inline AccountId getAccountId() const { return mAccountId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this AccountInfoQuery object. - * - * @param client The Client trying to construct this AccountInfoQuery. - * @param node The Node to which this AccountInfoQuery will be sent. - * @return A Query protobuf object filled with this AccountInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct an AccountInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct an AccountInfo object. - * @return An AccountInfo object filled with the Response protobuf object's data. + * @return An AccountInfo object filled with the Response protobuf object's data */ [[nodiscard]] AccountInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted AccountInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this AccountInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the AccountInfoQuery status response code. - * @return The AccountInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this AccountInfoQuery to a Node. - * - * @param client The Client submitting this AccountInfoQuery. - * @param deadline The deadline for submitting this AccountInfoQuery. - * @param node Pointer to the Node to which this AccountInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this AccountInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the account of which this query should get the info. diff --git a/sdk/main/include/AccountRecordsQuery.h b/sdk/main/include/AccountRecordsQuery.h index af77a7706..42242ab79 100644 --- a/sdk/main/include/AccountRecordsQuery.h +++ b/sdk/main/include/AccountRecordsQuery.h @@ -56,47 +56,44 @@ class AccountRecordsQuery : public Query [[nodiscard]] inline AccountId getAccountId() const { return mAccountId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this AccountRecordsQuery object. - * - * @param client The Client trying to construct this AccountRecordsQuery. - * @param node The Node to which this AccountRecordsQuery will be sent. - * @return A Query protobuf object filled with this AccountRecordsQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct an AccountRecords object from a Response protobuf object. * * @param response The Response protobuf object from which to construct an AccountRecords object. - * @return An AccountRecords object filled with the Response protobuf object's data. + * @return An AccountRecords object filled with the Response protobuf object's data */ [[nodiscard]] AccountRecords mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted AccountRecordsQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this AccountRecordsQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the AccountRecordsQuery status response code. - * @return The AccountRecordsQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this AccountRecordsQuery to a Node. - * - * @param client The Client submitting this AccountRecordsQuery. - * @param deadline The deadline for submitting this AccountRecordsQuery. - * @param node Pointer to the Node to which this AccountRecordsQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this AccountRecordsQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the account of which this query should get the records. diff --git a/sdk/main/include/AccountStakersQuery.h b/sdk/main/include/AccountStakersQuery.h index a2511a657..84574e7e8 100644 --- a/sdk/main/include/AccountStakersQuery.h +++ b/sdk/main/include/AccountStakersQuery.h @@ -52,47 +52,44 @@ class AccountStakersQuery : public Query [[nodiscard]] inline AccountId getAccountId() const { return mAccountId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this AccountStakersQuery object. - * - * @param client The Client trying to construct this AccountStakersQuery. - * @param node The Node to which this AccountStakersQuery will be sent. - * @return A Query protobuf object filled with this AccountStakersQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct an AccountStakers object from a Response protobuf object. * * @param response The Response protobuf object from which to construct an AccountStakers object. - * @return An AccountStakers object filled with the Response protobuf object's data. + * @return An AccountStakers object filled with the Response protobuf object's data */ [[nodiscard]] AccountStakers mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted AccountStakersQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this AccountStakersQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the AccountStakersQuery status response code. - * @return The AccountStakersQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this AccountStakersQuery to a Node. - * - * @param client The Client submitting this AccountStakersQuery. - * @param deadline The deadline for submitting this AccountStakersQuery. - * @param node Pointer to the Node to which this AccountStakersQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this AccountStakersQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the account of which this query should get the stakers. diff --git a/sdk/main/include/AccountUpdateTransaction.h b/sdk/main/include/AccountUpdateTransaction.h index 1c6ec920a..db777b51e 100644 --- a/sdk/main/include/AccountUpdateTransaction.h +++ b/sdk/main/include/AccountUpdateTransaction.h @@ -58,6 +58,15 @@ class AccountUpdateTransaction : public Transaction */ explicit AccountUpdateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit AccountUpdateTransaction( + const std::map>& transactions); + /** * Set the ID of the account to update. * @@ -242,30 +251,19 @@ class AccountUpdateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this AccountUpdateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this AccountUpdateTransaction's data + * to a Node. * - * @param client The Client trying to construct this AccountUpdateTransaction. - * @param node The Node to which this AccountUpdateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this AccountUpdateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * AccountUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this AccountUpdateTransaction to a Node. - * - * @param client The Client submitting this AccountUpdateTransaction. - * @param deadline The deadline for submitting this AccountUpdateTransaction. - * @param node Pointer to the Node to which this AccountUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the AccountUpdateTransaction protobuf representation to the Transaction @@ -275,6 +273,11 @@ class AccountUpdateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this AccountUpdateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a CryptoUpdateTransactionBody protobuf object from this AccountUpdateTransaction object. * diff --git a/sdk/main/include/ChunkedTransaction.h b/sdk/main/include/ChunkedTransaction.h index 9303bf54a..dd3401f93 100644 --- a/sdk/main/include/ChunkedTransaction.h +++ b/sdk/main/include/ChunkedTransaction.h @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace Hedera @@ -99,6 +100,63 @@ class ChunkedTransaction : public Transaction */ std::vector executeAll(const Client& client, const std::chrono::duration& timeout); + /** + * Derived from Transaction. Add a signature to this ChunkedTransaction. + * + * @param publicKey The associated PublicKey of the PrivateKey that generated the signature. + * @param signature The signature to add. + * @return A reference to this derived ChunkedTransaction object with the newly-added signature. + * @throws IllegalStateException If there are multiple chunks in this ChunkedTransaction,there is not exactly one node + * account ID set, or if this ChunkedTransaction is not frozen. + */ + SdkRequestType& addSignature(const std::shared_ptr& publicKey, + const std::vector& signature) override; + + /** + * Derived from Transaction. Get the signatures of each potential Transaction protobuf object this ChunkedTransaction + * may send. + * + * @return The map of node account IDs to their PublicKeys and signatures. + */ + [[nodiscard]] std::map, std::vector>> getSignatures() + const override; + + /** + * Get the signatures of all chunks of this ChunkedTransaction, for each potential node to which it may be sent. + * + * @return The list of signatures for each node account ID for each chunk. + */ + [[nodiscard]] std::vector, std::vector>>> + getAllSignatures() const; + + /** + * Derived from Transaction. Get the SHA384 hash of this ChunkedTransaction. + * + * @return The SHA384 hash of this Transaction. + * @throws IllegalStateException If this ChunkedTransaction contains multiple chunks or this ChunkedTransaction is + * not frozen. + */ + [[nodiscard]] std::vector getTransactionHash() const override; + + /** + * Derived from Transaction. Get the SHA384 hash of each potential Transaction protobuf object this ChunkedTransaction + * may send. + * + * @return The map of node account IDs to the SHA384 hash of their Transaction. + * @throws IllegalStateException If this ChunkedTransaction contains multiple chunks or this ChunkedTransaction is not + * frozen. + */ + [[nodiscard]] std::map> getTransactionHashPerNode() const override; + + /** + * Get the SHA384 hashes of all Transaction protobuf objects for each chunk of this ChunkedTransaction, for each node + * account ID. + * + * @return The list of Transaction protobuf object hashes for each node account ID for each chunk. + * @throws IllegalStateException If this ChunkedTransaction isn't frozen. + */ + [[nodiscard]] std::vector>> getAllTransactionHashesPerNode() const; + /** * Set the maximum number of chunks for this ChunkedTransaction. * @@ -120,16 +178,41 @@ class ChunkedTransaction : public Transaction * * @return The maximum number of chunks for this ChunkedTransaction. */ - [[nodiscard]] inline unsigned int getMaxChunks() const { return mMaxChunks; } + [[nodiscard]] unsigned int getMaxChunks() const; /** * Get the size of each chunk, in bytes, for this ChunkedTransaction. * * @return The size of each chunk, in bytes, for this ChunkedTransaction. */ - [[nodiscard]] inline unsigned int getChunkSize() const { return mChunkSize; } + [[nodiscard]] unsigned int getChunkSize() const; protected: + ChunkedTransaction(); + ~ChunkedTransaction(); + ChunkedTransaction(const ChunkedTransaction&); + ChunkedTransaction& operator=(const ChunkedTransaction&); + ChunkedTransaction(ChunkedTransaction&&) noexcept; + ChunkedTransaction& operator=(ChunkedTransaction&&) noexcept; + + /** + * Construct from a TransactionBody protobuf object. + * + * @param txBody The TransactionBody protobuf object from which to construct. + */ + explicit ChunkedTransaction(const proto::TransactionBody& txBody); + + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. This + * will ignore the first TransactionId entry (as its information will be stored in the base Transaction + * implementation) and construct additional Transaction protobuf objects for each additional chunk of the Transaction + * that must be sent. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ChunkedTransaction(const std::map>& transactions); + /** * Set the data for this ChunkedTransaction. * @@ -144,7 +227,15 @@ class ChunkedTransaction : public Transaction * * @return The data for this ChunkedTransaction. */ - [[nodiscard]] inline std::vector getData() const { return mData; } + [[nodiscard]] std::vector getData() const; + + /** + * Get the data contained in the input chunk of this ChunkedTransaction. + * + * @param chunk The chunk number of which to get the data. + * @return The data contained in the input chunk number. + */ + [[nodiscard]] std::vector getDataForChunk(unsigned int chunk) const; /** * Set the receipt retrieval policy for this ChunkedTransaction. @@ -160,53 +251,60 @@ class ChunkedTransaction : public Transaction * @retrun retrieveReceipt \c TRUE if this ChunkedTransaction should retrieve a receipt after each submitted chunk, * otherwise \c FALSE. */ - [[nodiscard]] inline bool getShouldGetReceipt() const { return mShouldGetReceipt; } + [[nodiscard]] bool getShouldGetReceipt() const; private: /** - * Perform any needed actions for this ChunkedTransaction after it has been chunked. + * Build and add the derived ChunkedTransaction's chunked protobuf representation to the TransactionBody protobuf + * object. + * + * @param chunk The chunk number. + * @param total The total number of chunks being created. + * @param body The TransactionBody protobuf object to which to add the chunked data. + */ + virtual void addToChunk(uint32_t chunk, [[maybe_unused]] uint32_t total, proto::TransactionBody& body) const = 0; + + /** + * Derived from Executable. Construct a Transaction protobuf object from this ChunkedTransaction, based on the attempt + * number. This will take into account the current chunk of this ChunkedTransaction trying to be sent. * - * @param firstTransactionId The transaction ID of the first chunk. - * @param chunk The chunk number of this chunk. - * @param total The total number of chunks being created. - * @throws UninitializedException If the client doesn't have an AccountId from which to generate a TransactionId. + * @param attempt The attempt number of trying to execute this ChunkedTransaction. + * @return A Transaction protobuf object filled with this ChunkedTransaction's data, based on the attempt number. */ - virtual void onChunk([[maybe_unused]] const TransactionId& firstTransactionId, - [[maybe_unused]] int32_t chunk, - [[maybe_unused]] int32_t total) - { // Intentionally unimplemented, no processing needs to occur by default. - } + [[nodiscard]] proto::Transaction makeRequest(unsigned int attempt) const override; /** - * Wrapper function needed to execute the Executable version of execute(). + * Derived from Transaction. Generate the SignedTransaction protobuf objects for this ChunkedTransaction. * - * @param client The Client to use to submit the ChunkedTransaction. - * @param timeout The desired timeout for the execution of the ChunkedTransaction. - * @param tx The ChunkedTransaction to execute. - * @return The TransactionResponse object sent from the Hedera network that contains the result of the request. + * @param client A pointer to the Client to use to generate the SignedTransaction protobuf objects. */ - TransactionResponse wrappedExecute(const Client& client, const std::chrono::duration& timeout); + void generateSignedTransactions(const Client* client) override; /** - * This ChunkedTransaction's data. + * Derived from Transaction. Clear the SignedTransaction and Transaction protobuf objects held by this + * ChunkedTransaction. */ - std::vector mData; + void clearTransactions() override; /** - * The size of this ChunkedTransaction's chunks, in bytes. + * Derived from Transaction. Get the ID of the previously-executed ChunkedTransaction. + * + * @return The ID of the previously-executed ChunkedTransaction. */ - unsigned int mChunkSize = 1024U; + [[nodiscard]] TransactionId getCurrentTransactionId() const override; /** - * The maximum number of chunks into which this ChunkedTransaction will get broken up. + * Get the number of chunks that will be required to send this full ChunkedTransaction. + * + * @return The number of chunks that will be required to send this full ChunkedTransaction. */ - unsigned int mMaxChunks = DEFAULT_MAX_CHUNKS; + [[nodiscard]] unsigned int getNumberOfChunksRequired() const; /** - * Should this ChunkedTransaction get a receipt for each submitted chunk? + * Implementation object used to hide implementation details and internal headers. */ - bool mShouldGetReceipt = false; + struct ChunkedTransactionImpl; + std::unique_ptr mImpl; }; } // namespace Hedera diff --git a/sdk/main/include/Client.h b/sdk/main/include/Client.h index 546924dfb..e8e7dd673 100644 --- a/sdk/main/include/Client.h +++ b/sdk/main/include/Client.h @@ -32,7 +32,7 @@ namespace Hedera namespace internal { class MirrorNetwork; -class Node; +class Network; } class AccountId; class Hbar; @@ -114,27 +114,7 @@ class Client Client& setOperator(const AccountId& accountId, const PrivateKey* privateKey); /** - * Sign an arbitrary array of bytes with this Client's operator. - * - * @param bytes The bytes for this Client's operator to sign. - * @return The generated signature of this Client's operator. - * @throws UninitializedException If this Client's operator has not yet been set. - */ - [[nodiscard]] std::vector sign(const std::vector& bytes) const; - - /** - * Get a list of pointers to Nodes on this Client's network that are associated with the input account IDs. If no - * account IDs are specified, this returns the list a list of pointers to all nodes in this Client's network. - * - * @param accountIds The account IDs of the requested nodes. This can be empty to get all Nodes. - * @return A list of pointers to Nodes that are associated with the requested account IDs. - * @throws UninitializedException If this Client's network has not yet been initialized. - */ - [[nodiscard]] std::vector> getNodesWithAccountIds( - const std::vector& accountIds) const; - - /** - * Initiate an orderly shutdown of communications with the network with which this Client was configured to + * Initiate an orderly close of communications with the network with which this Client was configured to * communicate. Preexisting transactions or queries continue but subsequent calls would be immediately cancelled. * * After this method returns, this Client can be re-used. All network communication can be re-established as needed. @@ -160,6 +140,17 @@ class Client */ Client& setMaxTransactionFee(const Hbar& fee); + /** + * Set the maximum query payment willing to be paid for transactions executed by this Client. Every request submitted + * with this Client will have its maximum query payment overwritten by this Client's maximum query payment if and only + * if it has not been set manually in the request itself. + * + * @param payment The desired maximum query payment willing to be paid for queries submitted by this Client. + * @return A reference to this Client object with the newly-set maximum query payment. + * @throws std::invalid_argument If the query payment is negative. + */ + Client& setMaxQueryPayment(const Hbar& payment); + /** * Set the transaction ID regeneration policy for transactions executed by this Client. Every transaction submitted * with this Client will have its transaction ID regeneration policy overwritten by this Client's transaction ID @@ -207,6 +198,13 @@ class Client */ Client& setMaxBackoff(const std::chrono::duration& backoff); + /** + * Get a pointer to the Network this Client is using to communicate with consensus nodes. + * + * @return A pointer to the Network this Client is using to communicate with consensus nodes. + */ + [[nodiscard]] std::shared_ptr getNetwork() const; + /** * Get the account ID of this Client's operator. * @@ -244,6 +242,13 @@ class Client */ [[nodiscard]] std::optional getMaxTransactionFee() const; + /** + * Get the maximum payment willing to be paid for queries submitted by this Client. + * + * @return The maximum query payment willing to be paid by this Client. Uninitialized if the fee has not yet been set. + */ + [[nodiscard]] std::optional getMaxQueryPayment() const; + /** * Get the transaction ID regeneration policy for transactions submitted by this Client. * diff --git a/sdk/main/include/ContractByteCodeQuery.h b/sdk/main/include/ContractByteCodeQuery.h index 4cd2e0a6d..f52fdc4f9 100644 --- a/sdk/main/include/ContractByteCodeQuery.h +++ b/sdk/main/include/ContractByteCodeQuery.h @@ -54,46 +54,43 @@ class ContractByteCodeQuery : public Query& node) const override; + [[nodiscard]] ContractByteCode mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Construct an ContractByteCode object from a Response protobuf object. + * Derived from Executable. Submit a Query protobuf object which contains this ContractByteCodeQuery's data to a Node. * - * @param response The Response protobuf object from which to construct an ContractByteCode object. - * @return An ContractByteCode object filled with the Response protobuf object's data + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. + * @return The gRPC status of the submission. */ - [[nodiscard]] ContractByteCode mapResponse(const proto::Response& response) const override; - + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const override; /** - * Derived from Executable. Get the status response code for a submitted ContractByteCodeQuery from a Response - * protobuf object. + * Derived from Query. Build a Query protobuf object with this ContractByteCodeQuery's data, with the input + * QueryHeader protobuf object. * - * @param response The Response protobuf object from which to grab the ContractByteCodeQuery status response code. - * @return The ContractByteCodeQuery status response code of the input Response protobuf object. + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; /** - * Derived from Executable. Submit this ContractByteCodeQuery to a Node. + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. * - * @param client The Client submitting this ContractByteCodeQuery. - * @param deadline The deadline for submitting this ContractByteCodeQuery. - * @param node Pointer to the Node to which this ContractByteCodeQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information - * from the gRPC server. - * @return The gRPC status of the submission. + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const override; + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the contract of which this query should get the byte code. diff --git a/sdk/main/include/ContractCallQuery.h b/sdk/main/include/ContractCallQuery.h index a2de54510..e10bd6948 100644 --- a/sdk/main/include/ContractCallQuery.h +++ b/sdk/main/include/ContractCallQuery.h @@ -125,46 +125,43 @@ class ContractCallQuery : public Query& node) const override; + [[nodiscard]] ContractFunctionResult mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Construct an ContractCallQuery object from a Response protobuf object. + * Derived from Executable. Submit a Query protobuf object which contains this ContractCallQuery's data to a Node. * - * @param response The Response protobuf object from which to construct an ContractCallQuery object. - * @return An ContractCallQuery object filled with the Response protobuf object's data + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. + * @return The gRPC status of the submission. */ - [[nodiscard]] ContractFunctionResult mapResponse(const proto::Response& response) const override; - + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const override; /** - * Derived from Executable. Get the status response code for a submitted ContractCallQuery from a Response + * Derived from Query. Build a Query protobuf object with this ContractCallQuery's data, with the input QueryHeader * protobuf object. * - * @param response The Response protobuf object from which to grab the ContractCallQuery status response code. - * @return The ContractCallQuery status response code of the input Response protobuf object. + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; /** - * Derived from Executable. Submit this ContractCallQuery to a Node. + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. * - * @param client The Client submitting this ContractCallQuery. - * @param deadline The deadline for submitting this ContractCallQuery. - * @param node Pointer to the Node to which this ContractCallQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information - * from the gRPC server. - * @return The gRPC status of the submission. + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const override; + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the contract from which this query should call a function. diff --git a/sdk/main/include/ContractCreateTransaction.h b/sdk/main/include/ContractCreateTransaction.h index 1f7d41c19..bd66c7759 100644 --- a/sdk/main/include/ContractCreateTransaction.h +++ b/sdk/main/include/ContractCreateTransaction.h @@ -106,6 +106,15 @@ class ContractCreateTransaction : public Transaction */ explicit ContractCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ContractCreateTransaction( + const std::map>& transactions); + /** * Set the ID of the file that contains the smart contract bytecode. A copy will be made and held by the contract * instance, and have the same expiration time as the instance. If the bytecode is large (>5K), then it must be stored @@ -343,30 +352,19 @@ class ContractCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ContractCreateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this ContractCreateTransaction's data + * to a Node. * - * @param client The Client trying to construct this ContractCreateTransaction. - * @param node The Node to which this ContractCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ContractCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ContractCreateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ContractCreateTransaction to a Node. - * - * @param client The Client submitting this ContractCreateTransaction. - * @param deadline The deadline for submitting this ContractCreateTransaction. - * @param node Pointer to the Node to which this ContractCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ContractCreateTransaction protobuf representation to the Transaction @@ -376,6 +374,11 @@ class ContractCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ContractCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ContractCreateTransactionBody protobuf object from this ContractCreateTransaction object. * diff --git a/sdk/main/include/ContractDeleteTransaction.h b/sdk/main/include/ContractDeleteTransaction.h index d5c5dc3df..edb451435 100644 --- a/sdk/main/include/ContractDeleteTransaction.h +++ b/sdk/main/include/ContractDeleteTransaction.h @@ -59,6 +59,15 @@ class ContractDeleteTransaction : public Transaction */ explicit ContractDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ContractDeleteTransaction( + const std::map>& transactions); + /** * Set the ID of the contract to delete. * @@ -115,30 +124,19 @@ class ContractDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ContractDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this ContractDeleteTransaction's data + * to a Node. * - * @param client The Client trying to construct this ContractDeleteTransaction. - * @param node The Node to which this ContractDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ContractDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ContractDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ContractDeleteTransaction to a Node. - * - * @param client The Client submitting this ContractDeleteTransaction. - * @param deadline The deadline for submitting this ContractDeleteTransaction. - * @param node Pointer to the Node to which this ContractDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ContractDeleteTransaction protobuf representation to the Transaction @@ -148,6 +146,11 @@ class ContractDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ContractDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ContractDeleteTransactionBody protobuf object from this ContractDeleteTransaction object. * diff --git a/sdk/main/include/ContractExecuteTransaction.h b/sdk/main/include/ContractExecuteTransaction.h index 03556089b..8f47ba236 100644 --- a/sdk/main/include/ContractExecuteTransaction.h +++ b/sdk/main/include/ContractExecuteTransaction.h @@ -60,6 +60,15 @@ class ContractExecuteTransaction : public Transaction>& transactions); + /** * Set the ID of the contract to call. * @@ -139,30 +148,19 @@ class ContractExecuteTransaction : public Transaction& /*node*/) const override; - - /** - * Derived from Executable. Submit this ContractExecuteTransaction to a Node. - * - * @param client The Client submitting this ContractExecuteTransaction. - * @param deadline The deadline for submitting this ContractExecuteTransaction. - * @param node Pointer to the Node to which this ContractExecuteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ContractExecuteTransaction protobuf representation to the Transaction @@ -172,6 +170,11 @@ class ContractExecuteTransaction : public Transaction [[nodiscard]] inline ContractId getContractId() { return mContractId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this ContractInfoQuery object. - * - * @param client The Client trying to construct this ContractInfoQuery. - * @param node The Node to which this ContractInfoQuery will be sent. - * @return A Query protobuf object filled with this ContractInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a ContractInfo object from a Response protobuf object. * @@ -76,28 +66,35 @@ class ContractInfoQuery : public Query [[nodiscard]] ContractInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted ContractInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this ContractInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the ContractInfoQuery status response code. - * @return The ContractInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this ContractInfoQuery to a Node. - * - * @param client The Client submitting this ContractInfoQuery. - * @param deadline The deadline for submitting this ContractInfoQuery. - * @param node Pointer to the Node to which this ContractInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this ContractInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the contract of which this query should get the info. diff --git a/sdk/main/include/ContractUpdateTransaction.h b/sdk/main/include/ContractUpdateTransaction.h index 8541ddeaa..0f57fe9e8 100644 --- a/sdk/main/include/ContractUpdateTransaction.h +++ b/sdk/main/include/ContractUpdateTransaction.h @@ -67,6 +67,15 @@ class ContractUpdateTransaction : public Transaction */ explicit ContractUpdateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ContractUpdateTransaction( + const std::map>& transactions); + /** * Set the ID of the contract to update. * @@ -253,30 +262,19 @@ class ContractUpdateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ContractUpdateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this ContractUpdateTransaction's data + * to a Node. * - * @param client The Client trying to construct this ContractUpdateTransaction. - * @param node The Node to which this ContractUpdateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ContractUpdateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ContractUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ContractUpdateTransaction to a Node. - * - * @param client The Client submitting this ContractUpdateTransaction. - * @param deadline The deadline for submitting this ContractUpdateTransaction. - * @param node Pointer to the Node to which this ContractUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ContractUpdateTransaction protobuf representation to the Transaction @@ -286,6 +284,11 @@ class ContractUpdateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ContractUpdateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ContractUpdateTransactionBody protobuf object from this ContractUpdateTransaction object. * diff --git a/sdk/main/include/Defaults.h b/sdk/main/include/Defaults.h index 50cf95f69..a5dfcc6d0 100644 --- a/sdk/main/include/Defaults.h +++ b/sdk/main/include/Defaults.h @@ -31,21 +31,54 @@ namespace Hedera */ constexpr auto DEFAULT_MAX_ATTEMPTS = 10U; /** - * The default minimum duration of time to wait before retrying to submit a previously-failed request to the same node. + * The default minimum duration of time to wait before retrying to submit a previously-failed request. */ constexpr auto DEFAULT_MIN_BACKOFF = std::chrono::milliseconds(250); /** - * The default maximum duration of time to wait before retrying to submit a previously-failed request to the same node. + * The default maximum duration of time to wait before retrying to submit a previously-failed request. */ constexpr auto DEFAULT_MAX_BACKOFF = std::chrono::seconds(8); +/** + * The default maximum number of times a node is allowed to return a bad gRPC status before it is permanently removed + * from a network. 0 indicates there's no maximum. + */ +constexpr auto DEFAULT_MAX_NODE_ATTEMPTS = 0U; +/** + * The default minimum duration of time to wait before retrying to submit a previously-failed request to the same node. + */ +constexpr auto DEFAULT_MIN_NODE_BACKOFF = std::chrono::seconds(8); +/** + * The default maximum duration of time to wait before retrying to submit a previously-failed request to the same node. + */ +constexpr auto DEFAULT_MAX_NODE_BACKOFF = std::chrono::hours(1); +/** + * The default amount of time to allow a node to gracefully close a gRPC connection before forcibly terminating it. + */ +constexpr auto DEFAULT_CLOSE_TIMEOUT = std::chrono::seconds(30); /** * The default maximum transaction fee. */ constexpr auto DEFAULT_MAX_TRANSACTION_FEE = Hbar(2LL); +/** + * The default maximum query payment + */ +constexpr auto DEFAULT_MAX_QUERY_PAYMENT = Hbar(1LL); /** * The default auto-renew period. */ constexpr auto DEFAULT_AUTO_RENEW_PERIOD = std::chrono::hours(2160); +/** + * The default duration of time a Transaction will remain valid. + */ +constexpr auto DEFAULT_TRANSACTION_VALID_DURATION = std::chrono::minutes(2); +/** + * The default transaction ID regeneration policy. + */ +constexpr auto DEFAULT_REGENERATE_TRANSACTION_ID = true; +/** + * The default size of a chunk for a ChunkedTransaction. + */ +constexpr auto DEFAULT_CHUNK_SIZE = 1024U; /** * The default number of chunks for a ChunkedTransaction. */ diff --git a/sdk/main/include/ECDSAsecp256k1PublicKey.h b/sdk/main/include/ECDSAsecp256k1PublicKey.h index 59c7e408a..4c7d09a05 100644 --- a/sdk/main/include/ECDSAsecp256k1PublicKey.h +++ b/sdk/main/include/ECDSAsecp256k1PublicKey.h @@ -188,6 +188,15 @@ class ECDSAsecp256k1PublicKey : public PublicKey */ [[nodiscard]] std::vector toBytesRaw() const override; + /** + * Derived from PublicKey. Serialize this ECDSAsecp256k1PublicKey to a SignaturePair protobuf object with the given + * signature. + * + * @param signature The signature created by this ECDSAsecp256k1PublicKey. + */ + [[nodiscard]] std::unique_ptr toSignaturePairProtobuf( + const std::vector& signature) const override; + /** * Construct an EvmAddress from this ECDSAsecp256k1PublicKey. The constructed EvmAddress will be the last 20 bytes of * the keccak-256 hash of this ECDSAsecp256k1PublicKey. diff --git a/sdk/main/include/ED25519PublicKey.h b/sdk/main/include/ED25519PublicKey.h index 19e03596d..8f1800a46 100644 --- a/sdk/main/include/ED25519PublicKey.h +++ b/sdk/main/include/ED25519PublicKey.h @@ -139,6 +139,15 @@ class ED25519PublicKey : public PublicKey */ [[nodiscard]] std::vector toBytesRaw() const override; + /** + * Derived from PublicKey. Serialize this ED25519PublicKey to a SignaturePair protobuf object with the given + * signature. + * + * @param signature The signature created by this ED25519PublicKey. + */ + [[nodiscard]] std::unique_ptr toSignaturePairProtobuf( + const std::vector& signature) const override; + private: /** * Construct from a wrapped OpenSSL key object. diff --git a/sdk/main/include/EthereumTransaction.h b/sdk/main/include/EthereumTransaction.h index a4aa03b7e..52d1298bc 100644 --- a/sdk/main/include/EthereumTransaction.h +++ b/sdk/main/include/EthereumTransaction.h @@ -56,6 +56,14 @@ class EthereumTransaction : public Transaction */ explicit EthereumTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit EthereumTransaction(const std::map>& transactions); + /** * Set the raw Ethereum transaction (RLP encoded type 0, 1, and 2). * @@ -112,30 +120,19 @@ class EthereumTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this EthereumTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this EthereumTransaction's data to a + * Node. * - * @param client The Client trying to construct this EthereumTransaction. - * @param node The Node to which this EthereumTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this EthereumTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ContractUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this EthereumTransaction to a Node. - * - * @param client The Client submitting this EthereumTransaction. - * @param deadline The deadline for submitting this EthereumTransaction. - * @param node Pointer to the Node to which this EthereumTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the EthereumTransaction protobuf representation to the Transaction protobuf @@ -145,6 +142,11 @@ class EthereumTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this EthereumTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a EthereumTransactionBody protobuf object from this EthereumTransaction object. * diff --git a/sdk/main/include/Executable.h b/sdk/main/include/Executable.h index 422777864..82d31c1ef 100644 --- a/sdk/main/include/Executable.h +++ b/sdk/main/include/Executable.h @@ -58,8 +58,6 @@ template& timeout); /** - * Set the desired account IDs of nodes to which this transaction will be submitted. + * Set the desired account IDs of nodes to which this request will be submitted. * * @param nodeAccountIds The desired list of account IDs of nodes to submit this request. * @return A reference to this Executable derived class with the newly-set node account IDs. */ - SdkRequestType& setNodeAccountIds(const std::vector& nodeAccountIds); + virtual SdkRequestType& setNodeAccountIds(std::vector nodeAccountIds); /** * Set the maximum number of times this Executable should try to resubmit itself after a failed attempt before it @@ -159,6 +157,13 @@ class Executable [[nodiscard]] inline std::optional> getMaxBackoff() const { return mMaxBackoff; } protected: + Executable() = default; + ~Executable() = default; + Executable(const Executable&) = default; + Executable& operator=(const Executable&) = default; + Executable(Executable&&) noexcept = default; + Executable& operator=(Executable&&) noexcept = default; + /** * Enumeration describing the status of a submitted Executable. */ @@ -182,13 +187,6 @@ class Executable RETRY }; - /** - * Perform any needed actions for this Executable when a Node has been selected to which to submit this Executable. - * - * @param node The Node to which this Executable is being submitted. - */ - virtual void onSelectNode([[maybe_unused]] const std::shared_ptr& node); - /** * Determine the ExecutionStatus of this Executable after being submitted. * @@ -203,15 +201,14 @@ class Executable private: /** - * Construct a ProtoRequestType object from this Executable object. + * Construct a ProtoRequestType object from this Executable, based on the node account ID at the given index. * - * @param client The Client being used to submit this Executable. - * @param node The Node to which this Executable will be sent. - * @return A ProtoRequestType object filled with this Executable object's data. + * @param index The index of the node account ID that's associated with the Node being used to execute this + * Executable. + * @return A ProtoRequestType object filled with this Executable's data, based on the node account ID at the given + * index. */ - [[nodiscard]] virtual ProtoRequestType makeRequest( - [[maybe_unused]] const Client& client, - [[maybe_unused]] const std::shared_ptr& node) const = 0; + [[nodiscard]] virtual ProtoRequestType makeRequest(unsigned int index) const = 0; /** * Construct an SdkResponseType from a ProtoResponseType object. @@ -230,18 +227,18 @@ class Executable [[nodiscard]] virtual Status mapResponseStatus(const ProtoResponseType& response) const = 0; /** - * Submit this Executable to a Node. + * Submit a ProtoRequestType object which contains this Executable's data to a Node. * - * @param client The Client submitting this Executable. - * @param deadline The deadline for submitting this Executable. - * @param node Pointer to the Node to which this Executable should be submitted. + * @param request The ProtoRequestType object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] virtual grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] virtual grpc::Status submitRequest(const ProtoRequestType& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, ProtoResponseType* response) const = 0; /** @@ -263,14 +260,24 @@ class Executable void setExecutionParameters(const Client& client); /** - * Get a Node from a list of Nodes to which to try and send this Executable. This will prioritize getting "healthy" - * Nodes first in order to ensure as little wait time to submit as possible. + * Get a list of Nodes that are on the input Client's Network that are being run by this Executable's node account + * IDs. + * + * @param client The Client from which to get the list of Nodes. + * @return A list of Nodes that are being run by this Executable's node account IDs. + */ + [[nodiscard]] std::vector> getNodesFromNodeAccountIds(const Client& client) const; + + /** + * Get the index of a Node from a list of Nodes to which to try and send this Executable. This will prioritize getting + * "healthy" Nodes first in order to ensure as little wait time to submit as possible. * - * @param nodes The list of Nodes from which to select a Node. + * @param nodes The list of Nodes from which to select a Node. + * @param attempt The attempt number of trying to submit this Executable. * @return A pointer to a Node to which to try and send this Executable. */ - [[nodiscard]] std::shared_ptr getNodeForExecute( - const std::vector>& nodes) const; + [[nodiscard]] unsigned int getNodeIndexForExecute(const std::vector>& nodes, + unsigned int attempt) const; /** * The list of account IDs of the nodes with which execution should be attempted. @@ -299,26 +306,26 @@ class Executable * The maximum number of attempts to be used for an execution. This may be this Executable's mMaxAttempts, the * Client's max attempts, or DEFAULT_MAX_ATTEMPTS. */ - uint32_t mCurrentMaxAttempts; + uint32_t mCurrentMaxAttempts = 0; /** * The minimum backoff to be used for an execution. This may be this Executable's mMinBackoff, the Client's set * minimum backoff, or DEFAULT_MIN_BACKOFF. */ - std::chrono::duration mCurrentMinBackoff; + std::chrono::duration mCurrentMinBackoff = DEFAULT_MIN_BACKOFF; /** * The maximum backoff to be used for an execution. This may be this Executable's mMaxBackoff, the Client's set * maximum backoff, or DEFAULT_MAX_BACKOFF. */ - std::chrono::duration mCurrentMaxBackoff; + std::chrono::duration mCurrentMaxBackoff = DEFAULT_MAX_BACKOFF; /** * The current backoff time being used during the current execution. Every failed submission attempt waits a certain * amount of time that is double the previous amount of time this Executable waited for its previous submission * attempt, up to the specified maximum backoff time, at which point the execution is considered a failure. */ - std::chrono::duration mCurrentBackoff; + std::chrono::duration mCurrentBackoff = DEFAULT_MIN_BACKOFF; }; } // namespace Hedera diff --git a/sdk/main/include/FileAppendTransaction.h b/sdk/main/include/FileAppendTransaction.h index 91581137f..00066699c 100644 --- a/sdk/main/include/FileAppendTransaction.h +++ b/sdk/main/include/FileAppendTransaction.h @@ -64,6 +64,14 @@ class FileAppendTransaction : public ChunkedTransaction */ explicit FileAppendTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit FileAppendTransaction(const std::map>& transactions); + /** * Set the ID of the file to which to append. * @@ -101,33 +109,22 @@ class FileAppendTransaction : public ChunkedTransaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this FileAppendTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this FileAppendTransaction's data to a + * Node. * - * @param client The Client trying to construct this FileAppendTransaction. - * @param node The Node to which this FileAppendTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this FileAppendTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * FileAppendTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this FileAppendTransaction to a Node. - * - * @param client The Client submitting this FileAppendTransaction. - * @param deadline The deadline for submitting this FileAppendTransaction. - * @param node Pointer to the Node to which this FileAppendTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** - * Derived from Transaction. Build and add the FileAppendTransaction protobuf representation to the Transaction + * Derived from Transaction. Build and add this FileAppendTransaction's protobuf representation to the Transaction * protobuf object. * * @param body The TransactionBody protobuf object being built. @@ -135,12 +132,30 @@ class FileAppendTransaction : public ChunkedTransaction void addToBody(proto::TransactionBody& body) const override; /** - * Build a FileAppendTransactionBody protobuf object from this FileAppendTransaction object. + * Derived from ChunkedTransaction. Build and add this FileAppendTransaction's chunked protobuf representation to the + * TransactionBody protobuf object. + * + * @param chunk The chunk number. + * @param total The total number of chunks being created. + * @param body The TransactionBody protobuf object to which to add the chunked data. + */ + void addToChunk(uint32_t chunk, uint32_t /*total*/, proto::TransactionBody& body) const override; + + /** + * Initialize this FileAppendTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + + /** + * Build a FileAppendTransactionBody protobuf object from this FileAppendTransaction object. Optionally, build this + * FileAppendTransaction for a specific chunk. * + * @param chunk The chunk number for which to build this FileAppendTransaction. The default value (-1) indicates to + * build for all chunks (i.e. build with all data). * @return A pointer to a FileAppendTransactionBody protobuf object filled with this FileAppendTransaction object's * data. */ - [[nodiscard]] proto::FileAppendTransactionBody* build() const; + [[nodiscard]] proto::FileAppendTransactionBody* build(int chunk = -1) const; /** * The ID of the file to which to append. diff --git a/sdk/main/include/FileContentsQuery.h b/sdk/main/include/FileContentsQuery.h index 7554b4346..4b4d05aa8 100644 --- a/sdk/main/include/FileContentsQuery.h +++ b/sdk/main/include/FileContentsQuery.h @@ -56,47 +56,44 @@ class FileContentsQuery : public Query [[nodiscard]] inline FileId getFileId() const { return mFileId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this FileContentsQuery object. - * - * @param client The Client trying to construct this FileContentsQuery. - * @param node The Node to which this FileContentsQuery will be sent. - * @return A Query protobuf object filled with this FileContentsQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a FileContents object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a FileContents object. - * @return A FileContents object filled with the Response protobuf object's data. + * @return A FileContents object filled with the Response protobuf object's data */ [[nodiscard]] FileContents mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted FileContentsQuery from a Response + * Derived from Executable. Submit a Query protobuf object which contains this FileContentsQuery's data to a Node. + * + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. + * @return The gRPC status of the submission. + */ + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this FileContentsQuery's data, with the input QueryHeader * protobuf object. * - * @param response The Response protobuf object from which to grab the FileContentsQuery status response code. - * @return The FileContentsQuery status response code of the input Response protobuf object. + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; /** - * Derived from Executable. Submit this FileContentsQuery to a Node. + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. * - * @param client The Client submitting this FileContentsQuery. - * @param deadline The deadline for submitting this FileContentsQuery. - * @param node Pointer to the Node to which this FileContentsQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information - * from the gRPC server. - * @return The gRPC status of the submission. + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const override; + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the file of which this query should get the contents. diff --git a/sdk/main/include/FileCreateTransaction.h b/sdk/main/include/FileCreateTransaction.h index d90513463..b69ea63ea 100644 --- a/sdk/main/include/FileCreateTransaction.h +++ b/sdk/main/include/FileCreateTransaction.h @@ -65,6 +65,14 @@ class FileCreateTransaction : public Transaction */ explicit FileCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit FileCreateTransaction(const std::map>& transactions); + /** * Set the time at which the new file will expire. When the file expires, it will be deleted. To prevent the file from * being deleted, use a FileUpdateTransaction to update with the new expiration time. @@ -139,30 +147,19 @@ class FileCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this FileCreateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this FileCreateTransaction's data to a + * Node. * - * @param client The Client trying to construct this FileCreateTransaction. - * @param node The Node to which this FileCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this FileCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * FileCreateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this FileCreateTransaction to a Node. - * - * @param client The Client submitting this FileCreateTransaction. - * @param deadline The deadline for submitting this FileCreateTransaction. - * @param node Pointer to the Node to which this FileCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the FileCreateTransaction protobuf representation to the Transaction @@ -172,6 +169,11 @@ class FileCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this FileCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a FileCreateTransactionBody protobuf object from this FileCreateTransaction object. * diff --git a/sdk/main/include/FileDeleteTransaction.h b/sdk/main/include/FileDeleteTransaction.h index 86a9fe1c4..fd0cc28e2 100644 --- a/sdk/main/include/FileDeleteTransaction.h +++ b/sdk/main/include/FileDeleteTransaction.h @@ -53,6 +53,14 @@ class FileDeleteTransaction : public Transaction */ explicit FileDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit FileDeleteTransaction(const std::map>& transactions); + /** * Set the ID of the file to delete. * @@ -73,30 +81,19 @@ class FileDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this FileDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this FileDeleteTransaction's data to a + * Node. * - * @param client The Client trying to construct this FileDeleteTransaction. - * @param node The Node to which this FileDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this FileCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * FileDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this FileDeleteTransaction to a Node. - * - * @param client The Client submitting this FileDeleteTransaction. - * @param deadline The deadline for submitting this FileDeleteTransaction. - * @param node Pointer to the Node to which this FileDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the FileDeleteTransaction protobuf representation to the Transaction @@ -106,6 +103,11 @@ class FileDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this FileDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a FileDeleteTransactionBody protobuf object from this FileDeleteTransaction object. * diff --git a/sdk/main/include/FileInfoQuery.h b/sdk/main/include/FileInfoQuery.h index 4c4fedb31..d7b9ad033 100644 --- a/sdk/main/include/FileInfoQuery.h +++ b/sdk/main/include/FileInfoQuery.h @@ -54,47 +54,44 @@ class FileInfoQuery : public Query [[nodiscard]] inline FileId getfileId() const { return mFileId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this FileInfoQuery object. - * - * @param client The Client trying to construct this FileInfoQuery. - * @param node The Node to which this FileInfoQuery will be sent. - * @return A Query protobuf object filled with this FileInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a FileInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a FileInfo object. - * @return A FileInfo object filled with the Response protobuf object's data. + * @return A FileInfo object filled with the Response protobuf object's data */ [[nodiscard]] FileInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted FileInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this FileInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the FileInfoQuery status response code. - * @return The FileInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this FileInfoQuery to a Node. - * - * @param client The Client submitting this FileInfoQuery. - * @param deadline The deadline for submitting this FileInfoQuery. - * @param node Pointer to the Node to which this FileInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this FileInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the file of which this query should get the info. diff --git a/sdk/main/include/FileUpdateTransaction.h b/sdk/main/include/FileUpdateTransaction.h index f5bc21b3e..ca4891e86 100644 --- a/sdk/main/include/FileUpdateTransaction.h +++ b/sdk/main/include/FileUpdateTransaction.h @@ -63,6 +63,14 @@ class FileUpdateTransaction : public Transaction */ explicit FileUpdateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit FileUpdateTransaction(const std::map>& transactions); + /** * Set the ID of the file to update. * @@ -154,30 +162,19 @@ class FileUpdateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this FileUpdateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this FileUpdateTransaction's data to a + * Node. * - * @param client The Client trying to construct this FileUpdateTransaction. - * @param node The Node to which this FileUpdateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this FileUpdateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * FileUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this FileUpdateTransaction to a Node. - * - * @param client The Client submitting this FileUpdateTransaction. - * @param deadline The deadline for submitting this FileUpdateTransaction. - * @param node Pointer to the Node to which this FileUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the FileUpdateTransaction protobuf representation to the Transaction @@ -187,6 +184,11 @@ class FileUpdateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this FileUpdateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a FileUpdateTransactionBody protobuf object from this FileUpdateTransaction object. * diff --git a/sdk/main/include/FreezeTransaction.h b/sdk/main/include/FreezeTransaction.h index f477dec3d..1e1607503 100644 --- a/sdk/main/include/FreezeTransaction.h +++ b/sdk/main/include/FreezeTransaction.h @@ -58,6 +58,14 @@ class FreezeTransaction : public Transaction */ explicit FreezeTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit FreezeTransaction(const std::map>& transactions); + /** * Set the ID of the file to use for the network software upgrade. * @@ -128,30 +136,19 @@ class FreezeTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this FreezeTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this FreezeTransaction's data to a + * Node. * - * @param client The Client trying to construct this FreezeTransaction. - * @param node The Node to which this FreezeTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this FreezeTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * FreezeTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this FreezeTransaction to a Node. - * - * @param client The Client submitting this FreezeTransaction. - * @param deadline The deadline for submitting this FreezeTransaction. - * @param node Pointer to the Node to which this FreezeTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the FreezeTransaction protobuf representation to the Transaction @@ -161,6 +158,11 @@ class FreezeTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this FreezeTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a FreezeTransactionBody protobuf object from this FreezeTransaction object. * diff --git a/sdk/main/include/LedgerId.h b/sdk/main/include/LedgerId.h index 427a6c969..d02c98e75 100644 --- a/sdk/main/include/LedgerId.h +++ b/sdk/main/include/LedgerId.h @@ -102,6 +102,13 @@ class LedgerId */ [[nodiscard]] inline bool isPreviewnet() const { return *this == PREVIEWNET; } + /** + * Does this LedgerId represent the LedgerId of any Hedera network? + * + * @return \c TRUE if this LedgerId represents the LedgerId of any Hedera network, otherwise \c FALSE. + */ + [[nodiscard]] inline bool isKnownNetwork() const { return isMainnet() || isTestnet() || isPreviewnet(); } + /** * Get the bytes of this LedgerId. * diff --git a/sdk/main/include/NetworkVersionInfoQuery.h b/sdk/main/include/NetworkVersionInfoQuery.h index b8bbcbb21..c010953b4 100644 --- a/sdk/main/include/NetworkVersionInfoQuery.h +++ b/sdk/main/include/NetworkVersionInfoQuery.h @@ -35,47 +35,45 @@ namespace Hedera class NetworkVersionInfoQuery : public Query { private: - /** - * Derived from Executable. Construct a Query protobuf object from this NetworkVersionInfoQuery object. - * - * @param client The Client trying to construct this NetworkVersionInfoQuery. - * @param node The Node to which this NetworkVersionInfoQuery will be sent. - * @return A Query protobuf object filled with this NetworkVersionInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a NetworkVersionInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a NetworkVersionInfo object. - * @return A NetworkVersionInfo object filled with the Response protobuf object's data. + * @return A NetworkVersionInfo object filled with the Response protobuf object's data */ [[nodiscard]] NetworkVersionInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted NetworkVersionInfoQuery from a Response - * protobuf object. + * Derived from Executable. Submit a Query protobuf object which contains this NetworkVersionInfoQuery's data to a + * Node. * - * @param response The Response protobuf object from which to grab the NetworkVersionInfoQuery status response code. - * @return The NetworkVersionInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this NetworkVersionInfoQuery to a Node. - * - * @param client The Client submitting this NetworkVersionInfoQuery. - * @param deadline The deadline for submitting this NetworkVersionInfoQuery. - * @param node Pointer to the Node to which this NetworkVersionInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this NetworkVersionInfoQuery's data, with the input + * QueryHeader protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; }; } // namespace Hedera diff --git a/sdk/main/include/PublicKey.h b/sdk/main/include/PublicKey.h index 797a1a9d1..294980d92 100644 --- a/sdk/main/include/PublicKey.h +++ b/sdk/main/include/PublicKey.h @@ -31,6 +31,7 @@ namespace proto { class Key; +class SignaturePair; } namespace Hedera::internal::OpenSSLUtils @@ -68,6 +69,17 @@ class PublicKey */ [[nodiscard]] static std::unique_ptr fromStringDer(std::string_view key); + /** + * Construct a PublicKey object from a raw byte vector. This will attempt to determine the type of key based on the + * input byte vector length. + * + * @param bytes The vector of raw bytes from which to construct a PublicKey. + * @return A pointer to a PublicKey representing the input DER-encoded bytes. + * @throws BadKeyException If the public key type (ED25519 or ECDSAsecp256k1) is unable to be determined or realized + * from the input byte array. + */ + [[nodiscard]] static std::unique_ptr fromBytes(const std::vector& bytes); + /** * Construct a PublicKey object from a DER-encoded byte vector. * @@ -125,6 +137,14 @@ class PublicKey */ [[nodiscard]] virtual std::vector toBytesRaw() const = 0; + /** + * Serialize this PublicKey to a SignaturePair protobuf object with the given signature. + * + * @param signature The signature created by this PublicKey. + */ + [[nodiscard]] virtual std::unique_ptr toSignaturePairProtobuf( + const std::vector& signature) const = 0; + /** * Construct an AccountId object using this PublicKey as its alias. * diff --git a/sdk/main/include/Query.h b/sdk/main/include/Query.h index 207a49798..927953ca2 100644 --- a/sdk/main/include/Query.h +++ b/sdk/main/include/Query.h @@ -22,10 +22,24 @@ #include "Executable.h" +#include +#include + namespace proto { class Query; +class QueryHeader; class Response; +class ResponseHeader; +class Transaction; +} + +namespace Hedera +{ +class AccountId; +class Client; +class Hbar; +class TransactionId; } namespace Hedera @@ -40,24 +54,120 @@ template class Query : public Executable { public: - ~Query() override = default; + /** + * Set an amount to pay for this Query. The Client will submit exactly this amount and no remainder will be returned. + * + * @param amount The amount to pay for this Query. + * @return A reference to this derived Query with the newly-set payment. + */ + SdkRequestType& setQueryPayment(const Hbar& amount); + + /** + * Set a maximum amount to pay for this Query. A Query without an explicit payment amount set will first query for the + * cost of the Query and attach a payment for that amount from the operator account on the client to the node account + * ID. Set to 0 to disable automatic implicit payments. + * + * @param maxAmount The maximum amount to pay for this Query. + * @return A reference to this derived Query with the newly-set payment. + */ + SdkRequestType& setMaxQueryPayment(const Hbar& maxAmount); + + /** + * Get the expected cost of this Query. + * + * @param client The Client to use to fetch the cost. + * @return The expected cost of this Query. + */ + [[nodiscard]] Hbar getCost(const Client& client); + + /** + * Get the expected cost of this Query with a specific timeout. + * + * @param client The Client to use to fetch the cost. + * @param timeout The timeout to use to get the cost. + * @return The expected cost of this Query. + */ + [[nodiscard]] Hbar getCost(const Client& client, const std::chrono::duration& timeout); protected: /** * Prevent public copying and moving to prevent slicing. Use the 'clone()' virtual method instead. */ - Query() = default; - Query(const Query&) = default; - Query& operator=(const Query&) = default; - Query(Query&&) noexcept = default; - Query& operator=(Query&&) noexcept = default; + Query(); + ~Query(); + Query(const Query&); + Query& operator=(const Query&); + Query(Query&&) noexcept; + Query& operator=(Query&&) noexcept; + + /** + * Get the cost of the Query from the ResponseHeader protobuf object and set it in this Query, if this Query was + * configured to get the cost. + * + * @param header The ResponseHeader protobuf object from which to get the cost. + */ + void saveCostFromHeader(const proto::ResponseHeader& header) const; + + /** + * Is this Query meant a cost query? + * + * @return \c TRUE if this Query is meant to get the cost, otherwise \c FALSE. + */ + [[nodiscard]] bool isCostQuery() const; + +private: + /** + * Build a Query protobuf object with this Query's data, with the input QueryHeader protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] virtual proto::Query buildRequest(proto::QueryHeader* header) const = 0; + + /** + * Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] virtual proto::ResponseHeader mapResponseHeader(const proto::Response& response) const = 0; + + /** + * Derived from Executable. Construct a Query protobuf object from this Query, based on the node account ID at the + * given index. + * + * @param index The index of the node account ID that's associated with the Node being used to execute this Query. + * @return A Query protobuf object filled with this Query's data, based on the node account ID at the given index. + */ + [[nodiscard]] proto::Query makeRequest(unsigned int index) const override; + + /** + * Derived from Executable. Get the status response code from a Response protobuf object. + * + * @param response The Response protobuf object from which to grab the status response code. + * @return The status response code of the input Response protobuf object. + */ + [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; + + /** + * Derived from Executable. Perform any needed actions for this Query when it is being submitted. + * + * @param client The Client being used to submit this Query. + */ + void onExecute(const Client& client) override; + + /** + * Does this Query require payment? Default to \c TRUE, as most Queries do. + * + * @return \c TRUE if this Query requires payment, otherwise \c FALSE. + */ + [[nodiscard]] inline virtual bool isPaymentRequired() const { return true; } /** - * Derived from Executable. Perform any operations needed when this Query is being executed. + * Implementation object used to hide implementation details and internal headers. */ - void onExecute(const Client&) override - { // Intentionally unimplemented - } + struct QueryImpl; + std::unique_ptr mImpl; }; } // namespace Hedera diff --git a/sdk/main/include/ScheduleCreateTransaction.h b/sdk/main/include/ScheduleCreateTransaction.h index e555d1a12..5bcff77c7 100644 --- a/sdk/main/include/ScheduleCreateTransaction.h +++ b/sdk/main/include/ScheduleCreateTransaction.h @@ -70,7 +70,7 @@ class ScheduleCreateTransaction : public Transaction { public: ScheduleCreateTransaction(); - ~ScheduleCreateTransaction() override; + ~ScheduleCreateTransaction(); ScheduleCreateTransaction(const ScheduleCreateTransaction&); ScheduleCreateTransaction& operator=(const ScheduleCreateTransaction&); ScheduleCreateTransaction(ScheduleCreateTransaction&&) noexcept; @@ -84,6 +84,15 @@ class ScheduleCreateTransaction : public Transaction */ explicit ScheduleCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ScheduleCreateTransaction( + const std::map>& transactions); + /** * Set the Transaction to schedule. * @@ -184,30 +193,19 @@ class ScheduleCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ScheduleCreateTransaction object. - * - * @param client The Client trying to construct this ScheduleCreateTransaction. - * @param node The Node to which this ScheduleCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ScheduleCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ScheduleCreateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ScheduleCreateTransaction to a Node. + * Derived from Executable. Submit a Transaction protobuf object which contains this ScheduleCreateTransaction's data + * to a Node. * - * @param client The Client submitting this ScheduleCreateTransaction. - * @param deadline The deadline for submitting this ScheduleCreateTransaction. - * @param node Pointer to the Node to which this ScheduleCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ScheduleCreateTransaction protobuf representation to the Transaction @@ -217,6 +215,11 @@ class ScheduleCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ScheduleCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ScheduleCreateTransactionBody protobuf object from this ScheduleCreateTransaction object. * @@ -225,11 +228,6 @@ class ScheduleCreateTransaction : public Transaction */ [[nodiscard]] proto::ScheduleCreateTransactionBody* build() const; - /** - * Initialize this ScheduleCreateTransaction's implementation object. - */ - void initImpl(); - /** * Implementation object used to hide implementation details and internal headers. */ diff --git a/sdk/main/include/ScheduleDeleteTransaction.h b/sdk/main/include/ScheduleDeleteTransaction.h index 16eeba7a1..962440fa1 100644 --- a/sdk/main/include/ScheduleDeleteTransaction.h +++ b/sdk/main/include/ScheduleDeleteTransaction.h @@ -56,6 +56,15 @@ class ScheduleDeleteTransaction : public Transaction */ explicit ScheduleDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ScheduleDeleteTransaction( + const std::map>& transactions); + /** * Set the ID of the schedule to delete. * @@ -77,30 +86,19 @@ class ScheduleDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ScheduleDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this ScheduleDeleteTransaction's data + * to a Node. * - * @param client The Client trying to construct this ScheduleDeleteTransaction. - * @param node The Node to which this ScheduleDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ScheduleDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ScheduleDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ScheduleDeleteTransaction to a Node. - * - * @param client The Client submitting this ScheduleDeleteTransaction. - * @param deadline The deadline for submitting this ScheduleDeleteTransaction. - * @param node Pointer to the Node to which this ScheduleDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ScheduleDeleteTransaction protobuf representation to the Transaction @@ -110,6 +108,11 @@ class ScheduleDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ScheduleDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ScheduleDeleteTransactionBody protobuf object from this ScheduleDeleteTransaction object. * diff --git a/sdk/main/include/ScheduleInfoQuery.h b/sdk/main/include/ScheduleInfoQuery.h index 153a83940..9ac95f421 100644 --- a/sdk/main/include/ScheduleInfoQuery.h +++ b/sdk/main/include/ScheduleInfoQuery.h @@ -53,47 +53,44 @@ class ScheduleInfoQuery : public Query [[nodiscard]] inline ScheduleId getScheduleId() const { return mScheduleId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this ScheduleInfoQuery object. - * - * @param client The Client trying to construct this ScheduleInfoQuery. - * @param node The Node to which this ScheduleInfoQuery will be sent. - * @return A Query protobuf object filled with this ScheduleInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a ScheduleInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a ScheduleInfo object. - * @return A ScheduleInfo object filled with the Response protobuf object's data. + * @return A ScheduleInfo object filled with the Response protobuf object's data */ [[nodiscard]] ScheduleInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted ScheduleInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this ScheduleInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the ScheduleInfoQuery status response code. - * @return The ScheduleInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this ScheduleInfoQuery to a Node. - * - * @param client The Client submitting this ScheduleInfoQuery. - * @param deadline The deadline for submitting this ScheduleInfoQuery. - * @param node Pointer to the Node to which this ScheduleInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this ScheduleInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the schedule of which this query should get the info. diff --git a/sdk/main/include/ScheduleSignTransaction.h b/sdk/main/include/ScheduleSignTransaction.h index 91ae3dcea..3691c621a 100644 --- a/sdk/main/include/ScheduleSignTransaction.h +++ b/sdk/main/include/ScheduleSignTransaction.h @@ -56,6 +56,15 @@ class ScheduleSignTransaction : public Transaction */ explicit ScheduleSignTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit ScheduleSignTransaction( + const std::map>& transactions); + /** * Set the ID of the schedule to sign. * @@ -85,30 +94,19 @@ class ScheduleSignTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this ScheduleSignTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this ScheduleSignTransaction's data to + * a Node. * - * @param client The Client trying to construct this ScheduleSignTransaction. - * @param node The Node to which this ScheduleSignTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this ScheduleSignTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * ScheduleSignTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this ScheduleSignTransaction to a Node. - * - * @param client The Client submitting this ScheduleSignTransaction. - * @param deadline The deadline for submitting this ScheduleSignTransaction. - * @param node Pointer to the Node to which this ScheduleSignTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the ScheduleSignTransaction protobuf representation to the Transaction @@ -118,6 +116,11 @@ class ScheduleSignTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this ScheduleSignTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ScheduleSignTransactionBody protobuf object from this ScheduleSignTransaction object. * diff --git a/sdk/main/include/SystemDeleteTransaction.h b/sdk/main/include/SystemDeleteTransaction.h index b09e19588..1b73b0010 100644 --- a/sdk/main/include/SystemDeleteTransaction.h +++ b/sdk/main/include/SystemDeleteTransaction.h @@ -57,6 +57,15 @@ class SystemDeleteTransaction : public Transaction */ explicit SystemDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit SystemDeleteTransaction( + const std::map>& transactions); + /** * Set the ID of the file to delete. This is mutually exclusive with mContractId, and will reset the value of * mContractId if it is set. @@ -113,30 +122,19 @@ class SystemDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this SystemDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this SystemDeleteTransaction's data to + * a Node. * - * @param client The Client trying to construct this SystemDeleteTransaction. - * @param node The Node to which this SystemDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this SystemDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * SystemDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this SystemDeleteTransaction to a Node. - * - * @param client The Client submitting this SystemDeleteTransaction. - * @param deadline The deadline for submitting this SystemDeleteTransaction. - * @param node Pointer to the Node to which this SystemDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the SystemDeleteTransaction protobuf representation to the Transaction @@ -146,6 +144,11 @@ class SystemDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this SystemDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a SystemDeleteTransactionBody protobuf object from this SystemDeleteTransaction object. * diff --git a/sdk/main/include/SystemUndeleteTransaction.h b/sdk/main/include/SystemUndeleteTransaction.h index 0f19566cf..912644510 100644 --- a/sdk/main/include/SystemUndeleteTransaction.h +++ b/sdk/main/include/SystemUndeleteTransaction.h @@ -53,6 +53,15 @@ class SystemUndeleteTransaction : public Transaction */ explicit SystemUndeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit SystemUndeleteTransaction( + const std::map>& transactions); + /** * Set the ID of the file to undelete. This is mutually exclusive with mContractId, and will reset the value of * mContractId if it is set. @@ -93,30 +102,19 @@ class SystemUndeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this SystemUndeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this SystemUndeleteTransaction's data + * to a Node. * - * @param client The Client trying to construct this SystemUndeleteTransaction. - * @param node The Node to which this SystemUndeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this SystemUndeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * SystemUndeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this SystemUndeleteTransaction to a Node. - * - * @param client The Client submitting this SystemUndeleteTransaction. - * @param deadline The deadline for submitting this SystemUndeleteTransaction. - * @param node Pointer to the Node to which this SystemUndeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the SystemUndeleteTransaction protobuf representation to the Transaction @@ -126,6 +124,11 @@ class SystemUndeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this SystemUndeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a SystemUndeleteTransactionBody protobuf object from this SystemUndeleteTransaction object. * diff --git a/sdk/main/include/TokenAssociateTransaction.h b/sdk/main/include/TokenAssociateTransaction.h index e2884a7e4..742be8553 100644 --- a/sdk/main/include/TokenAssociateTransaction.h +++ b/sdk/main/include/TokenAssociateTransaction.h @@ -74,6 +74,15 @@ class TokenAssociateTransaction : public Transaction */ explicit TokenAssociateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenAssociateTransaction( + const std::map>& transactions); + /** * Set the ID of the account to be associated with the provided tokens. * @@ -111,30 +120,19 @@ class TokenAssociateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenAssociateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenAssociateTransaction's data + * to a Node. * - * @param client The Client trying to construct this TokenAssociateTransaction. - * @param node The Node to which this TokenAssociateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenAssociateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenAssociateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenAssociateTransaction to a Node. - * - * @param client The Client submitting this TokenAssociateTransaction. - * @param deadline The deadline for submitting this TokenAssociateTransaction. - * @param node Pointer to the Node to which this TokenAssociateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenAssociateTransaction protobuf representation to the Transaction @@ -144,6 +142,11 @@ class TokenAssociateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenAssociateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenAssociateTransactionBody protobuf object from this TokenAssociateTransaction object. * diff --git a/sdk/main/include/TokenBurnTransaction.h b/sdk/main/include/TokenBurnTransaction.h index 1ddaa8916..0df3c75a4 100644 --- a/sdk/main/include/TokenBurnTransaction.h +++ b/sdk/main/include/TokenBurnTransaction.h @@ -58,6 +58,14 @@ class TokenBurnTransaction : public Transaction */ explicit TokenBurnTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenBurnTransaction(const std::map>& transactions); + /** * Set the ID of the token to burn. * @@ -110,30 +118,19 @@ class TokenBurnTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenBurnTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenBurnTransaction's data to a + * Node. * - * @param client The Client trying to construct this TokenBurnTransaction. - * @param node The Node to which this TokenBurnTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenBurnTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenBurnTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenBurnTransaction to a Node. - * - * @param client The Client submitting this TokenBurnTransaction. - * @param deadline The deadline for submitting this TokenBurnTransaction. - * @param node Pointer to the Node to which this TokenBurnTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenBurnTransaction protobuf representation to the Transaction @@ -143,6 +140,11 @@ class TokenBurnTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenBurnTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenBurnTransactionBody protobuf object from this TokenBurnTransaction object. * diff --git a/sdk/main/include/TokenCreateTransaction.h b/sdk/main/include/TokenCreateTransaction.h index 40dc46a2f..88293de10 100644 --- a/sdk/main/include/TokenCreateTransaction.h +++ b/sdk/main/include/TokenCreateTransaction.h @@ -71,6 +71,14 @@ class TokenCreateTransaction : public Transaction */ explicit TokenCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenCreateTransaction(const std::map>& transactions); + /** * Set the desired name for the new token. * @@ -395,30 +403,19 @@ class TokenCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenCreateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenCreateTransaction's data to + * a Node. * - * @param client The Client trying to construct this TokenCreateTransaction. - * @param node The Node to which this TokenCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenCreateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenCreateTransaction to a Node. - * - * @param client The Client submitting this TokenCreateTransaction. - * @param deadline The deadline for submitting this TokenCreateTransaction. - * @param node Pointer to the Node to which this TokenCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenCreateTransaction protobuf representation to the Transaction @@ -428,6 +425,11 @@ class TokenCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenCreateTransactionBody protobuf object from this TokenCreateTransaction object. * diff --git a/sdk/main/include/TokenDeleteTransaction.h b/sdk/main/include/TokenDeleteTransaction.h index 161aac862..47be5021b 100644 --- a/sdk/main/include/TokenDeleteTransaction.h +++ b/sdk/main/include/TokenDeleteTransaction.h @@ -59,6 +59,14 @@ class TokenDeleteTransaction : public Transaction */ explicit TokenDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenDeleteTransaction(const std::map>& transactions); + /** * Set the ID of the token to delete. * @@ -80,29 +88,19 @@ class TokenDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenDeleteTransaction's data to + * a Node. * - * @param client The Client trying to construct this TokenDeleteTransaction. - * @param node The Node to which this TokenDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TokenDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenDeleteTransaction to a Node. - * - * @param client The Client submitting this TokenDeleteTransaction. - * @param deadline The deadline for submitting this TokenDeleteTransaction. - * @param node Pointer to the Node to which this TokenDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenDeleteTransaction protobuf representation to the Transaction @@ -112,6 +110,11 @@ class TokenDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenDeleteTransactionBody protobuf object from this TokenDeleteTransaction object. * diff --git a/sdk/main/include/TokenDissociateTransaction.h b/sdk/main/include/TokenDissociateTransaction.h index 3ff5e7400..d5733e63e 100644 --- a/sdk/main/include/TokenDissociateTransaction.h +++ b/sdk/main/include/TokenDissociateTransaction.h @@ -69,6 +69,15 @@ class TokenDissociateTransaction : public Transaction>& transactions); + /** * Set the ID of the account to be dissociated from the provided tokens. * @@ -106,30 +115,19 @@ class TokenDissociateTransaction : public Transaction& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenDissociateTransaction to a Node. - * - * @param client The Client submitting this TokenDissociateTransaction. - * @param deadline The deadline for submitting this TokenDissociateTransaction. - * @param node Pointer to the Node to which this TokenDissociateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenDissociateTransaction protobuf representation to the Transaction @@ -139,6 +137,11 @@ class TokenDissociateTransaction : public Transaction>& transactions); + /** * Set the ID of the token whose fee schedule is to be updated. * @@ -94,31 +103,19 @@ class TokenFeeScheduleUpdateTransaction : public Transaction& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenFeeScheduleUpdateTransaction to a Node. - * - * @param client The Client submitting this TokenFeeScheduleUpdateTransaction. - * @param deadline The deadline for submitting this TokenFeeScheduleUpdateTransaction. - * @param node Pointer to the Node to which this TokenFeeScheduleUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenFeeScheduleUpdateTransaction protobuf representation to the @@ -128,6 +125,11 @@ class TokenFeeScheduleUpdateTransaction : public Transaction */ explicit TokenFreezeTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenFreezeTransaction(const std::map>& transactions); + /** * Set the ID of the account to be frozen for the specified token. * @@ -99,29 +107,19 @@ class TokenFreezeTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenFreezeTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenFreezeTransaction's data to + * a Node. * - * @param client The Client trying to construct this TokenFreezeTransaction. - * @param node The Node to which this TokenFreezeTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenFreezeTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TokenFreezeTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenFreezeTransaction to a Node. - * - * @param client The Client submitting this TokenFreezeTransaction. - * @param deadline The deadline for submitting this TokenFreezeTransaction. - * @param node Pointer to the Node to which this TokenFreezeTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenFreezeTransaction protobuf representation to the Transaction @@ -131,6 +129,11 @@ class TokenFreezeTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenFreezeTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenFreezeAccountTransactionBody protobuf object from this TokenFreezeTransaction object. * diff --git a/sdk/main/include/TokenGrantKycTransaction.h b/sdk/main/include/TokenGrantKycTransaction.h index 4557ef197..7da1c0ee1 100644 --- a/sdk/main/include/TokenGrantKycTransaction.h +++ b/sdk/main/include/TokenGrantKycTransaction.h @@ -65,6 +65,15 @@ class TokenGrantKycTransaction : public Transaction */ explicit TokenGrantKycTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenGrantKycTransaction( + const std::map>& transactions); + /** * Set the ID of the account to have passed KYC for this token. * @@ -101,30 +110,19 @@ class TokenGrantKycTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenGrantKycTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenGrantKycTransaction's data + * to a Node. * - * @param client The Client trying to construct this TokenGrantKycTransaction. - * @param node The Node to which this TokenGrantKycTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenGrantKycTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenGrantKycTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenGrantKycTransaction to a Node. - * - * @param client The Client submitting this TokenGrantKycTransaction. - * @param deadline The deadline for submitting this TokenGrantKycTransaction. - * @param node Pointer to the Node to which this TokenGrantKycTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenGrantKycTransaction protobuf representation to the Transaction @@ -134,6 +132,11 @@ class TokenGrantKycTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenGrantKycTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenGrantKycTransactionBody protobuf object from this TokenGrantKycTransaction object. * diff --git a/sdk/main/include/TokenInfoQuery.h b/sdk/main/include/TokenInfoQuery.h index b641b1b3e..f3b8fe06b 100644 --- a/sdk/main/include/TokenInfoQuery.h +++ b/sdk/main/include/TokenInfoQuery.h @@ -53,47 +53,44 @@ class TokenInfoQuery : public Query [[nodiscard]] inline TokenId getTokenId() const { return mTokenId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this TokenInfoQuery object. - * - * @param client The Client trying to construct this TokenInfoQuery. - * @param node The Node to which this TokenInfoQuery will be sent. - * @return A Query protobuf object filled with this TokenInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a TokenInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a TokenInfo object. - * @return A TokenInfo object filled with the Response protobuf object's data. + * @return A TokenInfo object filled with the Response protobuf object's data */ [[nodiscard]] TokenInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted TokenInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this TokenInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the TokenInfoQuery status response code. - * @return The TokenInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this TokenInfoQuery to a Node. - * - * @param client The Client submitting this TokenInfoQuery. - * @param deadline The deadline for submitting this TokenInfoQuery. - * @param node Pointer to the Node to which this TokenInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this TokenInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the token of which this query should get the info. diff --git a/sdk/main/include/TokenMintTransaction.h b/sdk/main/include/TokenMintTransaction.h index 94d030af5..0d780836f 100644 --- a/sdk/main/include/TokenMintTransaction.h +++ b/sdk/main/include/TokenMintTransaction.h @@ -73,6 +73,14 @@ class TokenMintTransaction : public Transaction */ explicit TokenMintTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenMintTransaction(const std::map>& transactions); + /** * Set the ID of the token to mint. * @@ -130,29 +138,19 @@ class TokenMintTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenMintTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenMintTransaction's data to a + * Node. * - * @param client The Client trying to construct this TokenMintTransaction. - * @param node The Node to which this TokenMintTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenMintTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TokenMintTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenMintTransaction to a Node. - * - * @param client The Client submitting this TokenMintTransaction. - * @param deadline The deadline for submitting this TokenMintTransaction. - * @param node Pointer to the Node to which this TokenMintTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenMintTransaction protobuf representation to the Transaction @@ -162,6 +160,11 @@ class TokenMintTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenMintTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenMintTransactionBody protobuf object from this TokenMintTransaction object. * diff --git a/sdk/main/include/TokenNftInfoQuery.h b/sdk/main/include/TokenNftInfoQuery.h index bb124564d..34503fd0f 100644 --- a/sdk/main/include/TokenNftInfoQuery.h +++ b/sdk/main/include/TokenNftInfoQuery.h @@ -58,47 +58,44 @@ class TokenNftInfoQuery : public Query [[nodiscard]] inline NftId getNftId() const { return mNftId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this TokenNftInfoQuery object. - * - * @param client The Client trying to construct this TokenNftInfoQuery. - * @param node The Node to which this TokenNftInfoQuery will be sent. - * @return A Query protobuf object filled with this TokenNftInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a TokenNftInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a TokenNftInfo object. - * @return A TokenNftInfo object filled with the Response protobuf object's data. + * @return A TokenNftInfo object filled with the Response protobuf object's data */ [[nodiscard]] TokenNftInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted TokenNftInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this TokenNftInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the TokenNftInfoQuery status response code. - * @return The TokenNftInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this TokenNftInfoQuery to a Node. - * - * @param client The Client submitting this TokenNftInfoQuery. - * @param deadline The deadline for submitting this TokenNftInfoQuery. - * @param node Pointer to the Node to which this TokenNftInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this TokenNftInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the NFT of which this query should get the info. diff --git a/sdk/main/include/TokenPauseTransaction.h b/sdk/main/include/TokenPauseTransaction.h index 79036b1ee..532811f37 100644 --- a/sdk/main/include/TokenPauseTransaction.h +++ b/sdk/main/include/TokenPauseTransaction.h @@ -70,6 +70,14 @@ class TokenPauseTransaction : public Transaction */ explicit TokenPauseTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenPauseTransaction(const std::map>& transactions); + /** * Set the ID of the tokens to pause. * @@ -90,30 +98,19 @@ class TokenPauseTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenPauseTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenPauseTransaction's data to a + * Node. * - * @param client The Client trying to construct this TokenPauseTransaction. - * @param node The Node to which this TokenPauseTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenPauseTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenPauseTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenPauseTransaction to a Node. - * - * @param client The Client submitting this TokenPauseTransaction. - * @param deadline The deadline for submitting this TokenPauseTransaction. - * @param node Pointer to the Node to which this TokenPauseTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenPauseTransaction protobuf representation to the Transaction @@ -123,6 +120,11 @@ class TokenPauseTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenPauseTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenPauseTransactionBody protobuf object from this TokenPauseTransaction object. * diff --git a/sdk/main/include/TokenRevokeKycTransaction.h b/sdk/main/include/TokenRevokeKycTransaction.h index 0bfda68e8..165a55ba8 100644 --- a/sdk/main/include/TokenRevokeKycTransaction.h +++ b/sdk/main/include/TokenRevokeKycTransaction.h @@ -66,6 +66,15 @@ class TokenRevokeKycTransaction : public Transaction */ explicit TokenRevokeKycTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenRevokeKycTransaction( + const std::map>& transactions); + /** * Set the ID of the account to have its KYC revoked for this token. * @@ -102,30 +111,19 @@ class TokenRevokeKycTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenRevokeKycTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenRevokeKycTransaction's data + * to a Node. * - * @param client The Client trying to construct this TokenRevokeKycTransaction. - * @param node The Node to which this TokenRevokeKycTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenRevokeKycTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenRevokeKycTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenRevokeKycTransaction to a Node. - * - * @param client The Client submitting this TokenRevokeKycTransaction. - * @param deadline The deadline for submitting this TokenRevokeKycTransaction. - * @param node Pointer to the Node to which this TokenRevokeKycTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenRevokeKycTransaction protobuf representation to the Transaction @@ -135,6 +133,11 @@ class TokenRevokeKycTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenRevokeKycTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenRevokeKycTransactionBody protobuf object from this TokenRevokeKycTransaction object. * diff --git a/sdk/main/include/TokenUnfreezeTransaction.h b/sdk/main/include/TokenUnfreezeTransaction.h index 60f6b9345..86e6ecf16 100644 --- a/sdk/main/include/TokenUnfreezeTransaction.h +++ b/sdk/main/include/TokenUnfreezeTransaction.h @@ -63,6 +63,15 @@ class TokenUnfreezeTransaction : public Transaction */ explicit TokenUnfreezeTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenUnfreezeTransaction( + const std::map>& transactions); + /** * Set the ID of the account to be unfrozen for the specified token. * @@ -99,30 +108,19 @@ class TokenUnfreezeTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenUnfreezeTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenUnfreezeTransaction's data + * to a Node. * - * @param client The Client trying to construct this TokenUnfreezeTransaction. - * @param node The Node to which this TokenUnfreezeTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenUnfreezeTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenUnfreezeTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenUnfreezeTransaction to a Node. - * - * @param client The Client submitting this TokenUnfreezeTransaction. - * @param deadline The deadline for submitting this TokenUnfreezeTransaction. - * @param node Pointer to the Node to which this TokenUnfreezeTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenUnfreezeTransaction protobuf representation to the Transaction @@ -132,6 +130,11 @@ class TokenUnfreezeTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenUnfreezeTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenUnfreezeAccountTransactionBody protobuf object from this TokenUnfreezeTransaction object. * diff --git a/sdk/main/include/TokenUnpauseTransaction.h b/sdk/main/include/TokenUnpauseTransaction.h index 95476c0c9..9b79819c1 100644 --- a/sdk/main/include/TokenUnpauseTransaction.h +++ b/sdk/main/include/TokenUnpauseTransaction.h @@ -53,6 +53,15 @@ class TokenUnpauseTransaction : public Transaction */ explicit TokenUnpauseTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenUnpauseTransaction( + const std::map>& transactions); + /** * Set the ID of the token to unpause. * @@ -73,30 +82,19 @@ class TokenUnpauseTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenUnpauseTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenUnpauseTransaction's data to + * a Node. * - * @param client The Client trying to construct this TokenUnpauseTransaction. - * @param node The Node to which this TokenUnpauseTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenUnpauseTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenUnpauseTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenUnpauseTransaction to a Node. - * - * @param client The Client submitting this TokenUnpauseTransaction. - * @param deadline The deadline for submitting this TokenUnpauseTransaction. - * @param node Pointer to the Node to which this TokenUnpauseTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenUnpauseTransaction protobuf representation to the Transaction @@ -106,6 +104,11 @@ class TokenUnpauseTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenUnpauseTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenUnpauseTransactionBody protobuf object from this TokenUnpauseTransaction object. * diff --git a/sdk/main/include/TokenUpdateTransaction.h b/sdk/main/include/TokenUpdateTransaction.h index e50ba0f8a..76c622413 100644 --- a/sdk/main/include/TokenUpdateTransaction.h +++ b/sdk/main/include/TokenUpdateTransaction.h @@ -64,6 +64,14 @@ class TokenUpdateTransaction : public Transaction */ explicit TokenUpdateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenUpdateTransaction(const std::map>& transactions); + /** * Set the ID of the token to update. * @@ -301,30 +309,19 @@ class TokenUpdateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenUpdateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenUpdateTransaction's data to + * a Node. * - * @param client The Client trying to construct this TokenUpdateTransaction. - * @param node The Node to which this TokenUpdateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenUpdateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenUpdateTransaction to a Node. - * - * @param client The Client submitting this TokenUpdateTransaction. - * @param deadline The deadline for submitting this TokenUpdateTransaction. - * @param node Pointer to the Node to which this TokenUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenUpdateTransaction protobuf representation to the Transaction @@ -334,6 +331,11 @@ class TokenUpdateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenUpdateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenUpdateTransactionBody protobuf object from this TokenUpdateTransaction object. * diff --git a/sdk/main/include/TokenWipeTransaction.h b/sdk/main/include/TokenWipeTransaction.h index d2249c814..80a672cf4 100644 --- a/sdk/main/include/TokenWipeTransaction.h +++ b/sdk/main/include/TokenWipeTransaction.h @@ -74,6 +74,14 @@ class TokenWipeTransaction : public Transaction */ explicit TokenWipeTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TokenWipeTransaction(const std::map>& transactions); + /** * Set the ID of the token to wipe. * @@ -143,30 +151,19 @@ class TokenWipeTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TokenWipeTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TokenWipeTransaction's data to a + * Node. * - * @param client The Client trying to construct this TokenWipeTransaction. - * @param node The Node to which this TokenWipeTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TokenWipeTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TokenWipeTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TokenWipeTransaction to a Node. - * - * @param client The Client submitting this TokenWipeTransaction. - * @param deadline The deadline for submitting this TokenWipeTransaction. - * @param node Pointer to the Node to which this TokenWipeTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TokenWipeTransaction protobuf representation to the Transaction @@ -176,6 +173,11 @@ class TokenWipeTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TokenWipeTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a TokenWipeAccountTransactionBody protobuf object from this TokenWipeTransaction object. * diff --git a/sdk/main/include/TopicCreateTransaction.h b/sdk/main/include/TopicCreateTransaction.h index 799801069..4b9cf0c2a 100644 --- a/sdk/main/include/TopicCreateTransaction.h +++ b/sdk/main/include/TopicCreateTransaction.h @@ -67,6 +67,14 @@ class TopicCreateTransaction : public Transaction */ explicit TopicCreateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TopicCreateTransaction(const std::map>& transactions); + /** * Set the desired memo for the new topic. * @@ -152,29 +160,19 @@ class TopicCreateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TopicCreateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TopicCreateTransaction's data to + * a Node. * - * @param client The Client trying to construct this TopicCreateTransaction. - * @param node The Node to which this TopicCreateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TopicCreateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TopicCreateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TopicCreateTransaction to a Node. - * - * @param client The Client submitting this TopicCreateTransaction. - * @param deadline The deadline for submitting this TopicCreateTransaction. - * @param node Pointer to the Node to which this TopicCreateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TopicCreateTransaction protobuf representation to the Transaction @@ -184,6 +182,11 @@ class TopicCreateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TopicCreateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ConsensusCreateTopicTransactionBody protobuf object from this TopicCreateTransaction object. * diff --git a/sdk/main/include/TopicDeleteTransaction.h b/sdk/main/include/TopicDeleteTransaction.h index 3cda160c2..3fc56e864 100644 --- a/sdk/main/include/TopicDeleteTransaction.h +++ b/sdk/main/include/TopicDeleteTransaction.h @@ -57,6 +57,14 @@ class TopicDeleteTransaction : public Transaction */ explicit TopicDeleteTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TopicDeleteTransaction(const std::map>& transactions); + /** * Set the ID of the topic to delete. * @@ -78,30 +86,19 @@ class TopicDeleteTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TopicDeleteTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TopicDeleteTransaction's data to + * a Node. * - * @param client The Client trying to construct this TopicDeleteTransaction. - * @param node The Node to which this TopicDeleteTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TopicDeleteTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TopicDeleteTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TopicDeleteTransaction to a Node. - * - * @param client The Client submitting this TopicDeleteTransaction. - * @param deadline The deadline for submitting this TopicDeleteTransaction. - * @param node Pointer to the Node to which this TopicDeleteTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TopicDeleteTransaction protobuf representation to the Transaction @@ -111,6 +108,11 @@ class TopicDeleteTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TopicDeleteTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ConsensusDeleteTopicTransactionBody protobuf object from this TopicDeleteTransaction object. * diff --git a/sdk/main/include/TopicInfoQuery.h b/sdk/main/include/TopicInfoQuery.h index 8bb4a73cf..fa08a76e6 100644 --- a/sdk/main/include/TopicInfoQuery.h +++ b/sdk/main/include/TopicInfoQuery.h @@ -53,47 +53,44 @@ class TopicInfoQuery : public Query [[nodiscard]] inline TopicId getTopicId() const { return mTopicId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this TopicInfoQuery object. - * - * @param client The Client trying to construct this TopicInfoQuery. - * @param node The Node to which this TopicInfoQuery will be sent. - * @return A Query protobuf object filled with this TopicInfoQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a TopicInfo object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a TopicInfo object. - * @return A TopicInfo object filled with the Response protobuf object's data. + * @return A TopicInfo object filled with the Response protobuf object's data */ [[nodiscard]] TopicInfo mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted TopicInfoQuery from a Response protobuf - * object. + * Derived from Executable. Submit a Query protobuf object which contains this TopicInfoQuery's data to a Node. * - * @param response The Response protobuf object from which to grab the TopicInfoQuery status response code. - * @return The TopicInfoQuery status response code of the input Response protobuf object. - */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; - - /** - * Derived from Executable. Submit this TopicInfoQuery to a Node. - * - * @param client The Client submitting this TopicInfoQuery. - * @param deadline The deadline for submitting this TopicInfoQuery. - * @param node Pointer to the Node to which this TopicInfoQuery should be submitted. - * @param response Pointer to the Response protobuf object that gRPC should populate with the response information + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::Response* response) const override; + /** + * Derived from Query. Build a Query protobuf object with this TopicInfoQuery's data, with the input QueryHeader + * protobuf object. + * + * @param header A pointer to the QueryHeader protobuf object to add to the Query protobuf object. + * @return The constructed Query protobuf object. + */ + [[nodiscard]] proto::Query buildRequest(proto::QueryHeader* header) const override; + + /** + * Derived from Query. Get the ResponseHeader protobuf object from the input Response protobuf object. + * + * @param response The Response protobuf object from which to get the ResponseHeader protobuf object. + * @return The ResponseHeader protobuf object of the input Response protobuf object for this derived Query. + */ + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the topic of which this query should get the info. diff --git a/sdk/main/include/TopicMessageSubmitTransaction.h b/sdk/main/include/TopicMessageSubmitTransaction.h index 77f55218c..a1e10d913 100644 --- a/sdk/main/include/TopicMessageSubmitTransaction.h +++ b/sdk/main/include/TopicMessageSubmitTransaction.h @@ -59,6 +59,15 @@ class TopicMessageSubmitTransaction : public ChunkedTransaction>& transactions); + /** * Set the ID of the topic to which to submit a message. * @@ -93,34 +102,22 @@ class TopicMessageSubmitTransaction : public ChunkedTransaction getMessage() const { return getData(); } private: - friend class ChunkedTransaction; friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TopicMessageSubmitTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TopicMessageSubmitTransaction's + * data to a Node. * - * @param client The Client trying to construct this TopicMessageSubmitTransaction. - * @param node The Node to which this TopicMessageSubmitTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TopicMessageSubmitTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this - * TopicMessageSubmitTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TopicMessageSubmitTransaction to a Node. - * - * @param client The Client submitting this TopicMessageSubmitTransaction. - * @param deadline The deadline for submitting this TopicMessageSubmitTransaction. - * @param node Pointer to the Node to which this TopicMessageSubmitTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TopicMessageSubmitTransaction protobuf representation to the @@ -131,44 +128,35 @@ class TopicMessageSubmitTransaction : public ChunkedTransaction */ explicit TopicUpdateTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TopicUpdateTransaction(const std::map>& transactions); + /** * Set the ID of the topic to update. * @@ -213,29 +221,19 @@ class TopicUpdateTransaction : public Transaction friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TopicUpdateTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TopicUpdateTransaction's data to + * a Node. * - * @param client The Client trying to construct this TopicUpdateTransaction. - * @param node The Node to which this TopicUpdateTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TopicUpdateTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TopicUpdateTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TopicUpdateTransaction to a Node. - * - * @param client The Client submitting this TopicUpdateTransaction. - * @param deadline The deadline for submitting this TopicUpdateTransaction. - * @param node Pointer to the Node to which this TopicUpdateTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TopicUpdateTransaction protobuf representation to the Transaction @@ -245,6 +243,11 @@ class TopicUpdateTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TopicUpdateTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a ConsensusUpdateTopicTransactionBody protobuf object from this TopicUpdateTransaction object. * diff --git a/sdk/main/include/Transaction.h b/sdk/main/include/Transaction.h index 16d21f265..09c187598 100644 --- a/sdk/main/include/Transaction.h +++ b/sdk/main/include/Transaction.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,7 @@ class WrappedTransaction; namespace proto { class SchedulableTransactionBody; +class SignedTransaction; class Transaction; class TransactionBody; class TransactionResponse; @@ -62,8 +64,8 @@ class Transaction { public: /** - * Construct a Transaction derived class from a byte array. The bytes can be a protobuf encoded TransactionBody, - * Transaction, or SignedTransaction. Since C++ return types must be known at compile time and the type of Transaction + * Construct a Transaction derived class from a byte array. The bytes can be a protobuf encoded TransactionList, + * Transaction, or TransactionBody. Since C++ return types must be known at compile time and the type of Transaction * to create may not be known at compile time, a WrappedTransaction is used to encompass all possible Transactions in * a std::variant. Usage of this return type would look like the following: * @@ -95,6 +97,13 @@ class Transaction */ [[nodiscard]] static WrappedTransaction fromBytes(const std::vector& bytes); + /** + * Construct a representative byte array from this Transaction object. + * + * @return The byte array representing this Transaction object. + */ + [[nodiscard]] std::vector toBytes() const; + /** * Sign this Transaction with the given PrivateKey. Signing a Transaction with a key that has already been used to * sign will be ignored. @@ -117,13 +126,49 @@ class Transaction SdkRequestType& signWith(const std::shared_ptr& key, const std::function(const std::vector&)>& signer); + /** + * Sign this Transaction with a configured Client. This will freeze this Transaction if it is not already frozen. + * + * @param client The Client with which to sign this Transaction. + * @return A reference to this derived Transaction object with the client signature. + * @throws UninitializedException If the input Client operator has not been initialized. + */ + SdkRequestType& signWithOperator(const Client& client); + + /** + * Add a signature to this Transaction. + * + * @param publicKey The associated PublicKey of the PrivateKey that generated the signature. + * @param signature The signature to add. + * @return A reference to this derived Transaction object with the newly-added signature. + * @throws IllegalStateException If there is not exactly one node account ID set or if this Transaction is not frozen. + */ + virtual SdkRequestType& addSignature(const std::shared_ptr& publicKey, + const std::vector& signature); + + /** + * Get the signatures of each potential Transaction protobuf object this Transaction may send. + * + * @return The map of node account IDs to their PublicKeys and signatures. + */ + [[nodiscard]] virtual std::map, std::vector>> + getSignatures() const; + + /** + * Freeze this Transaction. + * + * @return A reference to this derived Transaction object, now frozen. + * @throws IllegalStateException If this Transaction's TransactionId and node account IDs have not been manually set. + */ + SdkRequestType& freeze(); + /** * Freeze this transaction with a Client. The Client's operator will be used to generate a transaction ID, and the - * client's network will be used to generate a list of node account IDs. + * Client's network will be used to generate a list of node account IDs. * * @param client A pointer to the Client with which to freeze this Transaction. * @return A reference to this derived Transaction object, now frozen. - * @throws UninitializedException If Client operator has not been initialized. + * @throws UninitializedException If the input Client operator has not been initialized. */ SdkRequestType& freezeWith(const Client* client); @@ -131,137 +176,216 @@ class Transaction * Put this Transaction in a ScheduleCreateTransaction. * * @return This Transaction put in a ScheduleCreateTransaction. - * @throws IllegalStateException If this transaction has node account IDs already set; it is not allowed. + * @throws IllegalStateException If this Transaction has node account IDs already set. */ [[nodiscard]] ScheduleCreateTransaction schedule() const; /** - * Set the length of time that this Transaction will remain valid. + * Get the SHA384 hash of this Transaction. * - * @param duration The desired length of time to keep this Transaction valid. - * @return A reference to this derived Transaction object with the newly-set valid duration. + * @return The SHA384 hash of this Transaction. + * @throws IllegalStateException If this Transaction is not frozen. */ - SdkRequestType& setValidTransactionDuration(const std::chrono::duration& duration); + [[nodiscard]] virtual std::vector getTransactionHash() const; /** - * Set the maximum transaction fee willing to be paid to execute this Transaction. + * Get the SHA384 hash of each potential Transaction protobuf object this Transaction may send. * - * @param fee The desired maximum transaction fee willing to be paid to execute this Transaction. - * @return A reference to this derived Transaction object with the newly-set maximum transaction fee. + * @return The map of node account IDs to the SHA384 hash of their Transaction. + * @throws IllegalStateException If this Transaction is not frozen. */ - SdkRequestType& setMaxTransactionFee(const Hbar& fee); + [[nodiscard]] virtual std::map> getTransactionHashPerNode() const; /** - * Set the memo for this Transaction. + * Require that this Transaction has exactly one node account ID set. * - * @param memo The desired memo for this Transaction. - * @return A reference to this derived Transaction object with the newly-set memo. + * @throws IllegalStateException If there is not exactly one node account ID set. */ - SdkRequestType& setTransactionMemo(const std::string& memo); + void requireOneNodeAccountId() const; /** * Set the ID for this Transaction. * * @param id The desired transaction ID for this Transaction. * @return A reference to this derived Transaction object with the newly-set transaction ID. + * @throws IllegalStateException If this Transaction is frozen. */ SdkRequestType& setTransactionId(const TransactionId& id); + /** + * Derived from Executable. Set the desired account IDs of nodes to which this Transaction will be submitted. This is + * not different from Executable::setNodeAccountIds() other than it checks to make sure the Transaction isn't frozen + * and throws if it is. + * + * @param nodeAccountIds The desired list of account IDs of nodes to submit this Transaction. + * @return A reference to this Executable derived class with the newly-set node account IDs. + * @throws IllegalStateException If this Transaction is frozen. + */ + SdkRequestType& setNodeAccountIds(std::vector nodeAccountIds) override; + + /** + * Set the maximum transaction fee willing to be paid to execute this Transaction. + * + * @param fee The desired maximum transaction fee willing to be paid to execute this Transaction. + * @return A reference to this derived Transaction object with the newly-set maximum transaction fee. + * @throws IllegalStateException If this Transaction is frozen. + */ + SdkRequestType& setMaxTransactionFee(const Hbar& fee); + + /** + * Set the length of time that this Transaction will remain valid. + * + * @param duration The desired length of time to keep this Transaction valid. + * @return A reference to this derived Transaction object with the newly-set valid duration. + * @throws IllegalStateException If this Transaction is frozen. + */ + SdkRequestType& setValidTransactionDuration(const std::chrono::duration& duration); + + /** + * Set the memo for this Transaction. + * + * @param memo The desired memo for this Transaction. + * @return A reference to this derived Transaction object with the newly-set memo. + * @throws IllegalStateException If this Transaction is frozen. + */ + SdkRequestType& setTransactionMemo(const std::string& memo); + /** * Set the transaction ID regeneration policy for this Transaction. * * @param regenerate \c TRUE if it is desired for this Transaction to regenerate a transaction ID upon receiving a * TRANSACTION_EXPIRED response from the network after submission, otherwise \c FALSE. * @return A reference to this derived Transaction object with the newly-set transaction ID regeneration policy. + * @throws IllegalStateException If this Transaction is frozen. */ SdkRequestType& setRegenerateTransactionIdPolicy(bool regenerate); /** - * Get the desired length of time for this Transaction to remain valid upon submission. + * Get the ID of this Transaction. * - * @return The length of time this Transaction will remain valid. + * @return The ID of this Transaction. + * @throws IllegalStateException If no TransactionId has been generated or set yet. */ - [[nodiscard]] inline std::chrono::duration getValidTransactionDuration() const - { - return mTransactionValidDuration; - } + [[nodiscard]] TransactionId getTransactionId() const; /** - * Get the desired maximum transaction fee willing to be paid to execute this Transaction. + * Get the maximum transaction fee willing to be paid to execute this Transaction. * - * @return The desired maximum transaction fee willing to be paid. + * @return The maximum transaction fee willing to be paid. Uninitialized if no maximum transaction fee has been set. */ - [[nodiscard]] inline std::optional getMaxTransactionFee() const { return mMaxTransactionFee; } + [[nodiscard]] std::optional getMaxTransactionFee() const; /** - * Get the memo for this Transaction. + * Get the default maximum transaction fee. This can change between Transactions depending on their cost. * - * @return The memo for this Transaction. + * @return The default maximum transaction fee. */ - [[nodiscard]] inline std::string getTransactionMemo() const { return mTransactionMemo; } + [[nodiscard]] Hbar getDefaultMaxTransactionFee() const; /** - * Get the desired ID for this Transaction. + * Get the desired length of time for this Transaction to remain valid upon submission. * - * @return The desired ID for this Transaction. - * @throws IllegalStateException If no TransactionId has been generated or set yet. + * @return The length of time this Transaction will remain valid. */ - [[nodiscard]] TransactionId getTransactionId() const; + [[nodiscard]] std::chrono::duration getValidTransactionDuration() const; + + /** + * Get the memo for this Transaction. + * + * @return The memo for this Transaction. + */ + [[nodiscard]] std::string getTransactionMemo() const; /** * Get the desired transaction ID regeneration policy of this Transaction. * * @return \c TRUE if this Transaction should regenerate its transaction ID upon receipt of a TRANSACTION_EXPIRED - * response from the network, otherwise \c FALSE. + * response from the network, \c FALSE if this Transaction shouldn't regenerate its transaction ID, and + * uninitialized if this Transaction will follow the default behavior. */ - [[nodiscard]] inline std::optional getRegenerateTransactionIdPolicy() const - { - return mTransactionIdRegenerationPolicy; - } + [[nodiscard]] std::optional getRegenerateTransactionIdPolicy() const; protected: - /** - * Prevent public copying and moving to prevent slicing. Use the 'clone()' virtual method instead. - */ - Transaction() = default; - Transaction(const Transaction&) = default; - Transaction& operator=(const Transaction&) = default; - Transaction(Transaction&&) noexcept = default; - Transaction& operator=(Transaction&&) noexcept = default; + Transaction(); + ~Transaction(); + Transaction(const Transaction&); + Transaction& operator=(const Transaction&); + Transaction(Transaction&&) noexcept; + Transaction& operator=(Transaction&&) noexcept; /** * Construct from a TransactionBody protobuf object. * - * @param transactionBody The TransactionBody protobuf object from which to construct. + * @param txBody The TransactionBody protobuf object from which to construct. */ - explicit Transaction(const proto::TransactionBody& transactionBody); + explicit Transaction(const proto::TransactionBody& txBody); /** - * Derived from Executable. Perform any needed actions for this Transaction when a Node has been selected to which to - * submit this Transaction. + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * Assuming the input map isn't empty, this Transaction will set its values based on the values in the first + * TransactionId -> [AccountId, proto::Transaction] mapping and ignore the rest. * - * @param node The Node to which this Executable is being submitted. + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. */ - void onSelectNode(const std::shared_ptr& node) override; + explicit Transaction(const std::map>& transactions); /** - * Sign a TransactionBody protobuf object with a Client and put the signed bytes into a Transaction protobuf object. + * Derived from Executable. Construct a Transaction protobuf object from this Transaction, based on the node account + * ID at the given index. * - * @param transaction The TransactionBody to sign. - * @param client The Client being used to sign the transaction. - * @return A Transaction protobuf object containing the TransactionBody protobuf object signed by the Client. - * @throws UninitializedException If the input client has no operator with which to sign this Transaction. + * @param index The index of the node account ID that's associated with the Node being used to execute this + * Transaction. + * @return A Transaction protobuf object filled with this Transaction's data, based on the node account ID at the + * given index. + */ + [[nodiscard]] proto::Transaction makeRequest(unsigned int index) const override; + + /** + * Build all Transaction protobuf objects for this Transaction, each going to a different previously-selected node. */ - [[nodiscard]] proto::Transaction signTransaction(const proto::TransactionBody& transaction, - const Client& client) const; + void buildAllTransactions() const; /** - * Create a TransactionBody protobuf object from this Transaction object's data. + * Update mSourceTransactionBody. This will update all fields of mSourceTransactionBody except the transaction ID and + * the node account ID. * * @param client A pointer to the Client that will sign and submit this Transaction. - * @return The created TransactionBody protobuf object. */ - [[nodiscard]] proto::TransactionBody generateTransactionBody(const Client* client) const; + void updateSourceTransactionBody(const Client* client) const; + + /** + * Generate the SignedTransaction protobuf objects for this Transaction. + * + * @param client A pointer to the Client to use to generate the SignedTransaction protobuf objects. + */ + virtual void generateSignedTransactions(const Client* client); + + /** + * Add a Transaction or SignedTransaction protobuf object to this Transaction's Transaction or SignedTransaction + * protobuf object list, respectively. If a Transaction protobuf object is being added, it will also parse a + * SignedTransaction protobuf object from the Transaction protobuf object and add that SignedTransaction protobuf + * object to this Transaction's SignedTransaction protobuf object list. + * + * @param transaction The Transaction or SignedTransaction protobuf object to add to this Transaction. + */ + void addTransaction(const proto::Transaction& transaction); + void addTransaction(const proto::SignedTransaction& transaction); + + /** + * Add a SignedTransaction protobuf object created from the input TransactionBody protobuf object for each node + * account ID of this Transaction. It is expected that every field in the input TransactionBody protobuf object is + * valid except the node account ID field, which will be filled by the function. + * + * @param transaction The TransactionBody protobuf object from which to construct the SignedTransaction protobuf + * objects. + */ + void addSignedTransactionForEachNode(proto::TransactionBody& transactionBody); + + /** + * Clear the SignedTransaction and Transaction protobuf objects held by this Transaction. + */ + virtual void clearTransactions(); /** * Check and make sure this Transaction isn't frozen. @@ -270,6 +394,51 @@ class Transaction */ void requireNotFrozen() const; + /** + * Is this Transaction frozen? + * + * @return \c TRUE if this Transaction is frozen, otherwise \c FALSE. + */ + [[nodiscard]] bool isFrozen() const; + + /** + * Set the default maximum transaction fee for this Transaction. + * + * @param fee The default maximum transaction fee for this Transaction. + */ + void setDefaultMaxTransactionFee(const Hbar& fee); + + /** + * Get the signatures of the Transaction protobuf object at the specified offset. + * + * @param offset The offset at which to grab the signatures. + * @return The map of node account IDs to their PublicKeys and signatures for the specified offset. + */ + [[nodiscard]] std::map, std::vector>> getSignaturesInternal( + size_t offset = 0ULL) const; + + /** + * Get the Transaction protobuf object located at the given index in the Transaction protobuf object list. + * + * @param index The index at which to get the Transaction protobuf object. + * @return The Transaction protobuf object located at the given index. + */ + [[nodiscard]] proto::Transaction getTransactionProtobufObject(unsigned int index) const; + + /** + * Get the source TransactionBody protobuf object from which this Transaction constructed itself. + * + * @return The source TransactionBody protobuf object from which this Transaction constructed itself. + */ + [[nodiscard]] proto::TransactionBody getSourceTransactionBody() const; + + /** + * Get the ID of this Transaction. + * + * @return The ID of this Transaction. + */ + [[nodiscard]] virtual TransactionId getCurrentTransactionId() const; + private: /** * Build and add the derived Transaction's protobuf representation to the Transaction protobuf object. @@ -320,60 +489,26 @@ class Transaction void onExecute(const Client& client) override; /** - * Helper function used to get the proper maximum transaction fee to pack into a protobuf TransactionBody. The order - * of priority for maximum transaction fees goes: - * 1. Manually-set maximum transaction fee for this Transaction. - * 2. Client-set default max transaction fee. - * 3. Default maximum transaction fee. + * Build a Transaction protobuf object from the SignedTransaction protobuf object at the specified index. * - * @param client A pointer to the Client submitting this Transaction. - * @return The proper maximum transaction fee to set for this Transaction. - */ - [[nodiscard]] Hbar getMaxTransactionFee(const Client* client) const; - - /** - * Container of PublicKey and signer function pairs to use to sign this Transaction. - */ - std::vector< - std::pair, std::function(const std::vector&)>>> - mSignatures; - - /** - * Is this Transaction frozen? \c TRUE if yes, otherwise \c FALSE. - */ - bool mIsFrozen = false; - - /** - * The length of time this Transaction will remain valid. - */ - std::chrono::duration mTransactionValidDuration = std::chrono::minutes(2); - - /** - * The account ID of the Node sending this Transaction. - */ - AccountId mNodeAccountId; - - /** - * The maximum transaction fee willing to be paid to execute this Transaction. + * @param index The index in the Transaction's SignedTransaction list from which the Transaction protobuf object + * should be built. */ - std::optional mMaxTransactionFee; + void buildTransaction(unsigned int index) const; /** - * The memo to be associated with this Transaction. - */ - std::string mTransactionMemo; - - /** - * The ID of this Transaction. + * Determine if a PublicKey has already signed this Transaction. + * + * @param publicKey The PublicKey that could have already signed this Transaction. + * @return \c TRUE if the input PublicKey has already signed this Transaction, otherwise \c FALSE. */ - TransactionId mTransactionId; + [[nodiscard]] bool keyAlreadySigned(const std::shared_ptr& publicKey) const; /** - * Should this Transaction regenerate its TransactionId upon a TRANSACTION_EXPIRED response from the network? If not - * set, this Transaction will use the Client's set transaction ID regeneration policy. If that's not set, the default - * behavior is to regenerate the transaction ID. + * Implementation object used to hide implementation details and internal headers. */ - std::optional mTransactionIdRegenerationPolicy; + struct TransactionImpl; + std::unique_ptr mImpl; }; } // namespace Hedera diff --git a/sdk/main/include/TransactionId.h b/sdk/main/include/TransactionId.h index 53360983d..07932e736 100644 --- a/sdk/main/include/TransactionId.h +++ b/sdk/main/include/TransactionId.h @@ -85,7 +85,15 @@ class TransactionId * @param other The other TransactionId with which to compare this TransactionId. * @return \c TRUE if this TransactionId is the same as the input TransactionId, otherwise \c FALSE. */ - bool operator==(const TransactionId&) const; + bool operator==(const TransactionId& other) const; + + /** + * Compare this TransactionId to another TransactionId and determine if they represent different Transactions. + * + * @param other The other TransactionId with which to compare this TransactionId. + * @return \c TRUE if this TransactionId is different from the input TransactionId, otherwise \c FALSE. + */ + bool operator!=(const TransactionId& other) const; /** * Construct a TransactionID protobuf object from this TransactionId object. @@ -146,6 +154,18 @@ struct hash size_t operator()(const Hedera::TransactionId& id) const { return hash()(id.toString()); } }; +template<> +struct less +{ + /** + * Operator override to enable use of TransactionId in a std::map, which requires fair ordering. + */ + bool operator()(const Hedera::TransactionId& lhs, const Hedera::TransactionId& rhs) const + { + return lhs.toString() < rhs.toString(); + } +}; + } // namespace std #endif // HEDERA_SDK_CPP_TRANSACTION_ID_H_ diff --git a/sdk/main/include/TransactionReceiptQuery.h b/sdk/main/include/TransactionReceiptQuery.h index 9ea663fec..91295ac14 100644 --- a/sdk/main/include/TransactionReceiptQuery.h +++ b/sdk/main/include/TransactionReceiptQuery.h @@ -93,16 +93,6 @@ class TransactionReceiptQuery : public Query& /*node*/) const override; - /** * Derived from Executable. Construct a TransactionReceipt object from a Response protobuf object. * @@ -112,13 +102,20 @@ class TransactionReceiptQuery : public Query& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const override; /** * Derived from Executable. Determine the ExecutionStatus of this TransactionReceiptQuery after being submitted. @@ -134,21 +131,30 @@ class TransactionReceiptQuery : public Query& node, - proto::Response* response) const override; + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; + + /** + * Derived from Query. Does this TransactionReceiptQuery require payment? + * + * @return \c FALSE, TransactionReceiptQuery is free. + */ + [[nodiscard]] inline bool isPaymentRequired() const override { return false; } + /** * The ID of the transaction of which this query should get the receipt. */ diff --git a/sdk/main/include/TransactionRecordQuery.h b/sdk/main/include/TransactionRecordQuery.h index b5e18496d..d53a67bd1 100644 --- a/sdk/main/include/TransactionRecordQuery.h +++ b/sdk/main/include/TransactionRecordQuery.h @@ -60,32 +60,29 @@ class TransactionRecordQuery : public Query getTransactionId() const { return mTransactionId; } private: - /** - * Derived from Executable. Construct a Query protobuf object from this TransactionRecordQuery object. - * - * @param client The Client trying to construct this TransactionRecordQuery. - * @param node The Node to which this TransactionRecordQuery will be sent. - * @return A Query protobuf object filled with this TransactionRecordQuery object's data. - */ - [[nodiscard]] proto::Query makeRequest(const Client& client, - const std::shared_ptr& node) const override; - /** * Derived from Executable. Construct a TransactionRecord object from a Response protobuf object. * * @param response The Response protobuf object from which to construct a TransactionRecord object. - * @return An TransactionRecord object filled with the Response protobuf object's data + * @return A TransactionRecord object filled with the Response protobuf object's data */ [[nodiscard]] TransactionRecord mapResponse(const proto::Response& response) const override; /** - * Derived from Executable. Get the status response code for a submitted TransactionRecordQuery from a Response - * protobuf object. + * Derived from Executable. Submit a Query protobuf object which contains this TransactionRecordQuery's data to a + * Node. * - * @param response The Response protobuf object from which to grab the TransactionRecordQuery status response code. - * @return The TransactionRecordQuery status response code of the input Response protobuf object. + * @param request The Query protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. + * @return The gRPC status of the submission. */ - [[nodiscard]] Status mapResponseStatus(const proto::Response& response) const override; + [[nodiscard]] grpc::Status submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const override; /** * Derived from Executable. Determine the ExecutionStatus of this TransactionRecordQuery after being submitted. @@ -100,21 +97,22 @@ class TransactionRecordQuery : public Query& node, - proto::Response* response) const override; + [[nodiscard]] proto::ResponseHeader mapResponseHeader(const proto::Response& response) const override; /** * The ID of the transaction of which this query should get the record. diff --git a/sdk/main/include/TransactionResponse.h b/sdk/main/include/TransactionResponse.h index b7eecd212..1be79850f 100644 --- a/sdk/main/include/TransactionResponse.h +++ b/sdk/main/include/TransactionResponse.h @@ -70,7 +70,7 @@ class TransactionResponse * TransactionResponse is configured to throw. * @throws UninitializedException If the input Client has not yet been initialized. */ - [[nodiscard]] TransactionReceipt getReceipt(const Client& client) const; + TransactionReceipt getReceipt(const Client& client) const; /** * Get a TransactionReceipt for the Transaction to which this TransactionResponse is responding. @@ -85,7 +85,7 @@ class TransactionResponse * TransactionResponse is configured to throw. * @throws UninitializedException If the input Client has not yet been initialized. */ - [[nodiscard]] TransactionReceipt getReceipt(const Client& client, const std::chrono::duration& timeout) const; + TransactionReceipt getReceipt(const Client& client, const std::chrono::duration& timeout) const; /** * Get a TransactionRecord for the Transaction to which this TransactionResponse is responding. @@ -145,10 +145,12 @@ class TransactionResponse private: /** - * Allow Transactions to adjust this TransactionResponse's mTransactionId. + * Allow Transactions and ChunkedTransactions to adjust this TransactionResponse's mTransactionId. */ - template - friend class Transaction; + // clang-format off + template friend class Transaction; + template friend class ChunkedTransaction; + // clang-format on /** * The cost to execute this TransactionResponse's corresponding Transaction. diff --git a/sdk/main/include/TransferTransaction.h b/sdk/main/include/TransferTransaction.h index ae9cf795c..9b7374519 100644 --- a/sdk/main/include/TransferTransaction.h +++ b/sdk/main/include/TransferTransaction.h @@ -20,15 +20,11 @@ #ifndef HEDERA_SDK_CPP_TRANSFER_TRANSACTION_H_ #define HEDERA_SDK_CPP_TRANSFER_TRANSACTION_H_ -#include "AccountId.h" #include "HbarTransfer.h" -#include "NftId.h" -#include "TokenId.h" #include "TokenNftTransfer.h" #include "TokenTransfer.h" #include "Transaction.h" -#include #include #include @@ -37,6 +33,13 @@ namespace proto class CryptoTransferTransactionBody; } +namespace Hedera +{ +class AccountId; +class NftId; +class TokenId; +} + namespace Hedera { /** @@ -62,6 +65,14 @@ class TransferTransaction : public Transaction */ explicit TransferTransaction(const proto::TransactionBody& transactionBody); + /** + * Construct from a map of TransactionIds to node account IDs and their respective Transaction protobuf objects. + * + * @param transactions The map of TransactionIds to node account IDs and their respective Transaction protobuf + * objects. + */ + explicit TransferTransaction(const std::map>& transactions); + /** * Add an Hbar transfer to be submitted as part of this TransferTransaction. * @@ -194,49 +205,26 @@ class TransferTransaction : public Transaction private: /** - * Allow queries that are not free to create Transaction protobuf objects from TransferTransactions. + * Allow Queries to create Transaction protobuf objects from TransferTransactions (to use as payments). */ - friend class AccountInfoQuery; - friend class AccountRecordsQuery; - friend class AccountStakersQuery; - friend class ContractByteCodeQuery; - friend class ContractCallQuery; - friend class ContractInfoQuery; - friend class FileContentsQuery; - friend class FileInfoQuery; - friend class NetworkVersionInfoQuery; - friend class ScheduleInfoQuery; - friend class TokenInfoQuery; - friend class TokenNftInfoQuery; - friend class TopicInfoQuery; - friend class TransactionRecordQuery; - + template + friend class Query; friend class WrappedTransaction; /** - * Derived from Executable. Construct a Transaction protobuf object from this TransferTransaction object. + * Derived from Executable. Submit a Transaction protobuf object which contains this TransferTransaction's data to a + * Node. * - * @param client The Client trying to construct this TransferTransaction. - * @param node The Node to which this TransferTransaction will be sent. This is unused. - * @return A Transaction protobuf object filled with this TransferTransaction object's data. - * @throws UninitializedException If the input client has no operator with which to sign this TransferTransaction. - */ - [[nodiscard]] proto::Transaction makeRequest(const Client& client, - const std::shared_ptr& /*node*/) const override; - - /** - * Derived from Executable. Submit this TransferTransaction to a Node. - * - * @param client The Client submitting this TransferTransaction. - * @param deadline The deadline for submitting this TransferTransaction. - * @param node Pointer to the Node to which this TransferTransaction should be submitted. - * @param response Pointer to the TransactionResponse protobuf object that gRPC should populate with the response - * information from the gRPC server. + * @param request The Transaction protobuf object to submit. + * @param node The Node to which to submit the request. + * @param deadline The deadline for submitting the request. + * @param response Pointer to the ProtoResponseType object that gRPC should populate with the response information + * from the gRPC server. * @return The gRPC status of the submission. */ - [[nodiscard]] grpc::Status submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, + [[nodiscard]] grpc::Status submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const override; /** * Derived from Transaction. Build and add the TransferTransaction protobuf representation to the Transaction @@ -246,6 +234,11 @@ class TransferTransaction : public Transaction */ void addToBody(proto::TransactionBody& body) const override; + /** + * Initialize this TransferTransaction from its source TransactionBody protobuf object. + */ + void initFromSourceTransactionBody(); + /** * Build a CryptoTransferTransactionBody protobuf object from this TransferTransaction object. * diff --git a/sdk/main/include/exceptions/MaxQueryPaymentExceededException.h b/sdk/main/include/exceptions/MaxQueryPaymentExceededException.h new file mode 100644 index 000000000..8d8ae1cda --- /dev/null +++ b/sdk/main/include/exceptions/MaxQueryPaymentExceededException.h @@ -0,0 +1,60 @@ +/*- + * + * 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. + * + */ +#ifndef HEDERA_SDK_CPP_MAX_QUERY_PAYMENT_EXCEEDED_EXCEPTION_H_ +#define HEDERA_SDK_CPP_MAX_QUERY_PAYMENT_EXCEEDED_EXCEPTION_H_ + +#include +#include + +namespace Hedera +{ +/** + * Exception that is thrown when the cost to execute a Query is larger than the maximum allowed amount. + */ +class MaxQueryPaymentExceededException : public std::exception +{ +public: + /** + * Construct with a message. + * + * @param msg The error message to further describe this exception. + */ + explicit MaxQueryPaymentExceededException(std::string_view msg) + : mError(msg) + { + } + + /** + * Get the descriptor message for this error. + * + * @return The descriptor message for this error. + */ + [[nodiscard]] const char* what() const noexcept override { return mError.data(); }; + +private: + /** + * Descriptive error message. + */ + std::string_view mError; +}; + +} // namespace Hedera + +#endif // HEDERA_SDK_CPP_MAX_QUERY_PAYMENT_EXCEEDED_EXCEPTION_H_ diff --git a/sdk/main/include/impl/BaseNetwork.h b/sdk/main/include/impl/BaseNetwork.h new file mode 100644 index 000000000..da92fb041 --- /dev/null +++ b/sdk/main/include/impl/BaseNetwork.h @@ -0,0 +1,324 @@ +/*- + * + * 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. + * + */ +#ifndef HEDERA_SDK_CPP_IMPL_BASE_NETWORK_H_ +#define HEDERA_SDK_CPP_IMPL_BASE_NETWORK_H_ + +#include "BaseNode.h" +#include "Defaults.h" +#include "LedgerId.h" +#include "TLSBehavior.h" + +#include +#include +#include +#include +#include +#include + +namespace Hedera::internal +{ +template +class BaseNetwork +{ +public: + /** + * Set the NodeTypes in this BaseNetwork. It shutdowns and removes any NodeType from this BaseNetwork if the input + * network doesn't contain its representation. It will then add any new NodeTypes that don't already exist in this + * BaseNetwork. + * + * @param network The map of addresses to their keys that represent NodeTypes to add to this BaseNetwork. + * @return A reference to this derived BaseNetwork object with the newly-set NodeTypes. + */ + NetworkType& setNetwork(const std::unordered_map& network); + + /** + * Increase the backoff of the input NodeType. + * + * @param node The NodeType of which to increase the backoff. + */ + void increaseBackoff(const std::shared_ptr& node); + + /** + * Decrease the backoff of the input NodeType. + * + * @param node The NodeType of which to decrease the backoff. + */ + void decreaseBackoff(const std::shared_ptr& node) const; + + /** + * Get the list of all proxies at a specified key. + * + * @return The list of all proxies at a specified key. + */ + [[nodiscard]] std::vector> getNodeProxies(const KeyType& key); + + /** + * Close the connects on this BaseNetwork. + */ + void close() const; + + /** + * Set the maximum number of times to try to use a NodeType to submit a request. Once the NodeType exceeds this number + * of submission attempts that have returned a bad gRPC status, that NodeType will be permanently removed from this + * BaseNetwork. + * + * @param attempts The maximum number of times a NodeType can be retried. + * @return A reference to this derived BaseNetwork object with the newly-set maximum node attempts. + */ + NetworkType& setMaxNodeAttempts(unsigned int attempts); + + /** + * Set the minimum amount of time to backoff from a NodeType after a bad gRPC status is received. + * + * @param backoff The minimum backoff time to use for a NodeType after a bad gRPC status is received. + * @return A reference to this derived BaseNetwork object with the newly-set minimum backoff. + */ + NetworkType& setMinNodeBackoff(const std::chrono::duration& backoff); + + /** + * Set the maximum amount of time to backoff from a NodeType after a bad gRPC status is received. + * + * @param backoff The maximum backoff time to use for a NodeType after a bad gRPC status is received. + * @return A reference to this derived BaseNetwork object with the newly-set maximum backoff. + */ + NetworkType& setMaxNodeBackoff(const std::chrono::duration& backoff); + + /** + * Set the minimum amount of time to wait before readmitting NodeTypes as "healthy". + * + * @param time The minimum amount of time to wait before readmitting NodeTypes as "healthy". + * @return A reference to this derived BaseNetwork object with the newly-set minimum node readmit time. + */ + NetworkType& setMinNodeReadmitTime(const std::chrono::duration& time); + + /** + * Set the maximum amount of time to wait before readmitting NodeTypes as "healthy". + * + * @param time The maximum amount of time to wait before readmitting NodeTypes as "healthy". + * @return A reference to this derived BaseNetwork object with the newly-set maximum node readmit time. + */ + NetworkType& setMaxNodeReadmitTime(const std::chrono::duration& time); + + /** + * Set the amount of time to allow gRPC connections on this BaseNetwork to close gracefully before forcibly + * terminating them. + * + * @param timeout The amount of time to allow gRPC connections on this BaseNetwork to close gracefully. + * @return A reference to this derived BaseNetwork object with the newly-set close timeout. + */ + NetworkType& setCloseTimeout(const std::chrono::duration& timeout); + + /** + * Set the ledger ID of this BaseNetwork. + * + * @param ledgerId The ledger ID to set. + * @return A reference to this derived BaseNetwork object with the newly-set ledger ID. + */ + virtual NetworkType& setLedgerId(const LedgerId& ledgerId); + + /** + * Get the transport security policy of this BaseNetwork. + * + * @return The transport security policy of this BaseNetwork. + */ + [[nodiscard]] inline TLSBehavior isTransportSecurity() const { return mTransportSecurity; } + + /** + * Get the maximum number of times to try to use a NodeType before removing it from this BaseNetwork. + * + * @return The maximum number of times to try to use a NodeType before removing it from this BaseNetwork. + */ + [[nodiscard]] inline unsigned int getMaxNodeAttempts() const { return mMaxNodeAttempts; } + + /** + * Get the minimum amount of time to backoff from a NodeType after a bad gRPC status is received. + * + * @return The minimum amount of time to backoff from a NodeType after a bad gRPC status is received. + */ + [[nodiscard]] inline std::chrono::duration getMinNodeBackoff() const { return mMinNodeBackoff; } + + /** + * Get the maximum amount of time to backoff from a NodeType after a bad gRPC status is received. + * + * @return The maximum amount of time to backoff from a NodeType after a bad gRPC status is received. + */ + [[nodiscard]] inline std::chrono::duration getMaxNodeBackoff() const { return mMaxNodeBackoff; } + + /** + * Get the minimum amount of time to wait before readmitting NodeTypes as "healthy". + * + * @return The minimum amount of time to wait before readmitting NodeTypes as "healthy". + */ + [[nodiscard]] inline std::chrono::duration getMinNodeReadmitTime() const { return mMinNodeReadmitTime; } + + /** + * Get the maximum amount of time to wait before readmitting NodeTypes as "healthy". + * + * @return The maximum amount of time to wait before readmitting NodeTypes as "healthy". + */ + [[nodiscard]] inline std::chrono::duration getMaxNodeReadmitTime() const { return mMaxNodeReadmitTime; } + + /** + * Get the amount of time to allow gRPC connections on this BaseNetwork to close gracefully before forcibly + * terminating them. + * + * @return The amount of time to allow gRPC connections on this BaseNetwork to close gracefully before forcibly + * terminating them. + */ + [[nodiscard]] inline std::chrono::duration getCloseTimeout() const { return mCloseTimeout; } + + /** + * Get the ledger ID of this Network. + * + * @return The ledger ID of this Network. + */ + [[nodiscard]] inline LedgerId getLedgerId() const { return mLedgerId; } + +protected: + ~BaseNetwork() = default; + + /** + * Get a number of the most healthy nodes on this BaseNetwork. "Healthy"-ness is determined by sort order; the lower + * index nodes in the returned vector are considered the most healthy. + * + * This will also remove any nodes which have hit or exceeded mMaxNodeAttempts permanently from the BaseNetwork. + * + * @param count The number of nodes to get. + * @return A list of pointers to the healthiest BaseNodes on this BaseNetwork. + */ + [[nodiscard]] std::vector> getNumberOfMostHealthyNodes(unsigned int count); + + /** + * Set the transport security policy. + * + * @param tls The transport security policy to set. + */ + void setTransportSecurityInternal(TLSBehavior tls); + + /** + * Get the map of KeyTypes to their NodeTypes on this BaseNetwork. + * + * @return The map of KeyTypes to their NodeTypes on this BaseNetwork. + */ + [[nodiscard]] inline const std::unordered_map>>& + getNetworkInternal() const + { + return mNetwork; + } + + /** + * Get the list of NodeTypes on this BaseNetwork. + * + * @return The list of NodeTypes on this BaseNetwork. + */ + [[nodiscard]] inline const std::unordered_set>& getNodes() const { return mNodes; } + +private: + /** + * Create a NodeType for this BaseNetwork based on a network entry. + * + * @param address The address of the NodeType. + * @param key The key for the NodeType. + * @return A pointer to the created NodeType. + */ + [[nodiscard]] virtual std::shared_ptr createNodeFromNetworkEntry( + std::string_view address, + [[maybe_unused]] const KeyType& key) const = 0; + + /** + * Readmit nodes from the mNodes list to the mHealthyNodes list when the time has passed the mEarliestReadmitTime. + * While readmitting nodes, mEarliestReadmitTime will be updated to a new value. This value is either the value of + * the node with the smallest readmission time from now, or mMinNodeReadmitTime or mMaxNodeReadmitTime. + */ + void readmitNodes(); + + /** + * Remove a BaseNode from this BaseNetwork. + * + * @param node A pointer to the BaseNode to remove. + */ + void removeNodeFromNetwork(const std::shared_ptr& node); + + /** + * Map of node identifiers (KeyTypes) to their NodeTypes. + */ + std::unordered_map>> mNetwork; + + /** + * The list of all nodes on this BaseNetwork. + */ + std::unordered_set> mNodes; + + /** + * The list of current healthy nodes on this BaseNetwork. + */ + std::unordered_set> mHealthyNodes; + + /** + * The transport security policy of this BaseNetwork. + */ + TLSBehavior mTransportSecurity = TLSBehavior::REQUIRE; + + /** + * The maximum number of times to try to use a NodeType to submit a request. Once the NodeType exceeds this number of + * submission attempts that have returned a bad gRPC status, that NodeType will be permanently removed from this + * BaseNetwork. + */ + unsigned int mMaxNodeAttempts = DEFAULT_MAX_NODE_ATTEMPTS; + + /** + * The minimum amount of time to wait to use a NodeType after it has received a bad gRPC status. + */ + std::chrono::duration mMinNodeBackoff = DEFAULT_MIN_NODE_BACKOFF; + + /** + * The maximum amount of time to wait to use a NodeType after it has received a bad gRPC status. + */ + std::chrono::duration mMaxNodeBackoff = DEFAULT_MAX_NODE_BACKOFF; + + /** + * The minimum time to wait before attempting to readmit nodes. + */ + std::chrono::duration mMinNodeReadmitTime = DEFAULT_MIN_NODE_BACKOFF; + + /** + * The maximum time to wait before attempting to readmit nodes. + */ + std::chrono::duration mMaxNodeReadmitTime = DEFAULT_MAX_NODE_BACKOFF; + + /** + * The earliest time that a node should be readmitted. + */ + std::chrono::system_clock::time_point mEarliestReadmitTime = std::chrono::system_clock::now(); + + /** + * The timeout for closing either a single node when setting a new network, or closing the entire network. + */ + std::chrono::duration mCloseTimeout = DEFAULT_CLOSE_TIMEOUT; + + /** + * The ledger ID of the network. + */ + LedgerId mLedgerId; +}; + +} // namespace Hedera::internal + +#endif // HEDERA_SDK_CPP_IMPL_BASE_NETWORK_H_ diff --git a/sdk/main/include/impl/BaseNode.h b/sdk/main/include/impl/BaseNode.h new file mode 100644 index 000000000..2aa86f1f3 --- /dev/null +++ b/sdk/main/include/impl/BaseNode.h @@ -0,0 +1,241 @@ +/*- + * + * 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. + * + */ +#ifndef HEDERA_SDK_CPP_IMPL_BASE_NODE_H_ +#define HEDERA_SDK_CPP_IMPL_BASE_NODE_H_ + +#include // This is needed for Windows to build for some reason. + +#include "BaseNodeAddress.h" +#include "Defaults.h" + +#include +#include +#include + +namespace Hedera::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::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::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 minimum backoff. + */ + NodeType& setMaxNodeBackoff(const std::chrono::duration& backoff); + + /** + * Get this BaseNode's BaseNodeAddress. + * + * @return address The BaseNodeAddress of this BaseNode. + */ + [[nodiscard]] inline BaseNodeAddress getAddress() const { 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::duration getMinNodeBackoff() const { 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::duration getMaxNodeBackoff() const { 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 { 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 { return mReadmitTime; } + +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 a gRPC channel. + * + * @param channel The gRPC channel with which to initialize the stubs. + */ + virtual void initializeStubs([[maybe_unused]] const std::shared_ptr& channel) + { // 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"; } + + /** + * 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::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::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::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; +}; + +} // namespace Hedera::internal + +#endif // HEDERA_SDK_CPP_IMPL_BASE_NODE_H_ diff --git a/sdk/main/include/impl/BaseNodeAddress.h b/sdk/main/include/impl/BaseNodeAddress.h new file mode 100644 index 000000000..0e77d0a8b --- /dev/null +++ b/sdk/main/include/impl/BaseNodeAddress.h @@ -0,0 +1,159 @@ +/*- + * + * 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. + * + */ +#ifndef HEDERA_SDK_CPP_IMPL_BASE_NODE_ADDRESS_H_ +#define HEDERA_SDK_CPP_IMPL_BASE_NODE_ADDRESS_H_ + +#include +#include + +namespace Hedera::internal +{ +class BaseNodeAddress +{ +public: + /** + * Port numbers for various node types and security. + */ + static constexpr unsigned int PORT_MIRROR_PLAIN = 5600U; + static constexpr unsigned int PORT_MIRROR_TLS = 443U; + static constexpr unsigned int PORT_NODE_PLAIN = 50211U; + static constexpr unsigned int PORT_NODE_TLS = 50212U; + + /** + * Construct with values for name, address, and port. + * + * @param name The name with which to construct. + * @param address The address with which to construct. + * @param port The port with which to construct. + */ + explicit BaseNodeAddress(std::string_view name, std::string_view address, unsigned int port); + + /** + * Construct a BaseNodeAddress from an address string that contains the IP and port. + * + * @param address The address of the BaseNodeAddress. + * @return The constructed BaseNodeAddress. + * @throws std::invalid_argument If the provided address is malformed. + */ + [[nodiscard]] static BaseNodeAddress fromString(std::string_view address); + + /** + * Compare this BaseNodeAddress to another BaseNodeAddress and determine if they represent the same node address. + * + * @param other The other BaseNodeAddress with which to compare this BaseNodeAddress. + * @return \c TRUE if this BaseNodeAddress is the same as the input BaseNodeAddress, otherwise \c FALSE. + */ + bool operator==(const BaseNodeAddress& other) const; + + /** + * Create a copy of this BaseNodeAddress but using TLS. + * + * @return The copy of this BoseNodeAddress using TLS. + */ + [[nodiscard]] BaseNodeAddress toSecure() const; + + /** + * Create a copy of this BaseNodeAddress but not using TLS. + * + * @return The copy of this BoseNodeAddress not using TLS. + */ + [[nodiscard]] BaseNodeAddress toInsecure() const; + + /** + * Get the string representation of this BaseNodeAddress. + * + * @return The string representation of this BaseNodeAddress. + */ + [[nodiscard]] std::string toString() const; + + /** + * Is this BaseNodeAddress in process? + * + * @return \c TRUE if this BaseNodeAddress is in process, otherwise \c FALSE. + */ + [[nodiscard]] inline bool isInProcess() const { return !mName.empty(); } + + /** + * Is this BaseNodeAddress using transport security? + * + * @param \c TRUE if this BaseNodeAddress is using TLS, otherwise \c FALSE. + */ + [[nodiscard]] inline bool isTransportSecurity() const + { + return (mPort == PORT_NODE_TLS) || (mPort == PORT_MIRROR_TLS); + } + + /** + * Get the name of this BaseNodeAddress. + * + * @return The name of this BaseNodeAddress. + */ + [[nodiscard]] inline std::string getName() const { return mName; } + + /** + * Get the IP address of this BaseNodeAddress. + * + * @return The IP address of this BaseNodeAddress. + */ + [[nodiscard]] inline std::string getAddress() const { return mAddress; } + + /** + * Get the port of this BaseNodeAddress. + * + * @return The port of this BaseNodeAddress. + */ + [[nodiscard]] inline unsigned int getPort() const { return mPort; } + +private: + /** + * The name of the address. This is used for "in-process" addresses. + */ + std::string mName; + + /** + * The IP address. + */ + std::string mAddress; + + /** + * The port. + */ + unsigned int mPort = 0U; +}; + +} // namespace Hedera::internal + +namespace std +{ +template<> +struct hash +{ + /** + * Operator override to enable use of BaseNodeAddress as map key. + */ + size_t operator()(const Hedera::internal::BaseNodeAddress& address) const + { + return hash()(address.toString()); + } +}; + +} // namespace std + +#endif // HEDERA_SDK_CPP_IMPL_BASE_NODE_ADDRESS_H_ diff --git a/sdk/main/include/impl/Endpoint.h b/sdk/main/include/impl/Endpoint.h index 6bd651de4..8df2ac5b0 100644 --- a/sdk/main/include/impl/Endpoint.h +++ b/sdk/main/include/impl/Endpoint.h @@ -22,6 +22,9 @@ #include "IPv4Address.h" +#include +#include + namespace proto { class ServiceEndpoint; @@ -36,41 +39,56 @@ class Endpoint { public: /** - * Construct from an address and a port number. + * Construct an Endpoint object from a ServiceEndpoint protobuf object. * - * @param ipAddressV4 The IPv4 address of the endpoint. - * @param port The port of the endpoint. + * @param proto The ServiceEndpoint protobuf object from which to construct an Endpoint object. + * @return The constructed Endpoint object. */ - Endpoint(const IPv4Address& ipAddressV4, int port); + [[nodiscard]] static Endpoint fromProtobuf(const proto::ServiceEndpoint& protoServiceEndpoint); /** - * Create an Endpoint object from a ServiceEndpoint protobuf object. + * Construct a ServiceEndpoint protobuf object from this Endpoint object. * - * @param protoServiceEndpoint The ServiceEndpoint protobuf object from which to create an Endpoint object. - * @return The created Endpoint object. + * @return A pointer to the created ServiceEndpoint protobuf object filled with this Endpoint object's data. */ - static Endpoint fromProtobuf(const proto::ServiceEndpoint& protoServiceEndpoint); + [[nodiscard]] std::unique_ptr toProtobuf() const; /** - * Get a string representation of the endpoint with the form :. + * Get a string representation of this Endpoint. * - * @return A string representation of the Endpoint. + * @return A string representation of this Endpoint. */ [[nodiscard]] std::string toString() const; /** - * Get the IP address of the node. + * Set the IP address of this Endpoint. + * + * @param address The IP address to set. + * @return A reference to this Endpoint with the newly-set IP address. + */ + Endpoint& setAddress(const IPv4Address& address); + + /** + * Set the port of this Endpoint. + * + * @param port The port to set. + * @return A reference to this Endpoint with the newly-set port. + */ + Endpoint& setPort(unsigned int port); + + /** + * Get the IP address of this Endpoint. * - * @return The IP address (v4) of the node. + * @return The IP address of this Endpoint. */ [[nodiscard]] inline IPv4Address getAddress() const { return mAddress; } /** - * Get the port of the Endpoint. + * Get the port of this Endpoint. * - * @return The port of the Endpoint. + * @return The port of this Endpoint. */ - [[nodiscard]] inline int getPort() const { return mPort; } + [[nodiscard]] inline unsigned int getPort() const { return mPort; } private: /** @@ -81,7 +99,7 @@ class Endpoint /** * The port of the Endpoint. */ - int mPort; + unsigned int mPort = 0U; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/IPv4Address.h b/sdk/main/include/impl/IPv4Address.h index 770e0b861..f74e0b2f8 100644 --- a/sdk/main/include/impl/IPv4Address.h +++ b/sdk/main/include/impl/IPv4Address.h @@ -20,65 +20,47 @@ #ifndef HEDERA_SDK_CPP_IMPL_IPV4_ADDRESS_H_ #define HEDERA_SDK_CPP_IMPL_IPV4_ADDRESS_H_ +#include +#include #include -#include +#include namespace Hedera::internal { /** - * An IPv4 address (without port) + * An IPv4 address (without port). */ class IPv4Address { public: - IPv4Address() = default; - /** - * Constructor with four octets. + * Construct an IPv4Address object from a byte array. * - * @param octet1 The first octet. - * @param octet2 The second octet. - * @param octet3 The third octet. - * @param octet4 The fourth octet. + * @param bytes The byte array from which to construct an IPv4Address. + * @return The constructed IPv4Address object. + * @throws std::invalid_argument If an IPv4Address could not be realized from the input bytes. */ - IPv4Address(std::byte octet1, std::byte octet2, std::byte octet3, std::byte octet4); + [[nodiscard]] static IPv4Address fromBytes(const std::vector& bytes); /** - * Creates a new IP address from a string. Supports ascii or byte representation. + * Get the byte array representation of this IPv4Address. * - * @param address The IP address from which to construct, in string form. - * @return The new IP address. - * @throws std::invalid_argument If the input IPv4Address string is malformed. + * @return The byte array representation of this IPv4Address. */ - [[nodiscard]] static IPv4Address fromString(std::string_view address); + [[nodiscard]] std::vector toBytes() const; /** - * Get the string representation of this IPv4Address (form is ...). + * Get the string representation of this IPv4Address. * - * @return The string represenation of this IPv4Address. + * @return The string representation of this IPv4Address. */ [[nodiscard]] std::string toString() const; private: /** - * The first octet of the address - */ - std::byte mOctet1; - - /** - * The second octet of the address - */ - std::byte mOctet2; - - /** - * The third octet of the address - */ - std::byte mOctet3; - - /** - * The fourth octet of the address + * The four octets of the address. */ - std::byte mOctet4; + std::array mAddress; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/MirrorNetwork.h b/sdk/main/include/impl/MirrorNetwork.h index b8cda446e..0acb8a3c7 100644 --- a/sdk/main/include/impl/MirrorNetwork.h +++ b/sdk/main/include/impl/MirrorNetwork.h @@ -20,6 +20,9 @@ #ifndef HEDERA_SDK_CPP_IMPL_MIRROR_NETWORK_H_ #define HEDERA_SDK_CPP_IMPL_MIRROR_NETWORK_H_ +#include "BaseNetwork.h" +#include "BaseNodeAddress.h" + #include #include #include @@ -32,7 +35,7 @@ class MirrorNode; namespace Hedera::internal { -class MirrorNetwork +class MirrorNetwork : public BaseNetwork { public: /** @@ -65,32 +68,38 @@ class MirrorNetwork [[nodiscard]] static MirrorNetwork forNetwork(const std::vector& networkMap); /** - * Get a pointer to the next MirrorNode. + * Set the MirrorNodes in the MirrorNetwork. This will put the input addresses into a map of addresses to + * BaseNodeAddresses, and then feed it to BaseNetwork::setNetwork. * - * @return A pointer to the next MirrorNode. + * @param network The network to set for this MirrorNetwork. + * @return A reference to this MirrorNetwork object with the newly-set network. */ - [[nodiscard]] std::shared_ptr getNextMirrorNode() const; + MirrorNetwork& setNetwork(const std::vector& network); /** - * Initiate an orderly shutdown of communications with the MirrorNodes that are a part of this MirrorNetwork. + * Get the addresses of the MirrorNodes in this MirrorNetwork. * - * After this method returns, this MirrorNetwork can be re-used. All network communication can be re-established as - * needed. + * @return The addresses of the MirrorNodes in this MirrorNetwork. */ - void close() const; + [[nodiscard]] std::vector getNetwork() const; -private: /** - * Establish communications with all MirrorNodes for this MirrorNetwork that are specified in the input address list. + * Get a pointer to the next MirrorNode. * - * @param addresses The addresses of the MirrorNodes with which this MirrorNetwork will be communicating. + * @return A pointer to the next MirrorNode. */ - void setNetwork(const std::vector& addresses); + [[nodiscard]] std::shared_ptr getNextMirrorNode() const; +private: /** - * The list of pointers to MirrorNodes with which this MirrorNetwork is communicating. + * Derived from BaseNetwork. Create a MirrorNode for this MirrorNetwork based on a network entry. + * + * @param address The address of the MirrorNode. + * @param key The key for the MirrorNode. This is unused. + * @return A pointer to the created MirrorNode. */ - std::vector> mNodes; + [[nodiscard]] std::shared_ptr createNodeFromNetworkEntry(std::string_view address, + const BaseNodeAddress& /*key*/) const override; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/MirrorNode.h b/sdk/main/include/impl/MirrorNode.h index 559d17006..49adb97ae 100644 --- a/sdk/main/include/impl/MirrorNode.h +++ b/sdk/main/include/impl/MirrorNode.h @@ -22,174 +22,79 @@ #include -#include "Defaults.h" -#include "impl/NodeAddress.h" -#include "impl/TLSBehavior.h" +#include "BaseNode.h" -#include -#include -#include #include -#include #include -#include -namespace grpc -{ -class ClientContext; -class Status; -} - -namespace proto +namespace Hedera::internal { -class Query; -class Response; -class Transaction; -class TransactionResponse; +class BaseNodeAddress; } namespace Hedera::internal { /** - * Internal utility class used to represent a node on a Hedera network. + * Internal utility class used to represent a mirror node on a Hedera network. */ -class MirrorNode +class MirrorNode : public BaseNode { public: /** - * Construct this MirrorNode from a string which contains the IP and port with which to connect. - * - * @param address The address to which to connect. - */ - explicit MirrorNode(std::string_view address); - - /** - * Attempt to connect this MirrorNode to the remote mirror node. + * Construct with the address of the MirrorNode. * - * @param timeout The point in time that the attempted connection will cease and be considered a failure. - * @return \c TRUE if the Node is already connected or successfully connected, otherwise \c FALSE. - */ - bool connect(const std::chrono::system_clock::time_point& timeout); - - /** - * Shutdown the connection from this MirrorNode to the remote mirror node. + * @param address The address of the MirrorNode. */ - void shutdown(); + explicit MirrorNode(const BaseNodeAddress& address); /** - * Set the minimum amount of time this Node should wait before being willing to resubmit a previously failed request - * to its remote node. + * Construct with the address of the MirrorNode as a string. * - * @param backoff The minimum backoff time. - */ - void setMinBackoff(const std::chrono::duration& backoff); - - /** - * Set the maximum amount of time this Node should wait before being willing to resubmit a previously failed request - * to its remote node. - * - * @param backoff The maximum backoff time. - */ - void setMaxBackoff(const std::chrono::duration& backoff); - - /** - * Determine if this Node is "healthy", meaning this Node has received a gRPC status responses from its remote node - * that indicates a successful request attempt, or if it has fully backed off for its full period of backoff time - * after an unsuccessful submission attempt. - * - * @return \c TRUE if this Node is "healthy", otherwise \c FALSE. - */ - [[nodiscard]] bool isHealthy() const; - - /** - * Increase the backoff of this Node. This should be called when this Node either fails to connect to its remote node - * or it receives a gRPC status from its remote node that indicates a failed submission attempt. + * @param address The address of the MirrorNode as a string. */ - void increaseBackoff(); - - /** - * Decrease the backoff of this Node. This should be called when this Node successfully submits a request to its - * remote node. - */ - void decreaseBackoff(); + explicit MirrorNode(std::string_view address); /** - * Get the amount of time remaining in this Node's current backoff. + * Derived from BaseNode. Get this MirrorNode's key, which is its BaseNodeAddress. * - * @return The amount of time that should pass before this Node is good to try and submit another request. + * @return This MirrorNode's key, which is its BaseNodeAddress. */ - [[nodiscard]] std::chrono::duration getRemainingTimeForBackoff() const; + [[nodiscard]] inline BaseNodeAddress getKey() const override { return getAddress(); } /** - * Get the consensus service stub. + * Get a pointer to the ConsensusService stub used by this MirrorNode. * - * @return The consensus service stub. + * @return A pointer ot the ConsensusService stub used by this MirrorNode. */ - [[nodiscard]] inline std::shared_ptr - getConsensusServiceStub() const + [[nodiscard]] std::shared_ptr getConsensusServiceStub() const { return mConsensusStub; } private: /** - * Initialize the gRPC channel used to communicate with this Node's remote node based on mTLSBehavior. + * Derived from BaseNode. Get the authority of this MirrorNode. * - * @param deadline The deadline to connect. Processing will continue trying until this point to establish a connection - * and will return \c FALSE if not established by then. - * @return \c TRUE if initialization was successful, otherwise \c FALSE. - */ - bool initializeChannel(const std::chrono::system_clock::time_point& deadline); - - /** - * The address of the MirrorNode. + * @return There is no MirrorNode authority, so returns an empty string; */ - std::string mAddress; + [[nodiscard]] inline std::string getAuthority() const override { return {}; } /** - * Pointer to this Node's TLS channel credentials. This only depends on the NodeAddress so this will be updated - * whenever mAddress is. + * Derived from BaseNode. Initialize the stubs in this MirrorNode with a gRPC channel. + * + * @param channel The gRPC channel with which to initialize the stubs. */ - std::shared_ptr mTlsChannelCredentials = nullptr; + void initializeStubs(const std::shared_ptr& channel) override; /** - * Pointer to the gRPC channel used to communicate with the gRPC server living on the remote node. + * Derived from BaseNode. Close the stubs in this MirrorNode. */ - std::shared_ptr mChannel = nullptr; + void closeStubs() override; /** * Pointer to the gRPC stub used to communicate with the consensus service living on the remote mirror node. */ std::shared_ptr mConsensusStub = nullptr; - - /** - * The point in time that this Node would be considered healthy again. - */ - std::chrono::system_clock::time_point mReadmitTime = std::chrono::system_clock::now(); - - /** - * The minimum length of time this Node should wait before being willing to attempt to send a failed request to its - * remote node again. - */ - std::chrono::duration mMinBackoff = DEFAULT_MIN_BACKOFF; - - /** - * The maximum length of time this Node should wait before being willing to attempt to send a failed request to its - * remote node again. - */ - std::chrono::duration mMaxBackoff = DEFAULT_MAX_BACKOFF; - - /** - * The current backoff time. Every failed submission attempt waits a certain amount of time that is double the - * previous amount of time a request waited for its previous submission attempt, up to the specified maximum backoff - * time, at which point the execution is considered a failure. - */ - std::chrono::duration mCurrentBackoff = mMinBackoff; - - /** - * Is the gRPC channel being utilized by this Node to communicate with its remote node initialized? - */ - bool mIsInitialized = false; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/Network.h b/sdk/main/include/impl/Network.h index 8d59f6c88..235d87c30 100644 --- a/sdk/main/include/impl/Network.h +++ b/sdk/main/include/impl/Network.h @@ -20,7 +20,7 @@ #ifndef HEDERA_SDK_CPP_IMPL_NETWORK_H_ #define HEDERA_SDK_CPP_IMPL_NETWORK_H_ -#include "AccountId.h" +#include "BaseNetwork.h" #include "Node.h" #include "NodeAddressBook.h" #include "TLSBehavior.h" @@ -37,7 +37,7 @@ class AccountId; namespace Hedera::internal { -class Network +class Network : public BaseNetwork { public: /** @@ -62,65 +62,115 @@ class Network [[nodiscard]] static Network forPreviewnet(); /** - * Construct a Network that is pre-configured for local node access. + * Construct a custom Network. * - * @param networkMap The map with string representation of node addresses with their corresponding accountId. - * @return A Network object that is set-up to communicate with a specific node addresses. + * @param network The map with string representation of node addresses with their corresponding AccountIds. + * @return A Network object that is set-up to communicate with the custom network. */ - [[nodiscard]] static Network forNetwork(const std::unordered_map& networkMap); + [[nodiscard]] static Network forNetwork(const std::unordered_map& network); /** - * Get a list of Node pointers that point to Nodes on this Network that are associated with the input account IDs. If - * no account IDs are specified, pointers to all Nodes on this Network are returned. + * Derived from BaseNetwork. Set the ledger ID of this Network. * - * @param accountIds The IDs of the accounts that are associated with the desired Nodes. - * @return A list of Node pointers that point to Nodes with the requested account IDs. + * @param ledgerId The ledger ID to set. + * @return A reference to this Network object with the newly-set ledger ID. */ - [[nodiscard]] std::vector> getNodesWithAccountIds( - const std::vector& accountIds) const; + Network& setLedgerId(const LedgerId& ledgerId) override; /** - * Initiate an orderly shutdown of communications with the Nodes that are a part of this Network. Preexisting - * transactions or queries continue but subsequent calls would be immediately cancelled. + * Set this Network's certificate verification policy. * - * After this method returns, this Network can be re-used. All network communication can be re-established as needed. + * @param verify \c TRUE if this Network should verify remote node certificates, otherwise \c FALSE. + * @return A reference to this Network object with the newly-set certificate verification policy. */ - void close() const; + Network& setVerifyCertificates(bool verify); /** - * Set the TLS behavior of all Nodes on this Network. + * Set this Network's transport security policy. * - * @param desiredBehavior The desired behavior. + * @param tls The transport security policy to set. + * @return A reference to this Network object with the newly-set transport security policy. * @throws UninitializedException If TLS is required and a Node on this Network wasn't initialized with a certificate * hash. */ - void setTLSBehavior(TLSBehavior desiredBehavior) const; + Network& setTransportSecurity(TLSBehavior tls); + + /** + * Set the maximum number of nodes to be returned for each request. + * + * @param max The maximum number of nodes to be returned for each request. + * @return A reference to this Network object with the newly-set maximum nodes per request. + */ + Network& setMaxNodesPerRequest(unsigned int max); + + /** + * Get a list of node account IDs on which to execute. This will pick 1/3 of the available nodes sorted by health and + * expected delay from the network. + * + * @return A list of AccountIds that are running nodes on which should be executed. + */ + [[nodiscard]] std::vector getNodeAccountIdsForExecute(); + + /** + * Get a map of this Network, mapping the Node addresses to their AccountIds. + * + * @return A map of this Network, mapping the Node addresses to their AccountIds. + */ + [[nodiscard]] std::unordered_map getNetwork() const; private: /** - * Establish communications with all Nodes for this Network that are specified in the input address book. + * Construct with a network map. * - * @param nodeAddressBook The address book that contains the Nodes with which this Network will be communicating. - * @param tls The TLS behavior all nodes should initially use. Default value is REQUIRE. - * @throws UninitializedException If a NodeAddress in the input NodeAddressBook wasn't initialized with a certificate - * hash. + * @param network A map of node addresses to the AccountIds that run those nodes. + */ + explicit Network(const std::unordered_map& network); + + /** + * Construct a Network object configured to communicate with the network represented by the input LedgerId. + * + * @param ledgerId The LedgerId of the Network object to construct. + * @return The constructed Network object. + */ + [[nodiscard]] static Network getNetworkForLedgerId(const LedgerId& ledgerId); + + /** + * Get a map of AccountIds to NodeAddresses from a local file for a network based on the input LedgerId. + * + * @param ledgerId The LedgerId of the network of which to get the address book. + * @return The map of node addresses and AccountIds of the Nodes that exist on the network represented by the input + * LedgerId. */ - void setNetwork(const NodeAddressBook& nodeAddressBook, TLSBehavior tls = TLSBehavior::REQUIRE); + [[nodiscard]] static std::unordered_map getAddressBookForLedgerId(const LedgerId& ledgerId); /** - * Establish communications with all node addresses for this Network that are specified in the input map collection. + * Derived from BaseNetwork. Create a Node for this Network based on a network entry. * - * @param networkMap The map containing string node addresses pointing to specific accountId object. - * @param tls The TLS behavior all nodes should initially use. Default value is DISABLE. - * @throws UninitializedException If a NodeAddress in the input NodeAddressBook wasn't initialized with a certificate - * hash. + * @param address The address of the Node. + * @param key The key for the Node. + * @return A pointer to the created Node. + */ + [[nodiscard]] std::shared_ptr createNodeFromNetworkEntry(std::string_view address, + const AccountId& key) const override; + + /** + * Set the ledger ID of this Network. In addition, update the Nodes on this Network with their address book entry + * contained in the input map. + * + * @param ledgerId The new LedgerId of the Network. + * @param addressBook The address book with which to update this Network's Node's address book entry. + */ + Network& setLedgerIdInternal(const LedgerId& ledgerId, const std::unordered_map& addressBook); + + /** + * The maximum number of nodes to be returned for each request. */ - void setNetwork(const std::unordered_map& networkMap, TLSBehavior tls = TLSBehavior::DISABLE); + unsigned int mMaxNodesPerRequest = 0U; /** - * The list of pointers to Nodes with which this Network is communicating. + * Should the Nodes on this Network verify remote node certificates? */ - std::vector> mNodes; + bool mVerifyCertificates = true; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/Node.h b/sdk/main/include/impl/Node.h index 316a908ee..0880664a2 100644 --- a/sdk/main/include/impl/Node.h +++ b/sdk/main/include/impl/Node.h @@ -29,46 +29,42 @@ #include #include -#include "Defaults.h" -#include "impl/NodeAddress.h" -#include "impl/TLSBehavior.h" +#include "AccountId.h" +#include "BaseNode.h" -#include -#include -#include +#include #include -#include -#include +#include +#include + +namespace Hedera::internal +{ +class BaseNodeAddress; +} namespace Hedera::internal { /** * Internal utility class used to represent a node on a Hedera network. */ -class Node +class Node : public BaseNode { public: /** - * Construct this Node with the NodeAddress of the remote node it is meant to represent. + * Construct with the AccountId that's running this Node and the address of the Node. * - * @param address A pointer to the desired NodeAddress for this Node. - * @param tls The TLS behavior this Node should initially use. - * @throws UninitializedException If TLS is required and the input NodeAddress doesn't contain a certificate hash. + * @param accountId The AccountId that runs the remote node represented by this Node. + * @param address The address of the Node. */ - explicit Node(std::shared_ptr address, TLSBehavior tls = TLSBehavior::REQUIRE); + explicit Node(AccountId accountId, const BaseNodeAddress& address); /** - * Attempt to connect this Node to the remote node. + * Construct with the AccountId that's running this Node and the address of the Node as a string. * - * @param timeout The point in time that the attempted connection will cease and be considered a failure. - * @return \c TRUE if the Node is already connected or successfully connected, otherwise \c FALSE. - */ - bool connect(const std::chrono::system_clock::time_point& timeout); - - /** - * Shutdown the connection from this Node to the remote node. + * @param accountId The AccountId that runs the remote node represented by this Node. + * @param address The address of the Node as a string. */ - void shutdown(); + explicit Node(const AccountId& accountId, std::string_view address); /** * Submit a Query protobuf to the remote node with which this Node is communicating. @@ -99,89 +95,90 @@ class Node proto::TransactionResponse* response); /** - * Set the TLS behavior this Node should utilize when communicating with its remote node. + * Construct an insecure version of this Node. This will close the Node's current connection. * - * @param desiredBehavior The desired behavior. - * @throws UninitializedException If TLS is required and this Node's NodeAddress doesn't contain a certificate hash. + * @return A reference to this Node, now using an insecure connection. */ - void setTLSBehavior(TLSBehavior desiredBehavior); + Node& toInsecure(); /** - * Set the minimum amount of time this Node should wait before being willing to resubmit a previously failed request - * to its remote node. + * Construct a secure version of this Node. This will close the Node's current connection. * - * @param backoff The minimum backoff time. + * @return A reference to this Node, now using a secure connection. */ - void setMinBackoff(const std::chrono::duration& backoff); + Node& toSecure(); /** - * Set the maximum amount of time this Node should wait before being willing to resubmit a previously failed request - * to its remote node. + * Set the node certificate hash of this Node. * - * @param backoff The maximum backoff time. + * @param hash The node certificate hash to set. + * @return A reference to this Node with the newly-set node certificate hash. */ - void setMaxBackoff(const std::chrono::duration& backoff); + Node& setNodeCertificateHash(const std::vector& hash); /** - * Determine if this Node is "healthy", meaning this Node has received a gRPC status responses from its remote node - * that indicates a successful request attempt, or if it has fully backed off for its full period of backoff time - * after an unsuccessful submission attempt. + * Set the certificate verification policy of this Node. * - * @return \c TRUE if this Node is "healthy", otherwise \c FALSE. + * @param verify \c TRUE if this Node should verify certificates, otherwise \c FALSE. + * @return A reference to this Node with the newly-set certificate verification policy. */ - [[nodiscard]] bool isHealthy() const; + Node& setVerifyCertificates(bool verify); /** - * Increase the backoff of this Node. This should be called when this Node either fails to connect to its remote node - * or it receives a gRPC status from its remote node that indicates a failed submission attempt. + * Derived from BaseNode. Get this Node's key, which is its AccountId. + * + * @return This Node's key, which is its AccountId. */ - void increaseBackoff(); + [[nodiscard]] inline AccountId getKey() const override { return getAccountId(); }; /** - * Decrease the backoff of this Node. This should be called when this Node successfully submits a request to its - * remote node. + * Get the AccountId of this Node. + * + * @return The AccountId of this Node. */ - void decreaseBackoff(); + [[nodiscard]] inline AccountId getAccountId() const { return mAccountId; }; /** - * Get the amount of time remaining in this Node's current backoff. + * Get the node certificate hash of this Node. * - * @return The amount of time that should pass before this Node is good to try and submit another request. + * @return The node certificate hash of this Node. */ - [[nodiscard]] std::chrono::duration getRemainingTimeForBackoff() const; + [[nodiscard]] inline std::vector getNodeCertificateHash() const { return mNodeCertificateHash; } /** - * Get the ID of the account associated with this Node. + * Get the certificate verification policy of this Node. * - * @return The ID of the account associated with this Node. + * @return \c TRUE if this Node is currently configured to verify certificates, otherwise \c FALSE. */ - [[nodiscard]] inline AccountId getAccountId() const { return mAddress->getNodeAccountId(); } + [[nodiscard]] inline bool getVerifyCertificates() const { return mVerifyCertificates; } private: /** - * Initialize the gRPC channel used to communicate with this Node's remote node based on mTLSBehavior. + * Construct from another Node and a BaseNodeAddress. * - * @param deadline The deadline to connect. Processing will continue trying until this point to establish a connection - * and will return \c FALSE if not established by then. - * @return \c TRUE if initialization was successful, otherwise \c FALSE. + * @param node The Node from which to construct. + * @param address The address of the Node. */ - bool initializeChannel(const std::chrono::system_clock::time_point& deadline); + explicit Node(const Node& node, const BaseNodeAddress& address); /** - * Pointer to the NodeAddress of this Node. + * Derived from BaseNode. Get the TLS credentials of this Node's gRPC channel. + * + * @return A pointer to the TLS credentials for this Node's gRPC channel. */ - std::shared_ptr mAddress = nullptr; + [[nodiscard]] std::shared_ptr getTlsChannelCredentials() const override; /** - * Pointer to this Node's TLS channel credentials. This only depends on the NodeAddress so this will be updated - * whenever mAddress is. + * Derived from BaseNode. Initialize the stubs in this Node with a gRPC channel. + * + * @param channel The gRPC channel with which to initialize the stubs. */ - std::shared_ptr mTlsChannelCredentials = nullptr; + void initializeStubs(const std::shared_ptr& channel) override; /** - * Pointer to the gRPC channel used to communicate with the gRPC server living on the remote node. + * Derived from BaseNode. Close the stubs in this Node. */ - std::shared_ptr mChannel = nullptr; + void closeStubs() override; /** * Pointer to the gRPC stub used to communicate with the consensus service living on the remote node. @@ -224,38 +221,19 @@ class Node std::unique_ptr mTokenStub = nullptr; /** - * The TLS behavior this Node should use to communicate with its remote node. - */ - TLSBehavior mTLSBehavior = TLSBehavior::REQUIRE; - - /** - * The point in time that this Node would be considered healthy again. - */ - std::chrono::system_clock::time_point mReadmitTime = std::chrono::system_clock::now(); - - /** - * The minimum length of time this Node should wait before being willing to attempt to send a failed request to its - * remote node again. - */ - std::chrono::duration mMinBackoff = DEFAULT_MIN_BACKOFF; - - /** - * The maximum length of time this Node should wait before being willing to attempt to send a failed request to its - * remote node again. + * The AccountId that runs the remote node represented by this Node. */ - std::chrono::duration mMaxBackoff = DEFAULT_MAX_BACKOFF; + AccountId mAccountId; /** - * The current backoff time. Every failed submission attempt waits a certain amount of time that is double the - * previous amount of time a request waited for its previous submission attempt, up to the specified maximum backoff - * time, at which point the execution is considered a failure. + * The node certificate hash of this Node. */ - std::chrono::duration mCurrentBackoff = mMinBackoff; + std::vector mNodeCertificateHash; /** - * Is the gRPC channel being utilized by this Node to communicate with its remote node initialized? + * Should this Node verify the certificates coming from the remote node? */ - bool mIsInitialized = false; + bool mVerifyCertificates = false; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/NodeAddress.h b/sdk/main/include/impl/NodeAddress.h index 0fd5ab71c..f19717a79 100644 --- a/sdk/main/include/impl/NodeAddress.h +++ b/sdk/main/include/impl/NodeAddress.h @@ -23,7 +23,9 @@ #include "AccountId.h" #include "impl/Endpoint.h" +#include #include +#include #include namespace proto @@ -39,127 +41,78 @@ namespace Hedera::internal class NodeAddress { public: - NodeAddress() = default; - /** - * Construct a NodeAddress instance with a given IPv4 address and port. + * Construct a NodeAddress object from a NodeAddress protobuf object. * - * @param ipAddressV4 The stringified IPv4 address. - * @param port The port number of the server for the node. - * @throws std::invalid_argument If the given IP address is malformed. + * @param proto The NodeAddress protobuf object from which to construct a NodeAddress object. + * @return The constructed NodeAddress object. */ - NodeAddress(std::string_view ipAddressV4, int port); - - /** - * Determine if a particular port number corresponds to a TLS port. - * - * @param port The port number. - * @return \c TRUE if the input port number corresponds to a TLS port, otherwise \c FALSE. - */ - static inline bool isTlsPort(int port) { return (port == PORT_NODE_TLS) || (port == PORT_MIRROR_TLS); } - - /** - * Determine if a particular port number corresponds to a non-TLS port. - * - * @param port The port number. - * @return \c TRUE if the input port number corresponds to a non-TLS port, otherwise \c FALSE. - */ - static inline bool isNonTlsPort(int port) { return (port == PORT_NODE_PLAIN) || (port == PORT_MIRROR_PLAIN); } + [[nodiscard]] static NodeAddress fromProtobuf(const proto::NodeAddress& protoNodeAddress); /** - * Create a NodeAddress object from a NodeAddress protobuf object. + * Construct a NodeAddress protobuf object from this NodeAddress object. * - * @param protoNodeAddress The NodeAddress protobuf object from which to create a NodeAddress object. - * @return The created NodeAddress object. + * @return A pointer to the created NodeAddress protobuf object filled with this NodeAddress object's data. */ - [[nodiscard]] static NodeAddress fromProtobuf(const proto::NodeAddress& protoNodeAddress); + [[nodiscard]] std::unique_ptr toProtobuf() const; /** - * Create a NodeAddress object from a given string. + * Get a string representation of this NodeAddress. * - * @param nodeAddress The string representation from which to create a new NodeAddress object. - * @return The created NodeAddress object. - * @throws std::invalid_argument If the given node address is malformed. + * @return A string representing this NodeAddress. */ - [[nodiscard]] static NodeAddress fromString(std::string_view nodeAddress); + [[nodiscard]] std::string toString() const; /** - * Set a new public key for the node. + * Set the public key of this NodeAddress. This should be a hex-encoded string of the public key's DER encoding. * - * @param publicKey The public key to be assigned to the node. + * @param publicKey The hex-encoded and DER-encoded public key to set. * @return A reference to this NodeAddress with the newly-set public key. */ - NodeAddress& setRSAPublicKey(std::string_view publicKey); + NodeAddress& setPublicKey(std::string_view publicKey); /** - * Set a new node ID for the node at this address. + * Set the node ID of this NodeAddress. * - * @param nodeId The ID of the node to set. + * @param nodeId The node ID to set. * @return A reference to this NodeAddress with the newly-set node ID. */ NodeAddress& setNodeId(const int64_t& nodeId); /** - * Set a new account ID associated with the node at this address. + * Set the account ID of this NodeAddress. * - * @param accountId The account ID to be associated with the node. + * @param accountId The account ID to set. * @return A reference to this NodeAddress with the newly-set account ID. */ - NodeAddress& setNodeAccountId(const AccountId& accountId); + NodeAddress& setAccountId(const AccountId& accountId); /** - * Set a new certificate hash for the node. + * Set the certificate hash of this NodeAddress. This should be hex-encoded SHA384 hash of the UTF-8 NFKD encoding of + * the remote node's TLS cert in PEM format. * - * @param certHash The certificate hash to be assigned to the node. + * @param certHash The certificate hash to set. * @return A reference to this NodeAddress with the newly-set certificate hash. */ - NodeAddress& setNodeCertHash(std::string_view certHash); + NodeAddress& setCertHash(std::string_view certHash); + NodeAddress& setCertHash(std::vector certHash); /** - * Set a vector of endpoints for the node. + * Set the list of endpoints of this NodeAddress. * - * @param endpoints The endpoints to be assigned to the node. + * @param endpoints The list of endpoints to set. * @return A reference to this NodeAddress with the newly-set endpoints. */ - NodeAddress& setEndpoints(const std::vector>& endpoints); + NodeAddress& setEndpoints(const std::vector& endpoints); /** - * Set а new description text for the node. + * Set the description text of this NodeAddress. * - * @param description The description text to be assigned with the node. + * @param description The description text to set. * @return A reference to this NodeAddress with the newly-set description. */ NodeAddress& setDescription(std::string_view description); - /** - * Set a new amount of tinybars staked to the node. - * - * @param stake The new amount of tinybars staked to the node. - * @return A reference to this NodeAddress with the newly-set staked tinybars. - */ - NodeAddress& setStake(const uint64_t& stake); - - /** - * Get a string representation of the NodeAddress. - * - * @return A string representing this NodeAddress. - */ - [[nodiscard]] std::string toString() const; - - /** - * Get the default IP address of this NodeAddress. - * - * @return The default IP address of this NodeAddress. - */ - [[nodiscard]] inline IPv4Address getDefaultIpAddress() const { return getDefaultEndpoint()->getAddress(); } - - /** - * Get the default port number of the gRPC server of this NodeAddress. - * - * @return The default port of this NodeAddress. - */ - [[nodiscard]] inline int getDefaultPort() const { return getDefaultEndpoint()->getPort(); } - /** * Get the node ID of this NodeAddress. * @@ -170,45 +123,30 @@ class NodeAddress /** * Get the public key of this NodeAddress. * - * @return The hash value representing the public key of the node. + * @return The public key of this NodeAddress. */ [[nodiscard]] inline std::string getPublicKey() const { return mRSAPublicKey; } /** - * Get the account ID associated with this NodeAddress. + * Get the account ID of this NodeAddress. * - * @return The account ID associated with this NodeAddress. + * @return The account ID of this NodeAddress. */ - [[nodiscard]] inline AccountId getNodeAccountId() const { return mNodeAccountId; } + [[nodiscard]] inline AccountId getAccountId() const { return mNodeAccountId; } /** - * Get the SHA-384 hash of this NodeAddress's certificate chain. + * Get the node certificate hash of this NodeAddress. * - * @return The SHA-384 hash of this NodeAddress's certificate chain. + * @return The node certificate hash of this NodeAddress. */ - [[nodiscard]] inline std::vector getNodeCertHash() const { return mNodeCertHash; } + [[nodiscard]] inline std::vector getCertHash() const { return mNodeCertHash; } /** - * Get the default Endpoint of this NodeAddress. + * Get the list of endpoints of this NodeAddress. * - * @return The default Endpoint of this NodeAddress. + * @return The list of endpoints of this NodeAddress. */ - [[nodiscard]] inline std::shared_ptr getDefaultEndpoint() const - { - if (mEndpoints.empty()) - { - return nullptr; - } - - return mEndpoints.front(); - } - - /** - * Get the Endpoints associated with this NodeAddress. - * - * @return The Endpoints associated with this NodeAddress. - */ - [[nodiscard]] inline const std::vector>& getEndpoints() const { return mEndpoints; } + [[nodiscard]] inline const std::vector& getEndpoints() const { return mEndpoints; } /** * Get the description text of this NodeAddress. @@ -217,27 +155,7 @@ class NodeAddress */ [[nodiscard]] inline std::string getDescription() const { return mDescription; } - /** - * Get the amount of tinybars staked to the Node at this NodeAddress. - * - * @return The amount of tinybars staked to the Node at this NodeAddress. - */ - [[nodiscard]] inline uint64_t getStake() const { return mStake; } - private: - /** - * Port numbers for various node types and security. - */ - static constexpr int PORT_MIRROR_PLAIN = 5600; - static constexpr int PORT_MIRROR_TLS = 443; - static constexpr int PORT_NODE_PLAIN = 50211; - static constexpr int PORT_NODE_TLS = 50212; - - /** - * The Endpoints associated with the node. - */ - std::vector> mEndpoints; - /** * The node's public key. */ @@ -259,14 +177,14 @@ class NodeAddress std::vector mNodeCertHash; /** - * A string description of the node. + * The Endpoints associated with the node. */ - std::string mDescription; + std::vector mEndpoints; /** - * The amount of tinybars staked to the node. + * A string description of the node. */ - uint64_t mStake = 0; + std::string mDescription; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/NodeAddressBook.h b/sdk/main/include/impl/NodeAddressBook.h index f3ff9107d..4aacabe23 100644 --- a/sdk/main/include/impl/NodeAddressBook.h +++ b/sdk/main/include/impl/NodeAddressBook.h @@ -20,17 +20,14 @@ #ifndef HEDERA_SDK_CPP_IMPL_NODE_ADDRESS_BOOK_H_ #define HEDERA_SDK_CPP_IMPL_NODE_ADDRESS_BOOK_H_ -#include "AccountId.h" #include "impl/NodeAddress.h" -#include -#include -#include +#include +#include namespace proto { class NodeAddressBook; -class NodeAddress; } namespace Hedera::internal @@ -42,54 +39,55 @@ class NodeAddressBook { public: /** - * Construct a NodeAddressBook object from a file that contains the serialization of a NodeAddressBook protobuf - * object. + * Construct a NodeAddressBook object from a NodeAddressBook protobuf object. * - * @param fileName The name of the file where the NodeAddressBook protobuf object is encoded. + * @param proto The NodeAddressBook protobuf object from which to construct a NodeAddressBook object. * @return The constructed NodeAddressBook object. */ - [[nodiscard]] static NodeAddressBook fromFile(std::string_view fileName); + [[nodiscard]] static NodeAddressBook fromProtobuf(const proto::NodeAddressBook& proto); /** - * Construct a NodeAddressBook object from the byte serialization of a NodeAddressBook protobuf object. + * Construct a NodeAddressBook object from a byte array. * - * @param bytes The byte serialization of the NodeAddressBook protobuf object to decode. + * @param bytes The byte array from which to construct a NodeAddressBook object. * @return The constructed NodeAddressBook object. */ [[nodiscard]] static NodeAddressBook fromBytes(const std::vector& bytes); /** - * Construct a NodeAddressBook object from a NodeAddressBook protobuf object. + * Construct a NodeAddressBook protobuf object from this NodeAddressBook object. * - * @param protoAddressBook The NodeAddressBook protobuf object from which to create a NodeAddressBook object. - * @return The constructed NodeAddressBook object. + * @return A pointer to the created NodeAddressBook protobuf object filled with this NodeAddressBook object's data. */ - [[nodiscard]] static NodeAddressBook fromProtobuf(const proto::NodeAddressBook& protoAddressBook); + [[nodiscard]] std::unique_ptr toProtobuf() const; /** - * Construct a NodeAddressBook object from an address map. + * Get the byte array representation of this NodeAddressBook. * - * @param addressMap The address map containing accountId to node address relations. - * @return The constructed NodeAddressBook object. + * @return The byte array representation of this NodeAddressBook. + */ + [[nodiscard]] std::vector toBytes() const; + + /** + * Set the list of NodeAddresses in this NodeAddressBook. + * + * @param addresses The list of NodeAddresses to set. + * @return A reference to this NodeAddressBook with the newly-set NodeAddress list. */ - [[nodiscard]] static NodeAddressBook fromAddressMap( - const std::unordered_map>& addressMap); + NodeAddressBook& setNodeAddresses(const std::vector& addresses); /** - * Get a map of AccountIds to NodeAddresses contained in this NodeAddressBook. + * Get the list of NodeAddresses. * - * @return A map of AccountIds to NodeAddresses contained in this NodeAddressBook. + * @return The list of NodeAddresses. */ - [[nodiscard]] inline const std::unordered_map>& getAddressMap() const - { - return mAddressMap; - } + [[nodiscard]] inline std::vector getNodeAddresses() const { return mNodeAddresses; } private: /** - * A map from AccountId's to NodeAddresses. + * The list of NodeAddresses. */ - std::unordered_map> mAddressMap; + std::vector mNodeAddresses; }; } // namespace Hedera::internal diff --git a/sdk/main/include/impl/TLSBehavior.h b/sdk/main/include/impl/TLSBehavior.h index 27a81db98..15e3a62cb 100644 --- a/sdk/main/include/impl/TLSBehavior.h +++ b/sdk/main/include/impl/TLSBehavior.h @@ -20,11 +20,6 @@ #ifndef HEDERA_SDK_CPP_IMPL_TLS_BEHAVIOR_H_ #define HEDERA_SDK_CPP_IMPL_TLS_BEHAVIOR_H_ -#include -#include -#include -#include - namespace Hedera::internal { /** diff --git a/sdk/main/include/impl/Utilities.h b/sdk/main/include/impl/Utilities.h index c69fbc68d..08811a83e 100644 --- a/sdk/main/include/impl/Utilities.h +++ b/sdk/main/include/impl/Utilities.h @@ -150,6 +150,16 @@ template */ [[nodiscard]] std::string byteVectorToString(const std::vector& bytes); +/** + * Get a random number between the two input inclusive bounds. + * + * @param lowerBound The lower bound of the random number. + * @param upperBound The upper bound of the random number. + * @return A random number between the two bounds. + * @throws std::invalid_argument If lowerBound is greater than or equal to upperBound. + */ +[[nodiscard]] unsigned int getRandomNumber(unsigned int lowerBound, unsigned int upperBound); + } // namespace Hedera::internal::Utilities #endif // HEDERA_SDK_CPP_IMPL_UTILITIES_H_ diff --git a/sdk/main/src/AccountAllowanceApproveTransaction.cc b/sdk/main/src/AccountAllowanceApproveTransaction.cc index 16e4232aa..ee404abd8 100644 --- a/sdk/main/src/AccountAllowanceApproveTransaction.cc +++ b/sdk/main/src/AccountAllowanceApproveTransaction.cc @@ -33,27 +33,15 @@ namespace Hedera AccountAllowanceApproveTransaction::AccountAllowanceApproveTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptoapproveallowance()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoApproveAllowance data"); - } - - const proto::CryptoApproveAllowanceTransactionBody& body = transactionBody.cryptoapproveallowance(); - - for (int i = 0; i < body.cryptoallowances_size(); ++i) - { - mHbarAllowances.push_back(HbarAllowance::fromProtobuf(body.cryptoallowances(i))); - } - - for (int i = 0; i < body.tokenallowances_size(); ++i) - { - mTokenAllowances.push_back(TokenAllowance::fromProtobuf(body.tokenallowances(i))); - } + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.nftallowances_size(); ++i) - { - mNftAllowances.push_back(TokenNftAllowance::fromProtobuf(body.nftallowances(i))); - } +//----- +AccountAllowanceApproveTransaction::AccountAllowanceApproveTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -148,20 +136,13 @@ AccountAllowanceApproveTransaction& AccountAllowanceApproveTransaction::deleteNf } //----- -proto::Transaction AccountAllowanceApproveTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status AccountAllowanceApproveTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status AccountAllowanceApproveTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoApproveAllowance, makeRequest(client, node), deadline, response); + proto::TransactionBody::DataCase::kCryptoApproveAllowance, request, deadline, response); } //----- @@ -170,6 +151,34 @@ void AccountAllowanceApproveTransaction::addToBody(proto::TransactionBody& body) body.set_allocated_cryptoapproveallowance(build()); } +//----- +void AccountAllowanceApproveTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptoapproveallowance()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoApproveAllowance data"); + } + + const proto::CryptoApproveAllowanceTransactionBody& body = transactionBody.cryptoapproveallowance(); + + for (int i = 0; i < body.cryptoallowances_size(); ++i) + { + mHbarAllowances.push_back(HbarAllowance::fromProtobuf(body.cryptoallowances(i))); + } + + for (int i = 0; i < body.tokenallowances_size(); ++i) + { + mTokenAllowances.push_back(TokenAllowance::fromProtobuf(body.tokenallowances(i))); + } + + for (int i = 0; i < body.nftallowances_size(); ++i) + { + mNftAllowances.push_back(TokenNftAllowance::fromProtobuf(body.nftallowances(i))); + } +} + //----- proto::CryptoApproveAllowanceTransactionBody* AccountAllowanceApproveTransaction::build() const { diff --git a/sdk/main/src/AccountAllowanceDeleteTransaction.cc b/sdk/main/src/AccountAllowanceDeleteTransaction.cc index 2aad94783..9f5510b1a 100644 --- a/sdk/main/src/AccountAllowanceDeleteTransaction.cc +++ b/sdk/main/src/AccountAllowanceDeleteTransaction.cc @@ -33,28 +33,15 @@ namespace Hedera AccountAllowanceDeleteTransaction::AccountAllowanceDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptodeleteallowance()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoDeleteAllowance data"); - } - - const proto::CryptoDeleteAllowanceTransactionBody& body = transactionBody.cryptodeleteallowance(); - - for (int i = 0; i < body.nftallowances_size(); ++i) - { - std::vector serialNumbers; - serialNumbers.reserve(body.nftallowances(i).serial_numbers_size()); - - for (int j = 0; j < body.nftallowances(i).serial_numbers_size(); ++j) - { - serialNumbers.push_back(static_cast(body.nftallowances(i).serial_numbers(j))); - } + initFromSourceTransactionBody(); +} - mNftAllowanceDeletions.emplace_back(TokenId::fromProtobuf(body.nftallowances(i).token_id()), - AccountId::fromProtobuf(body.nftallowances(i).owner()), - std::optional(), - serialNumbers); - } +//----- +AccountAllowanceDeleteTransaction::AccountAllowanceDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -80,20 +67,12 @@ AccountAllowanceDeleteTransaction& AccountAllowanceDeleteTransaction::deleteAllT } //----- -proto::Transaction AccountAllowanceDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status AccountAllowanceDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status AccountAllowanceDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoDeleteAllowance, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kCryptoDeleteAllowance, request, deadline, response); } //----- @@ -102,6 +81,35 @@ void AccountAllowanceDeleteTransaction::addToBody(proto::TransactionBody& body) body.set_allocated_cryptodeleteallowance(build()); } +//----- +void AccountAllowanceDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptodeleteallowance()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoDeleteAllowance data"); + } + + const proto::CryptoDeleteAllowanceTransactionBody& body = transactionBody.cryptodeleteallowance(); + + for (int i = 0; i < body.nftallowances_size(); ++i) + { + std::vector serialNumbers; + serialNumbers.reserve(body.nftallowances(i).serial_numbers_size()); + + for (int j = 0; j < body.nftallowances(i).serial_numbers_size(); ++j) + { + serialNumbers.push_back(static_cast(body.nftallowances(i).serial_numbers(j))); + } + + mNftAllowanceDeletions.emplace_back(TokenId::fromProtobuf(body.nftallowances(i).token_id()), + AccountId::fromProtobuf(body.nftallowances(i).owner()), + std::optional(), + serialNumbers); + } +} + //----- proto::CryptoDeleteAllowanceTransactionBody* AccountAllowanceDeleteTransaction::build() const { diff --git a/sdk/main/src/AccountBalanceQuery.cc b/sdk/main/src/AccountBalanceQuery.cc index 0c0aff7df..2b3b331aa 100644 --- a/sdk/main/src/AccountBalanceQuery.cc +++ b/sdk/main/src/AccountBalanceQuery.cc @@ -19,7 +19,6 @@ */ #include "AccountBalanceQuery.h" #include "AccountBalance.h" -#include "Status.h" #include "impl/Node.h" #include @@ -48,48 +47,46 @@ AccountBalanceQuery& AccountBalanceQuery::setContractId(const ContractId& contra } //----- -proto::Query AccountBalanceQuery::makeRequest(const Client&, const std::shared_ptr&) const +AccountBalance AccountBalanceQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::CryptoGetAccountBalanceQuery* getAccountBalanceQuery = query.mutable_cryptogetaccountbalance(); + return AccountBalance::fromProtobuf(response.cryptogetaccountbalance()); +} + +//----- +grpc::Status AccountBalanceQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const +{ + return node->submitQuery(proto::Query::QueryCase::kCryptogetAccountBalance, request, deadline, response); +} - proto::QueryHeader* header = getAccountBalanceQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - // This is a free query, so no payment required +//----- +proto::Query AccountBalanceQuery::buildRequest(proto::QueryHeader* header) const +{ + auto accountBalanceQuery = std::make_unique(); + accountBalanceQuery->set_allocated_header(header); if (mAccountId) { - getAccountBalanceQuery->set_allocated_accountid(mAccountId->toProtobuf().release()); + accountBalanceQuery->set_allocated_accountid(mAccountId->toProtobuf().release()); } if (mContractId) { - getAccountBalanceQuery->set_allocated_contractid(mContractId->toProtobuf().release()); + accountBalanceQuery->set_allocated_contractid(mContractId->toProtobuf().release()); } + proto::Query query; + query.set_allocated_cryptogetaccountbalance(accountBalanceQuery.release()); return query; } //----- -AccountBalance AccountBalanceQuery::mapResponse(const proto::Response& response) const -{ - return AccountBalance::fromProtobuf(response.cryptogetaccountbalance()); -} - -//----- -Status AccountBalanceQuery::mapResponseStatus(const proto::Response& response) const -{ - return gProtobufResponseCodeToStatus.at(response.cryptogetaccountbalance().header().nodetransactionprecheckcode()); -} - -//----- -grpc::Status AccountBalanceQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader AccountBalanceQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kCryptogetAccountBalance, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.cryptogetaccountbalance().header()); + return response.cryptogetaccountbalance().header(); } } // namespace Hedera diff --git a/sdk/main/src/AccountCreateTransaction.cc b/sdk/main/src/AccountCreateTransaction.cc index b54ab8301..b830115d0 100644 --- a/sdk/main/src/AccountCreateTransaction.cc +++ b/sdk/main/src/AccountCreateTransaction.cc @@ -35,52 +35,24 @@ namespace Hedera AccountCreateTransaction::AccountCreateTransaction() : Transaction() { - setMaxTransactionFee(Hbar(5LL)); + setDefaultMaxTransactionFee(Hbar(5LL)); } //----- AccountCreateTransaction::AccountCreateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptocreateaccount()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoCreateAccount data"); - } - - const proto::CryptoCreateTransactionBody& body = transactionBody.cryptocreateaccount(); - - if (body.has_key()) - { - mKey = ValuePtr(Key::fromProtobuf(body.key()).release()); - } - - mInitialBalance = Hbar(static_cast(body.initialbalance()), HbarUnit::TINYBAR()); - mReceiverSignatureRequired = body.receiversigrequired(); - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - mAccountMemo = body.memo(); - mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations()); - - if (body.has_staked_account_id()) - { - mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); - } - - else if (body.has_staked_node_id()) - { - mStakedNodeId = static_cast(body.staked_node_id()); - } - - mDeclineStakingReward = body.decline_reward(); + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); +} - if (!body.alias().empty()) - { - mAlias = EvmAddress::fromBytes(internal::Utilities::stringToByteVector(body.alias())); - } +//----- +AccountCreateTransaction::AccountCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); } //----- @@ -187,20 +159,12 @@ AccountCreateTransaction& AccountCreateTransaction::setAlias(const EvmAddress& a } //----- -proto::Transaction AccountCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status AccountCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status AccountCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoCreateAccount, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kCryptoCreateAccount, request, deadline, response); } //----- @@ -209,6 +173,52 @@ void AccountCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_cryptocreateaccount(build()); } +//----- +void AccountCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptocreateaccount()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoCreateAccount data"); + } + + const proto::CryptoCreateTransactionBody& body = transactionBody.cryptocreateaccount(); + + if (body.has_key()) + { + mKey = ValuePtr(Key::fromProtobuf(body.key()).release()); + } + + mInitialBalance = Hbar(static_cast(body.initialbalance()), HbarUnit::TINYBAR()); + mReceiverSignatureRequired = body.receiversigrequired(); + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + mAccountMemo = body.memo(); + mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations()); + + if (body.has_staked_account_id()) + { + mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); + } + + else if (body.has_staked_node_id()) + { + mStakedNodeId = static_cast(body.staked_node_id()); + } + + mDeclineStakingReward = body.decline_reward(); + + if (!body.alias().empty()) + { + mAlias = EvmAddress::fromBytes(internal::Utilities::stringToByteVector(body.alias())); + } +} + //----- proto::CryptoCreateTransactionBody* AccountCreateTransaction::build() const { diff --git a/sdk/main/src/AccountDeleteTransaction.cc b/sdk/main/src/AccountDeleteTransaction.cc index 8174959a0..3986f2b75 100644 --- a/sdk/main/src/AccountDeleteTransaction.cc +++ b/sdk/main/src/AccountDeleteTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera AccountDeleteTransaction::AccountDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptodelete()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoDelete data"); - } - - const proto::CryptoDeleteTransactionBody& body = transactionBody.cryptodelete(); - - if (body.has_deleteaccountid()) - { - mDeleteAccountId = AccountId::fromProtobuf(body.deleteaccountid()); - } + initFromSourceTransactionBody(); +} - if (body.has_transferaccountid()) - { - mTransferAccountId = AccountId::fromProtobuf(body.transferaccountid()); - } +//----- +AccountDeleteTransaction::AccountDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -68,20 +61,12 @@ AccountDeleteTransaction& AccountDeleteTransaction::setTransferAccountId(const A } //----- -proto::Transaction AccountDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status AccountDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status AccountDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoDelete, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kCryptoDelete, request, deadline, response); } //----- @@ -90,6 +75,29 @@ void AccountDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_cryptodelete(build()); } +//----- +void AccountDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptodelete()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoDelete data"); + } + + const proto::CryptoDeleteTransactionBody& body = transactionBody.cryptodelete(); + + if (body.has_deleteaccountid()) + { + mDeleteAccountId = AccountId::fromProtobuf(body.deleteaccountid()); + } + + if (body.has_transferaccountid()) + { + mTransferAccountId = AccountId::fromProtobuf(body.transferaccountid()); + } +} + //----- proto::CryptoDeleteTransactionBody* AccountDeleteTransaction::build() const { diff --git a/sdk/main/src/AccountInfoQuery.cc b/sdk/main/src/AccountInfoQuery.cc index 5ec084672..e0ae014c1 100644 --- a/sdk/main/src/AccountInfoQuery.cc +++ b/sdk/main/src/AccountInfoQuery.cc @@ -18,11 +18,7 @@ * */ #include "AccountInfoQuery.h" -#include "AccountId.h" #include "AccountInfo.h" -#include "Client.h" -#include "TransactionRecord.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -40,47 +36,37 @@ AccountInfoQuery& AccountInfoQuery::setAccountId(const AccountId& accountId) } //----- -proto::Query AccountInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +AccountInfo AccountInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::CryptoGetInfoQuery* getAccountInfoQuery = query.mutable_cryptogetinfo(); - - proto::QueryHeader* header = getAccountInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getAccountInfoQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); - - return query; + return AccountInfo::fromProtobuf(response.cryptogetinfo().accountinfo()); } //----- -AccountInfo AccountInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status AccountInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return AccountInfo::fromProtobuf(response.cryptogetinfo().accountinfo()); + return node->submitQuery(proto::Query::QueryCase::kCryptoGetInfo, request, deadline, response); } //----- -Status AccountInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query AccountInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.cryptogetinfo().header().nodetransactionprecheckcode()); + auto accountInfoQuery = std::make_unique(); + accountInfoQuery->set_allocated_header(header); + accountInfoQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_cryptogetinfo(accountInfoQuery.release()); + return query; } //----- -grpc::Status AccountInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader AccountInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kCryptoGetInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.cryptogetinfo().header()); + return response.cryptogetinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/AccountRecordsQuery.cc b/sdk/main/src/AccountRecordsQuery.cc index 8626e2d77..42ce27480 100644 --- a/sdk/main/src/AccountRecordsQuery.cc +++ b/sdk/main/src/AccountRecordsQuery.cc @@ -18,11 +18,7 @@ * */ #include "AccountRecordsQuery.h" -#include "AccountId.h" #include "AccountRecords.h" -#include "Client.h" -#include "TransactionRecord.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -40,48 +36,37 @@ AccountRecordsQuery& AccountRecordsQuery::setAccountId(const AccountId& accountI } //----- -proto::Query AccountRecordsQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +AccountRecords AccountRecordsQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::CryptoGetAccountRecordsQuery* getAccountRecordsQuery = query.mutable_cryptogetaccountrecords(); - - proto::QueryHeader* header = getAccountRecordsQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getAccountRecordsQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); - - return query; + return AccountRecords::fromProtobuf(response.cryptogetaccountrecords()); } //----- -AccountRecords AccountRecordsQuery::mapResponse(const proto::Response& response) const +grpc::Status AccountRecordsQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return AccountRecords::fromProtobuf(response.cryptogetaccountrecords()); + return node->submitQuery(proto::Query::QueryCase::kCryptoGetAccountRecords, request, deadline, response); } //----- -Status AccountRecordsQuery::mapResponseStatus(const proto::Response& response) const +proto::Query AccountRecordsQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.cryptogetaccountrecords().header().nodetransactionprecheckcode()); + auto accountRecordsQuery = std::make_unique(); + accountRecordsQuery->set_allocated_header(header); + accountRecordsQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_cryptogetaccountrecords(accountRecordsQuery.release()); + return query; } //----- -grpc::Status AccountRecordsQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader AccountRecordsQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kCryptoGetAccountRecords, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.cryptogetaccountrecords().header()); + return response.cryptogetaccountrecords().header(); } } // namespace Hedera diff --git a/sdk/main/src/AccountStakersQuery.cc b/sdk/main/src/AccountStakersQuery.cc index 9ab699ec1..960316c12 100644 --- a/sdk/main/src/AccountStakersQuery.cc +++ b/sdk/main/src/AccountStakersQuery.cc @@ -38,55 +38,44 @@ AccountStakersQuery& AccountStakersQuery::setAccountId(const AccountId& accountI return *this; } -//----- -proto::Query AccountStakersQuery::makeRequest(const Client& client, const std::shared_ptr& node) const -{ - proto::Query query; - proto::CryptoGetStakersQuery* getAccountStakersQuery = query.mutable_cryptogetproxystakers(); - - proto::QueryHeader* header = getAccountStakersQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getAccountStakersQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); - - return query; -} - //----- AccountStakers AccountStakersQuery::mapResponse(const proto::Response& response) const { AccountStakers accountStakers; - for (int i = 0; i < response.cryptogetproxystakers().stakers().proxystaker_size(); ++i) { + accountStakers.push_back(ProxyStaker::fromProtobuf(response.cryptogetproxystakers().stakers().proxystaker(i))); } return accountStakers; } //----- -Status AccountStakersQuery::mapResponseStatus(const proto::Response& response) const +grpc::Status AccountStakersQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const +{ + return node->submitQuery(proto::Query::QueryCase::kCryptoGetProxyStakers, request, deadline, response); +} + +//----- +proto::Query AccountStakersQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.cryptogetproxystakers().header().nodetransactionprecheckcode()); + auto accountStakersQuery = std::make_unique(); + accountStakersQuery->set_allocated_header(header); + accountStakersQuery->set_allocated_accountid(mAccountId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_cryptogetproxystakers(accountStakersQuery.release()); + return query; } //----- -grpc::Status AccountStakersQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader AccountStakersQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kCryptoGetProxyStakers, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.cryptogetproxystakers().header()); + return response.cryptogetproxystakers().header(); } } // namespace Hedera diff --git a/sdk/main/src/AccountUpdateTransaction.cc b/sdk/main/src/AccountUpdateTransaction.cc index d98ced16f..3bc7717ec 100644 --- a/sdk/main/src/AccountUpdateTransaction.cc +++ b/sdk/main/src/AccountUpdateTransaction.cc @@ -32,62 +32,15 @@ namespace Hedera AccountUpdateTransaction::AccountUpdateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptoupdateaccount()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoUpdate data"); - } - - const proto::CryptoUpdateTransactionBody& body = transactionBody.cryptoupdateaccount(); - - if (body.has_accountidtoupdate()) - { - mAccountId = AccountId::fromProtobuf(body.accountidtoupdate()); - } - - if (body.has_key()) - { - mKey = ValuePtr(Key::fromProtobuf(body.key()).release()); - } - - if (body.has_receiversigrequiredwrapper()) - { - mReceiverSignatureRequired = body.receiversigrequiredwrapper().value(); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } - - if (body.has_memo()) - { - mAccountMemo = body.memo().value(); - } - - if (body.has_max_automatic_token_associations()) - { - mMaxAutomaticTokenAssociations = body.max_automatic_token_associations().value(); - } - - if (body.has_staked_account_id()) - { - mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); - } - - if (body.has_staked_node_id()) - { - mStakedNodeId = static_cast(body.staked_node_id()); - } + initFromSourceTransactionBody(); +} - if (body.has_decline_reward()) - { - mDeclineStakingReward = body.decline_reward().value(); - } +//----- +AccountUpdateTransaction::AccountUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -195,20 +148,12 @@ AccountUpdateTransaction& AccountUpdateTransaction::setDeclineStakingReward(bool } //----- -proto::Transaction AccountUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status AccountUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status AccountUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoUpdateAccount, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kCryptoUpdateAccount, request, deadline, response); } //----- @@ -217,6 +162,69 @@ void AccountUpdateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_cryptoupdateaccount(build()); } +//----- +void AccountUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptoupdateaccount()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoUpdate data"); + } + + const proto::CryptoUpdateTransactionBody& body = transactionBody.cryptoupdateaccount(); + + if (body.has_accountidtoupdate()) + { + mAccountId = AccountId::fromProtobuf(body.accountidtoupdate()); + } + + if (body.has_key()) + { + mKey = ValuePtr(Key::fromProtobuf(body.key()).release()); + } + + if (body.has_receiversigrequiredwrapper()) + { + mReceiverSignatureRequired = body.receiversigrequiredwrapper().value(); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } + + if (body.has_memo()) + { + mAccountMemo = body.memo().value(); + } + + if (body.has_max_automatic_token_associations()) + { + mMaxAutomaticTokenAssociations = body.max_automatic_token_associations().value(); + } + + if (body.has_staked_account_id()) + { + mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); + } + + if (body.has_staked_node_id()) + { + mStakedNodeId = static_cast(body.staked_node_id()); + } + + if (body.has_decline_reward()) + { + mDeclineStakingReward = body.decline_reward().value(); + } +} + //----- proto::CryptoUpdateTransactionBody* AccountUpdateTransaction::build() const { diff --git a/sdk/main/src/ChunkedTransaction.cc b/sdk/main/src/ChunkedTransaction.cc index 9f86030a3..9443b052b 100644 --- a/sdk/main/src/ChunkedTransaction.cc +++ b/sdk/main/src/ChunkedTransaction.cc @@ -24,13 +24,42 @@ #include "TransactionReceipt.h" #include "TransactionResponse.h" #include "exceptions/IllegalStateException.h" +#include "impl/TimestampConverter.h" #include "impl/Utilities.h" +#include "impl/openssl_utils/OpenSSLUtils.h" #include -#include +#include +#include +#include +#include namespace Hedera { +//----- +template +struct ChunkedTransaction::ChunkedTransactionImpl +{ + // The TransactionIds of all chunks that are to be sent as part of this ChunkedTransaction, minus the first chunk + // (which is stored in Transaction::mTransactionId). + std::vector mChunkedTransactionIds; + + // This ChunkedTransaction's data. + std::vector mData; + + // The size of this ChunkedTransaction's chunks, in bytes. + unsigned int mChunkSize = DEFAULT_CHUNK_SIZE; + + // The maximum number of chunks into which this ChunkedTransaction will get broken up. + unsigned int mMaxChunks = DEFAULT_MAX_CHUNKS; + + // Should this ChunkedTransaction get a receipt for each submitted chunk? + bool mShouldGetReceipt = false; + + // The current chunk attempting to be sent. + unsigned int mCurrentChunk = 0U; +}; + //----- template TransactionResponse ChunkedTransaction::execute(const Client& client) @@ -61,75 +90,152 @@ std::vector ChunkedTransaction::executeAll( { // Determine how many chunks are going to be required to send this whole ChunkedTransaction and make sure it's within // the set limit. - const auto requiredChunks = - static_cast(std::ceil(static_cast(mData.size()) / static_cast(mChunkSize))); - if (requiredChunks > mMaxChunks) + const unsigned int requiredChunks = getNumberOfChunksRequired(); + if (requiredChunks > mImpl->mMaxChunks) { throw IllegalStateException("Transaction requires " + std::to_string(requiredChunks) + " but is only allotted " + - std::to_string(mMaxChunks) + ". Try using setMaxChunks()"); + std::to_string(mImpl->mMaxChunks) + ". Try using setMaxChunks()"); } // Container to hold responses. std::vector responses; + responses.reserve(requiredChunks); - // The transaction chunks being sent should all have the same TransactionId besides their valid start time being a - // little off. The first TransactionId should be saved so that it can be used to generate the IDs for the other - // chunks. - TransactionId firstTransactionId; - - // Move the data out to prevent an unnecessary copy of all the data. - std::vector data = std::move(mData); - mData.clear(); - mData.reserve(mChunkSize); - - for (int chunk = 0; chunk < requiredChunks; ++chunk) + for (; mImpl->mCurrentChunk < requiredChunks; ++mImpl->mCurrentChunk) { - // Create a copy of this entire transaction. This should carry over all manually-set items, if any. - SdkRequestType tx = *static_cast(this); - - // Create the chunk and set it in the transaction. - const unsigned int startingByteForChunk = mChunkSize * chunk; - const auto start = data.cbegin() + startingByteForChunk; - tx.mData = { start, - start + ((mChunkSize + startingByteForChunk > data.size()) ? data.size() - startingByteForChunk - : mChunkSize) }; - - // Adjust the TransactionId if this is not the first chunk. - if (chunk != 0) + responses.push_back( + Executable::execute( + client, timeout)); + + if (mImpl->mShouldGetReceipt) { - tx.setTransactionId(TransactionId::withValidStart( - firstTransactionId.getAccountId(), - firstTransactionId.getValidTransactionTime() + - std::chrono::duration(chunk))); + const TransactionReceipt txReceipt = responses.back().getReceipt(client, timeout); } + } - // Get the transaction ready to execute. - tx.freezeWith(&client); + // Reset current chunk. + mImpl->mCurrentChunk = 0U; - // Grab the first transaction if this is the first transaction. - if (chunk == 0) - { - firstTransactionId = tx.getTransactionId(); - } + return responses; +} - // Do any needed post-chunk processing on the transaction. This is required to happen after freezing so that - // TopicMessageSubmitTransaction can read the transaction ID. - tx.onChunk(firstTransactionId, chunk, requiredChunks); +//----- +template +SdkRequestType& ChunkedTransaction::addSignature(const std::shared_ptr& publicKey, + const std::vector& signature) +{ + if (mImpl->mData.size() > mImpl->mChunkSize) + { + throw IllegalStateException( + "Cannot manually add a signature to a ChunkedTransaction with data length greater than " + + std::to_string(mImpl->mChunkSize)); + } - // Execute the chunk. - responses.push_back(tx.wrappedExecute(client, timeout)); + return Transaction::addSignature(publicKey, signature); +} - // Wait for the transaction to fully complete, if configured - if (mShouldGetReceipt) +//----- +template +std::map, std::vector>> +ChunkedTransaction::getSignatures() const +{ + if (mImpl->mData.size() > mImpl->mChunkSize) + { + throw IllegalStateException("Cannot get signatures for a ChunkedTransaction with data length greater than " + + std::to_string(mImpl->mChunkSize) + ". Try calling getAllSignatures() instead."); + } + + return Transaction::getSignatures(); +} + +//----- +template +std::vector, std::vector>>> +ChunkedTransaction::getAllSignatures() const +{ + // Grab the signatures of the first chunk. If there are no signatures, there are no signers. + std::vector, std::vector>>> signatures; + signatures.push_back(Transaction::getSignatures()); + + if (signatures.cbegin()->empty()) + { + return {}; + } + + // All Transaction protobuf objects get built in Transaction::getSignatures(), so the signatures just + // need to be grabbed for each transaction chunk. The first transaction chunk is already in the signatures map, so + // start at index 1. + for (size_t i = 1; i < mImpl->mChunkedTransactionIds.size(); ++i) + { + signatures.push_back(Transaction::getSignaturesInternal(i)); + } + + return signatures; +} + +//----- +template +std::vector ChunkedTransaction::getTransactionHash() const +{ + if (!mImpl->mChunkedTransactionIds.empty()) + { + throw IllegalStateException( + "A single hash cannot be generated for this transaction, try calling 'getAllTransactionHashesPerNode()'"); + } + + return Transaction::getTransactionHash(); +} + +//----- +template +std::map> ChunkedTransaction::getTransactionHashPerNode() const +{ + if (!mImpl->mChunkedTransactionIds.empty()) + { + throw IllegalStateException( + "A single hash cannot be generated for this transaction, try calling 'getAllTransactionHashesPerNode()'"); + } + + return Transaction::getTransactionHashPerNode(); +} + +//----- +template +std::vector>> +ChunkedTransaction::getAllTransactionHashesPerNode() const +{ + if (!Transaction::isFrozen()) + { + throw IllegalStateException("Transaction must be frozen in order to calculate the hashes."); + } + + // Build all the Transaction protobuf objects. + Transaction::buildAllTransactions(); + + // Grab the node account IDs being used for this ChunkedTransaction. + const std::vector nodeAccountIds = + Executable:: + getNodeAccountIds(); + + // Add one to the mChunkedTransactionIds size to include the first TransactionId stored in the Transaction base class. + std::vector>> hashes; + for (unsigned int i = 0; i < mImpl->mChunkedTransactionIds.size() + 1; ++i) + { + // For each node account ID, grab the correct Transaction protobuf object and generate the hash. + std::map> hashMap; + for (unsigned int j = 0; j < nodeAccountIds.size(); ++j) { - const TransactionReceipt txReceipt = responses.back().getReceipt(client); + hashMap.emplace(nodeAccountIds.at(j), + internal::OpenSSLUtils::computeSHA384(internal::Utilities::stringToByteVector( + Transaction::getTransactionProtobufObject( + (i * static_cast(nodeAccountIds.size())) + j) + .signedtransactionbytes()))); } - } - // Move the data back into mData. - mData = std::move(data); + hashes.push_back(hashMap); + } - return responses; + return hashes; } //----- @@ -137,7 +243,7 @@ template SdkRequestType& ChunkedTransaction::setMaxChunks(unsigned int chunks) { Transaction::requireNotFrozen(); - mMaxChunks = chunks; + mImpl->mMaxChunks = chunks; return static_cast(*this); } @@ -146,16 +252,122 @@ template SdkRequestType& ChunkedTransaction::setChunkSize(unsigned int size) { Transaction::requireNotFrozen(); - mChunkSize = size; + mImpl->mChunkSize = size; return static_cast(*this); } +//----- +template +unsigned int ChunkedTransaction::getMaxChunks() const +{ + return mImpl->mMaxChunks; +} + +//----- +template +unsigned int ChunkedTransaction::getChunkSize() const +{ + return mImpl->mChunkSize; +} + +//----- +template +ChunkedTransaction::ChunkedTransaction() + : Transaction() + , mImpl(std::make_unique()) +{ +} + +//----- +template +ChunkedTransaction::~ChunkedTransaction() = default; + +//----- +template +ChunkedTransaction::ChunkedTransaction(const ChunkedTransaction& other) + : Transaction(other) + , mImpl(std::make_unique(*other.mImpl)) +{ +} + +//----- +template +ChunkedTransaction& ChunkedTransaction::operator=(const ChunkedTransaction& other) +{ + if (this != &other) + { + Transaction::operator=(other); + mImpl = std::make_unique(*other.mImpl); + } + + return *this; +} + +//----- +template +ChunkedTransaction::ChunkedTransaction(ChunkedTransaction&& other) noexcept + : Transaction(std::move(other)) + , mImpl(std::move(other.mImpl)) // NOLINT +{ +} + +//----- +template +ChunkedTransaction& ChunkedTransaction::operator=(ChunkedTransaction&& other) noexcept +{ + if (this != &other) + { + Transaction::operator=(std::move(other)); + mImpl = std::move(other.mImpl); // NOLINT + } + + return *this; +} + +//----- +template +ChunkedTransaction::ChunkedTransaction(const proto::TransactionBody& txBody) + : Transaction(txBody) + , mImpl(std::make_unique()) +{ +} + +//----- +template +ChunkedTransaction::ChunkedTransaction( + const std::map>& transactions) + : Transaction(transactions) + , mImpl(std::make_unique()) +{ + // Make sure there's more than one chunk. + if (transactions.size() <= 1) + { + return; + } + + // Go through each additional TransactionId and store its information. + auto iter = transactions.cbegin(); + std::advance(iter, 1); + + for (; iter != transactions.cend(); ++iter) + { + // Save the TransactionId. + mImpl->mChunkedTransactionIds.push_back(iter->first); + + // Add each Transaction protobuf object to this ChunkedTransaction's Transaction protobuf object list. The node + // account IDs should be in the same order as each other for each TransactionId. + for (const auto& [accountId, transaction] : iter->second) + { + Transaction::addTransaction(transaction); + } + } +} + //----- template SdkRequestType& ChunkedTransaction::setData(const std::vector& data) { - Transaction::requireNotFrozen(); - mData = data; + mImpl->mData = data; return static_cast(*this); } @@ -166,19 +378,106 @@ SdkRequestType& ChunkedTransaction::setData(std::string_view dat return setData(internal::Utilities::stringToByteVector(data)); } +//----- +template +std::vector ChunkedTransaction::getData() const +{ + return mImpl->mData; +} + +//----- +template +std::vector ChunkedTransaction::getDataForChunk(unsigned int chunk) const +{ + const unsigned int startingByteForChunk = mImpl->mChunkSize * chunk; + const auto start = mImpl->mData.cbegin() + startingByteForChunk; + return { start, + start + ((mImpl->mChunkSize + startingByteForChunk > mImpl->mData.size()) + ? mImpl->mData.size() - startingByteForChunk + : mImpl->mChunkSize) }; +} + //----- template void ChunkedTransaction::setShouldGetReceipt(bool retrieveReceipt) { - mShouldGetReceipt = retrieveReceipt; + mImpl->mShouldGetReceipt = retrieveReceipt; +} + +//----- +template +bool ChunkedTransaction::getShouldGetReceipt() const +{ + return mImpl->mShouldGetReceipt; +} + +//----- +template +proto::Transaction ChunkedTransaction::makeRequest(unsigned int attempt) const +{ + // Adjust the index to account for the current chunk. + return Transaction::makeRequest( + static_cast( + mImpl->mCurrentChunk * + Executable:: + getNodeAccountIds() + .size()) + + attempt); +} + +//----- +template +void ChunkedTransaction::generateSignedTransactions(const Client* client) +{ + // Update this Transaction's source TransactionBody protobuf object. + Transaction::updateSourceTransactionBody(client); + proto::TransactionBody sourceTransactionBody = Transaction::getSourceTransactionBody(); + + const unsigned int requiredChunks = getNumberOfChunksRequired(); + for (int i = 0; i < requiredChunks; ++i) + { + // Generate a new TransactionId if this isn't the first chunk. Add one to the smallest system clock duration to make + // cascading transaction IDs. + if (i > 0) + { + mImpl->mChunkedTransactionIds.push_back(TransactionId::withValidStart( + AccountId::fromProtobuf(sourceTransactionBody.transactionid().accountid()), + internal::TimestampConverter::fromProtobuf(sourceTransactionBody.transactionid().transactionvalidstart()) + + std::chrono::system_clock::duration(1))); + sourceTransactionBody.set_allocated_transactionid(mImpl->mChunkedTransactionIds.back().toProtobuf().release()); + } + + // Generate the chunk and add it to sourceTransactionBody. + addToChunk(i, requiredChunks, sourceTransactionBody); + + // Create a SignedTransaction protobuf object for each node account ID and add it to this ChunkedTransaction's + // SignedTransaction protobuf object list. + Transaction::addSignedTransactionForEachNode(sourceTransactionBody); + } +} + +//----- +template +void ChunkedTransaction::clearTransactions() +{ + Transaction::clearTransactions(); + mImpl->mChunkedTransactionIds.clear(); } + +//----- +template +TransactionId ChunkedTransaction::getCurrentTransactionId() const +{ + return mImpl->mCurrentChunk == 0 ? Transaction::getCurrentTransactionId() + : mImpl->mChunkedTransactionIds.at(mImpl->mCurrentChunk - 1); +} + //----- template -TransactionResponse ChunkedTransaction::wrappedExecute(const Client& client, - const std::chrono::duration& timeout) +unsigned int ChunkedTransaction::getNumberOfChunksRequired() const { - return Executable::execute( - client, timeout); + return static_cast( + std::ceil(static_cast(mImpl->mData.size()) / static_cast(mImpl->mChunkSize))); } /** diff --git a/sdk/main/src/Client.cc b/sdk/main/src/Client.cc index bf04ababb..71a6be77f 100644 --- a/sdk/main/src/Client.cc +++ b/sdk/main/src/Client.cc @@ -37,7 +37,7 @@ struct Client::ClientImpl { // Pointer to the network object that contains all processing for sending/receiving information to/from a Hedera // network. - std::optional mNetwork; + std::shared_ptr mNetwork = nullptr; // Pointer to the MirrorNetwork object that contains the mirror nodes for sending/receiving information to/from a // Hedera mirror node. @@ -52,6 +52,9 @@ struct Client::ClientImpl // The maximum fee this Client is willing to pay for transactions. std::optional mMaxTransactionFee; + // The maximum payment this Client is willing to make for queries. + std::optional mMaxQueryPayment; + // The transaction ID regeneration policy to utilize when transactions submitted by this Client receive a // TRANSACTION_EXPIRED response from the network. std::optional mTransactionIdRegenerationPolicy; @@ -106,7 +109,7 @@ Client& Client::operator=(Client&& other) noexcept Client Client::forMainnet() { Client client; - client.mImpl->mNetwork = internal::Network::forMainnet(); + client.mImpl->mNetwork = std::make_shared(internal::Network::forMainnet()); client.mImpl->mMirrorNetwork = std::make_shared(internal::MirrorNetwork::forMainnet()); return client; } @@ -115,7 +118,7 @@ Client Client::forMainnet() Client Client::forTestnet() { Client client; - client.mImpl->mNetwork = internal::Network::forTestnet(); + client.mImpl->mNetwork = std::make_shared(internal::Network::forTestnet()); client.mImpl->mMirrorNetwork = std::make_shared(internal::MirrorNetwork::forTestnet()); return client; } @@ -124,7 +127,7 @@ Client Client::forTestnet() Client Client::forPreviewnet() { Client client; - client.mImpl->mNetwork = internal::Network::forPreviewnet(); + client.mImpl->mNetwork = std::make_shared(internal::Network::forPreviewnet()); client.mImpl->mMirrorNetwork = std::make_shared(internal::MirrorNetwork::forPreviewnet()); return client; } @@ -133,7 +136,7 @@ Client Client::forPreviewnet() Client Client::forNetwork(const std::unordered_map& networkMap) { Client client; - client.mImpl->mNetwork = internal::Network::forNetwork(networkMap); + client.mImpl->mNetwork = std::make_shared(internal::Network::forNetwork(networkMap)); client.mImpl->mMirrorNetwork = nullptr; return client; } @@ -155,29 +158,6 @@ Client& Client::setOperator(const AccountId& accountId, const PrivateKey* privat return *this; } -//----- -std::vector Client::sign(const std::vector& bytes) const -{ - if (mImpl->mOperatorPrivateKey) - { - return mImpl->mOperatorPrivateKey->sign(bytes); - } - - throw UninitializedException("No client operator private key with which to sign"); -} - -//----- -std::vector> Client::getNodesWithAccountIds( - const std::vector& accountIds) const -{ - if (mImpl->mNetwork) - { - return mImpl->mNetwork->getNodesWithAccountIds(accountIds); - } - - throw UninitializedException("Client network uninitialized"); -} - void Client::close() const { if (mImpl->mNetwork) @@ -210,6 +190,18 @@ Client& Client::setMaxTransactionFee(const Hbar& fee) return *this; } +//----- +Client& Client::setMaxQueryPayment(const Hbar& payment) +{ + if (payment.toTinybars() < 0) + { + throw std::invalid_argument("Query payment cannot be negative"); + } + + mImpl->mMaxQueryPayment = payment; + return *this; +} + //----- Client& Client::setTransactionIdRegenerationPolicy(bool regenerate) { @@ -248,6 +240,12 @@ Client& Client::setMaxBackoff(const std::chrono::duration& backoff) return *this; } +//----- +std::shared_ptr Client::getNetwork() const +{ + return mImpl->mNetwork; +} + //----- std::optional Client::getOperatorAccountId() const { @@ -280,6 +278,12 @@ std::optional Client::getMaxTransactionFee() const return mImpl->mMaxTransactionFee; } +//----- +std::optional Client::getMaxQueryPayment() const +{ + return mImpl->mMaxQueryPayment; +} + //----- std::optional Client::getTransactionIdRegenerationPolicy() const { diff --git a/sdk/main/src/ContractByteCodeQuery.cc b/sdk/main/src/ContractByteCodeQuery.cc index 06fd8c416..a9d778776 100644 --- a/sdk/main/src/ContractByteCodeQuery.cc +++ b/sdk/main/src/ContractByteCodeQuery.cc @@ -18,9 +18,6 @@ * */ #include "ContractByteCodeQuery.h" -#include "Client.h" -#include "Status.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include "impl/Utilities.h" @@ -39,49 +36,37 @@ ContractByteCodeQuery& ContractByteCodeQuery::setContractId(const ContractId& co } //----- -proto::Query ContractByteCodeQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +ContractByteCode ContractByteCodeQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::ContractGetBytecodeQuery* getByteCodeQuery = query.mutable_contractgetbytecode(); - - proto::QueryHeader* header = getByteCodeQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getByteCodeQuery->set_allocated_contractid(mContractId.toProtobuf().release()); - - return query; + return internal::Utilities::stringToByteVector(response.contractgetbytecoderesponse().bytecode()); } //----- -ContractByteCode ContractByteCodeQuery::mapResponse(const proto::Response& response) const +grpc::Status ContractByteCodeQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return internal::Utilities::stringToByteVector(response.contractgetbytecoderesponse().bytecode()); + return node->submitQuery(proto::Query::QueryCase::kContractGetBytecode, request, deadline, response); } //----- -Status ContractByteCodeQuery::mapResponseStatus(const proto::Response& response) const +proto::Query ContractByteCodeQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at( - response.contractgetbytecoderesponse().header().nodetransactionprecheckcode()); + auto contractByteCodeQuery = std::make_unique(); + contractByteCodeQuery->set_allocated_header(header); + contractByteCodeQuery->set_allocated_contractid(mContractId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_contractgetbytecode(contractByteCodeQuery.release()); + return query; } //----- -grpc::Status ContractByteCodeQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader ContractByteCodeQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kContractGetBytecode, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.contractgetbytecoderesponse().header()); + return response.contractgetbytecoderesponse().header(); } } // namespace Hedera \ No newline at end of file diff --git a/sdk/main/src/ContractCallQuery.cc b/sdk/main/src/ContractCallQuery.cc index 61bb25851..5ee753d95 100644 --- a/sdk/main/src/ContractCallQuery.cc +++ b/sdk/main/src/ContractCallQuery.cc @@ -18,10 +18,7 @@ * */ #include "ContractCallQuery.h" -#include "Client.h" #include "ContractFunctionResult.h" -#include "Status.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include "impl/Utilities.h" @@ -67,55 +64,44 @@ ContractCallQuery& ContractCallQuery::setSenderAccountId(const AccountId& accoun } //----- -proto::Query ContractCallQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +ContractFunctionResult ContractCallQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::ContractCallLocalQuery* callLocalQuery = query.mutable_contractcalllocal(); - - proto::QueryHeader* header = callLocalQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - callLocalQuery->set_allocated_contractid(mContractId.toProtobuf().release()); - callLocalQuery->set_gas(static_cast(mGas)); - callLocalQuery->set_allocated_functionparameters( - new std::string(internal::Utilities::byteVectorToString(mFunctionParameters))); - - if (mSenderAccountId.has_value()) - { - callLocalQuery->set_allocated_sender_id(mSenderAccountId->toProtobuf().release()); - } - - return query; + return ContractFunctionResult::fromProtobuf(response.contractcalllocal().functionresult()); } //----- -ContractFunctionResult ContractCallQuery::mapResponse(const proto::Response& response) const +grpc::Status ContractCallQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return ContractFunctionResult::fromProtobuf(response.contractcalllocal().functionresult()); + return node->submitQuery(proto::Query::QueryCase::kContractCallLocal, request, deadline, response); } //----- -Status ContractCallQuery::mapResponseStatus(const proto::Response& response) const +proto::Query ContractCallQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.contractcalllocal().header().nodetransactionprecheckcode()); + auto contractCallQuery = std::make_unique(); + contractCallQuery->set_allocated_header(header); + contractCallQuery->set_allocated_contractid(mContractId.toProtobuf().release()); + contractCallQuery->set_gas(static_cast(mGas)); + contractCallQuery->set_functionparameters(internal::Utilities::byteVectorToString(mFunctionParameters)); + + if (mSenderAccountId.has_value()) + { + contractCallQuery->set_allocated_sender_id(mSenderAccountId->toProtobuf().release()); + } + + proto::Query query; + query.set_allocated_contractcalllocal(contractCallQuery.release()); + return query; } //----- -grpc::Status ContractCallQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader ContractCallQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kContractCallLocal, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.contractcalllocal().header()); + return response.contractcalllocal().header(); } } // namespace Hedera diff --git a/sdk/main/src/ContractCreateTransaction.cc b/sdk/main/src/ContractCreateTransaction.cc index 58f74ce38..b411f012c 100644 --- a/sdk/main/src/ContractCreateTransaction.cc +++ b/sdk/main/src/ContractCreateTransaction.cc @@ -34,62 +34,24 @@ namespace Hedera ContractCreateTransaction::ContractCreateTransaction() : Transaction() { - setMaxTransactionFee(Hbar(20LL)); + setDefaultMaxTransactionFee(Hbar(20LL)); } //----- ContractCreateTransaction::ContractCreateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_contractcreateinstance()) - { - throw std::invalid_argument("Transaction body doesn't contain ContractCreateInstance data"); - } - - const proto::ContractCreateTransactionBody& body = transactionBody.contractcreateinstance(); - - if (body.has_fileid()) - { - mBytecodeFileId = FileId::fromProtobuf(body.fileid()); - } - - if (body.has_initcode()) - { - mBytecode = internal::Utilities::stringToByteVector(body.initcode()); - } - - if (body.has_adminkey()) - { - mAdminKey = ValuePtr(Key::fromProtobuf(body.adminkey()).release()); - } - - mGas = static_cast(body.gas()); - mInitialBalance = Hbar(body.initialbalance(), HbarUnit::TINYBAR()); - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - mConstructorParameters = internal::Utilities::stringToByteVector(body.constructorparameters()); - mMemo = body.memo(); - mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations()); - - if (body.has_auto_renew_account_id()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.auto_renew_account_id()); - } - - if (body.has_staked_account_id()) - { - mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); - } - - if (body.has_staked_node_id()) - { - mStakedNodeId = static_cast(body.staked_node_id()); - } + setDefaultMaxTransactionFee(Hbar(20LL)); + initFromSourceTransactionBody(); +} - mDeclineStakingReward = body.decline_reward(); +//----- +ContractCreateTransaction::ContractCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + setDefaultMaxTransactionFee(Hbar(20LL)); + initFromSourceTransactionBody(); } //----- @@ -203,20 +165,13 @@ ContractCreateTransaction& ContractCreateTransaction::setDeclineStakingReward(bo } //----- -proto::Transaction ContractCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ContractCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ContractCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { return node->submitTransaction( - proto::TransactionBody::DataCase::kContractCreateInstance, makeRequest(client, node), deadline, response); + proto::TransactionBody::DataCase::kContractCreateInstance, request, deadline, response); } //----- @@ -225,6 +180,63 @@ void ContractCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_contractcreateinstance(build()); } +//----- +void ContractCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_contractcreateinstance()) + { + throw std::invalid_argument("Transaction body doesn't contain ContractCreateInstance data"); + } + + const proto::ContractCreateTransactionBody& body = transactionBody.contractcreateinstance(); + + if (body.has_fileid()) + { + mBytecodeFileId = FileId::fromProtobuf(body.fileid()); + } + + if (body.has_initcode()) + { + mBytecode = internal::Utilities::stringToByteVector(body.initcode()); + } + + if (body.has_adminkey()) + { + mAdminKey = ValuePtr(Key::fromProtobuf(body.adminkey()).release()); + } + + mGas = static_cast(body.gas()); + mInitialBalance = Hbar(body.initialbalance(), HbarUnit::TINYBAR()); + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + mConstructorParameters = internal::Utilities::stringToByteVector(body.constructorparameters()); + mMemo = body.memo(); + mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations()); + + if (body.has_auto_renew_account_id()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.auto_renew_account_id()); + } + + if (body.has_staked_account_id()) + { + mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); + } + + if (body.has_staked_node_id()) + { + mStakedNodeId = static_cast(body.staked_node_id()); + } + + mDeclineStakingReward = body.decline_reward(); +} + //----- proto::ContractCreateTransactionBody* ContractCreateTransaction::build() const { diff --git a/sdk/main/src/ContractDeleteTransaction.cc b/sdk/main/src/ContractDeleteTransaction.cc index 0781e34a9..48d26ecbf 100644 --- a/sdk/main/src/ContractDeleteTransaction.cc +++ b/sdk/main/src/ContractDeleteTransaction.cc @@ -29,28 +29,17 @@ namespace Hedera { //----- ContractDeleteTransaction::ContractDeleteTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_contractdeleteinstance()) - { - throw std::invalid_argument("Transaction body doesn't contain ContractDeleteInstance data"); - } - - const proto::ContractDeleteTransactionBody& body = transactionBody.contractdeleteinstance(); - - if (body.has_contractid()) - { - mContractId = ContractId::fromProtobuf(body.contractid()); - } - - if (body.has_transferaccountid()) - { - mTransferAccountId = AccountId::fromProtobuf(body.transferaccountid()); - } + initFromSourceTransactionBody(); +} - else if (body.has_transfercontractid()) - { - mTransferContractId = ContractId::fromProtobuf(body.transfercontractid()); - } +//----- +ContractDeleteTransaction::ContractDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -80,20 +69,13 @@ ContractDeleteTransaction& ContractDeleteTransaction::setTransferContractId(cons } //----- -proto::Transaction ContractDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ContractDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ContractDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { return node->submitTransaction( - proto::TransactionBody::DataCase::kContractDeleteInstance, makeRequest(client, node), deadline, response); + proto::TransactionBody::DataCase::kContractDeleteInstance, request, deadline, response); } //----- @@ -102,6 +84,34 @@ void ContractDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_contractdeleteinstance(build()); } +//----- +void ContractDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_contractdeleteinstance()) + { + throw std::invalid_argument("Transaction body doesn't contain ContractDeleteInstance data"); + } + + const proto::ContractDeleteTransactionBody& body = transactionBody.contractdeleteinstance(); + + if (body.has_contractid()) + { + mContractId = ContractId::fromProtobuf(body.contractid()); + } + + if (body.has_transferaccountid()) + { + mTransferAccountId = AccountId::fromProtobuf(body.transferaccountid()); + } + + else if (body.has_transfercontractid()) + { + mTransferContractId = ContractId::fromProtobuf(body.transfercontractid()); + } +} + //----- proto::ContractDeleteTransactionBody* ContractDeleteTransaction::build() const { diff --git a/sdk/main/src/ContractExecuteTransaction.cc b/sdk/main/src/ContractExecuteTransaction.cc index 1058bc29d..bec8b4a3e 100644 --- a/sdk/main/src/ContractExecuteTransaction.cc +++ b/sdk/main/src/ContractExecuteTransaction.cc @@ -31,22 +31,17 @@ namespace Hedera { //----- ContractExecuteTransaction::ContractExecuteTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_contractcall()) - { - throw std::invalid_argument("Transaction body doesn't contain ContractCall data"); - } - - const proto::ContractCallTransactionBody& body = transactionBody.contractcall(); - - if (body.has_contractid()) - { - mContractId = ContractId::fromProtobuf(body.contractid()); - } + initFromSourceTransactionBody(); +} - mGas = static_cast(body.gas()); - mPayableAmount = Hbar(body.amount(), HbarUnit::TINYBAR()); - mFunctionParameters = internal::Utilities::stringToByteVector(body.functionparameters()); +//----- +ContractExecuteTransaction::ContractExecuteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -91,20 +86,12 @@ ContractExecuteTransaction& ContractExecuteTransaction::setFunction(std::string_ } //----- -proto::Transaction ContractExecuteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ContractExecuteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ContractExecuteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kContractCall, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kContractCall, request, deadline, response); } //----- @@ -113,6 +100,28 @@ void ContractExecuteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_contractcall(build()); } +//----- +void ContractExecuteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_contractcall()) + { + throw std::invalid_argument("Transaction body doesn't contain ContractCall data"); + } + + const proto::ContractCallTransactionBody& body = transactionBody.contractcall(); + + if (body.has_contractid()) + { + mContractId = ContractId::fromProtobuf(body.contractid()); + } + + mGas = static_cast(body.gas()); + mPayableAmount = Hbar(body.amount(), HbarUnit::TINYBAR()); + mFunctionParameters = internal::Utilities::stringToByteVector(body.functionparameters()); +} + //----- proto::ContractCallTransactionBody* ContractExecuteTransaction::build() const { diff --git a/sdk/main/src/ContractInfoQuery.cc b/sdk/main/src/ContractInfoQuery.cc index 8c2cd39bc..0984055b1 100644 --- a/sdk/main/src/ContractInfoQuery.cc +++ b/sdk/main/src/ContractInfoQuery.cc @@ -18,10 +18,7 @@ * */ #include "ContractInfoQuery.h" -#include "Client.h" #include "ContractInfo.h" -#include "Status.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -39,47 +36,37 @@ ContractInfoQuery& ContractInfoQuery::setContractId(const ContractId& contractId } //----- -proto::Query ContractInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +ContractInfo ContractInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::ContractGetInfoQuery* getContractInfoQuery = query.mutable_contractgetinfo(); - - proto::QueryHeader* header = getContractInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getContractInfoQuery->set_allocated_contractid(mContractId.toProtobuf().release()); - - return query; + return ContractInfo::fromProtobuf(response.contractgetinfo().contractinfo()); } //----- -ContractInfo ContractInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status ContractInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return ContractInfo::fromProtobuf(response.contractgetinfo().contractinfo()); + return node->submitQuery(proto::Query::QueryCase::kContractGetInfo, request, deadline, response); } //----- -Status ContractInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query ContractInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.contractgetinfo().header().nodetransactionprecheckcode()); + auto contractGetInfoQuery = std::make_unique(); + contractGetInfoQuery->set_allocated_header(header); + contractGetInfoQuery->set_allocated_contractid(mContractId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_contractgetinfo(contractGetInfoQuery.release()); + return query; } //----- -grpc::Status ContractInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader ContractInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kContractGetInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.contractgetinfo().header()); + return response.contractgetinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/ContractUpdateTransaction.cc b/sdk/main/src/ContractUpdateTransaction.cc index 626ca994f..630f31c23 100644 --- a/sdk/main/src/ContractUpdateTransaction.cc +++ b/sdk/main/src/ContractUpdateTransaction.cc @@ -33,62 +33,15 @@ namespace Hedera ContractUpdateTransaction::ContractUpdateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_contractupdateinstance()) - { - throw std::invalid_argument("Transaction body doesn't contain ContractUpdateInstance data"); - } - - const proto::ContractUpdateTransactionBody& body = transactionBody.contractupdateinstance(); - - if (body.has_contractid()) - { - mContractId = ContractId::fromProtobuf(body.contractid()); - } - - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } - - if (body.has_adminkey()) - { - mAdminKey = ValuePtr(Key::fromProtobuf(body.adminkey()).release()); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - if (body.has_memowrapper()) - { - mContractMemo = body.memowrapper().value(); - } - - if (body.has_max_automatic_token_associations()) - { - mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations().value()); - } - - if (body.has_auto_renew_account_id()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.auto_renew_account_id()); - } - - if (body.has_staked_account_id()) - { - mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); - } - - if (body.has_staked_node_id()) - { - mStakedNodeId = static_cast(body.staked_node_id()); - } + initFromSourceTransactionBody(); +} - if (body.has_decline_reward()) - { - mDeclineStakingReward = body.decline_reward().value(); - } +//----- +ContractUpdateTransaction::ContractUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -188,20 +141,13 @@ ContractUpdateTransaction& ContractUpdateTransaction::setDeclineStakingReward(bo } //----- -proto::Transaction ContractUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ContractUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ContractUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { return node->submitTransaction( - proto::TransactionBody::DataCase::kContractUpdateInstance, makeRequest(client, node), deadline, response); + proto::TransactionBody::DataCase::kContractUpdateInstance, request, deadline, response); } //----- @@ -210,6 +156,69 @@ void ContractUpdateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_contractupdateinstance(build()); } +//----- +void ContractUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_contractupdateinstance()) + { + throw std::invalid_argument("Transaction body doesn't contain ContractUpdateInstance data"); + } + + const proto::ContractUpdateTransactionBody& body = transactionBody.contractupdateinstance(); + + if (body.has_contractid()) + { + mContractId = ContractId::fromProtobuf(body.contractid()); + } + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } + + if (body.has_adminkey()) + { + mAdminKey = ValuePtr(Key::fromProtobuf(body.adminkey()).release()); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + if (body.has_memowrapper()) + { + mContractMemo = body.memowrapper().value(); + } + + if (body.has_max_automatic_token_associations()) + { + mMaxAutomaticTokenAssociations = static_cast(body.max_automatic_token_associations().value()); + } + + if (body.has_auto_renew_account_id()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.auto_renew_account_id()); + } + + if (body.has_staked_account_id()) + { + mStakedAccountId = AccountId::fromProtobuf(body.staked_account_id()); + } + + if (body.has_staked_node_id()) + { + mStakedNodeId = static_cast(body.staked_node_id()); + } + + if (body.has_decline_reward()) + { + mDeclineStakingReward = body.decline_reward().value(); + } +} + //----- proto::ContractUpdateTransactionBody* ContractUpdateTransaction::build() const { diff --git a/sdk/main/src/ECDSAsecp256k1PublicKey.cc b/sdk/main/src/ECDSAsecp256k1PublicKey.cc index 23d24208a..a559d39e8 100644 --- a/sdk/main/src/ECDSAsecp256k1PublicKey.cc +++ b/sdk/main/src/ECDSAsecp256k1PublicKey.cc @@ -423,6 +423,16 @@ std::vector ECDSAsecp256k1PublicKey::toBytesRaw() const publicKeyBytes.cend() }); } +//----- +std::unique_ptr ECDSAsecp256k1PublicKey::toSignaturePairProtobuf( + const std::vector& signature) const +{ + auto signaturePair = std::make_unique(); + signaturePair->set_pubkeyprefix(internal::Utilities::byteVectorToString(toBytesRaw())); + signaturePair->set_ecdsa_secp256k1(internal::Utilities::byteVectorToString(signature)); + return signaturePair; +} + //----- EvmAddress ECDSAsecp256k1PublicKey::toEvmAddress() const { diff --git a/sdk/main/src/ED25519PublicKey.cc b/sdk/main/src/ED25519PublicKey.cc index f357f2b81..2723f7785 100644 --- a/sdk/main/src/ED25519PublicKey.cc +++ b/sdk/main/src/ED25519PublicKey.cc @@ -185,6 +185,16 @@ std::vector ED25519PublicKey::toBytesRaw() const return internal::Utilities::removePrefix(toBytesDer(), static_cast(DER_ENCODED_PREFIX_BYTES.size())); } +//----- +std::unique_ptr ED25519PublicKey::toSignaturePairProtobuf( + const std::vector& signature) const +{ + auto signaturePair = std::make_unique(); + signaturePair->set_pubkeyprefix(internal::Utilities::byteVectorToString(toBytesRaw())); + signaturePair->set_ed25519(internal::Utilities::byteVectorToString(signature)); + return signaturePair; +} + //----- ED25519PublicKey::ED25519PublicKey(internal::OpenSSLUtils::EVP_PKEY&& key) : PublicKey(std::move(key)) diff --git a/sdk/main/src/EthereumTransaction.cc b/sdk/main/src/EthereumTransaction.cc index 2d05ecbfb..7f8caf8cb 100644 --- a/sdk/main/src/EthereumTransaction.cc +++ b/sdk/main/src/EthereumTransaction.cc @@ -31,21 +31,15 @@ namespace Hedera EthereumTransaction::EthereumTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_ethereumtransaction()) - { - throw std::invalid_argument("Transaction body doesn't contain EthereumTransaction data"); - } - - const proto::EthereumTransactionBody& body = transactionBody.ethereumtransaction(); - - mEthereumData = internal::Utilities::stringToByteVector(body.ethereum_data()); - - if (body.has_call_data()) - { - mCallDataFileId = FileId::fromProtobuf(body.call_data()); - } + initFromSourceTransactionBody(); +} - mMaxGasAllowance = Hbar(body.max_gas_allowance(), HbarUnit::TINYBAR()); +//----- +EthereumTransaction::EthereumTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -73,19 +67,12 @@ EthereumTransaction& EthereumTransaction::setMaxGasAllowance(const Hbar& maxGasA } //----- -proto::Transaction EthereumTransaction::makeRequest(const Client& client, const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status EthereumTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status EthereumTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kEthereumTransaction, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kEthereumTransaction, request, deadline, response); } //----- @@ -94,6 +81,28 @@ void EthereumTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_ethereumtransaction(build()); } +//----- +void EthereumTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_ethereumtransaction()) + { + throw std::invalid_argument("Transaction body doesn't contain EthereumTransaction data"); + } + + const proto::EthereumTransactionBody& body = transactionBody.ethereumtransaction(); + + mEthereumData = internal::Utilities::stringToByteVector(body.ethereum_data()); + + if (body.has_call_data()) + { + mCallDataFileId = FileId::fromProtobuf(body.call_data()); + } + + mMaxGasAllowance = Hbar(body.max_gas_allowance(), HbarUnit::TINYBAR()); +} + //----- proto::EthereumTransactionBody* EthereumTransaction::build() const { diff --git a/sdk/main/src/Executable.cc b/sdk/main/src/Executable.cc index 52c09eaad..a55676e8d 100644 --- a/sdk/main/src/Executable.cc +++ b/sdk/main/src/Executable.cc @@ -89,9 +89,12 @@ #include "TransactionRecordQuery.h" #include "TransactionResponse.h" #include "TransferTransaction.h" +#include "exceptions/IllegalStateException.h" #include "exceptions/MaxAttemptsExceededException.h" #include "exceptions/PrecheckStatusException.h" +#include "impl/Network.h" #include "impl/Node.h" +#include "impl/Utilities.h" #include #include @@ -122,25 +125,23 @@ SdkResponseType Executable> nodes = getNodesFromNodeAccountIds(client); + + // The time to timeout. const std::chrono::system_clock::time_point timeoutTime = std::chrono::system_clock::now() + std::chrono::duration_cast(timeout); - // The response object to fill - ProtoResponseType response; - - // List of nodes to which this Executable may be sent - const std::vector> nodes = client.getNodesWithAccountIds(mNodeAccountIds); - - for (uint32_t attempt = 1;; ++attempt) + for (unsigned int attempt = 0U;; ++attempt) { - if (attempt > mCurrentMaxAttempts) + if (attempt >= mCurrentMaxAttempts) { throw MaxAttemptsExceededException("Max number of attempts made (max attempts allowed: " + std::to_string(mCurrentMaxAttempts)); } - std::shared_ptr node = getNodeForExecute(nodes); + const unsigned int nodeIndex = getNodeIndexForExecute(nodes, attempt); + const std::shared_ptr& node = nodes.at(nodeIndex); // If the returned node is not healthy, then no nodes are healthy and the returned node has the shortest remaining // delay. Sleep for the delay period. @@ -150,15 +151,20 @@ SdkResponseType Executableconnect(timeoutTime)) + if (node->channelFailedToConnect()) { + std::cout << "Failed to connect to node " << node->getAccountId().toString() << " at address " + << node->getAddress().toString() << " on attempt " << attempt << std::endl; node->increaseBackoff(); continue; } - // Do node specific tasks - onSelectNode(node); - const grpc::Status status = submitRequest(client, timeoutTime, node, &response); + // Create the request based on the index of the node being used. + const ProtoRequestType request = makeRequest(nodeIndex); + + // Submit the request and get the response. + ProtoResponseType response; + const grpc::Status status = submitRequest(request, node, timeoutTime, &response); // Increase backoff for this node but try submitting again for UNAVAILABLE, RESOURCE_EXHAUSTED, and INTERNAL // responses. @@ -184,7 +190,7 @@ SdkResponseType Executable SdkRequestType& Executable::setNodeAccountIds( - const std::vector& nodeAccountIds) + std::vector nodeAccountIds) { - mNodeAccountIds = nodeAccountIds; + mNodeAccountIds = std::move(nodeAccountIds); return static_cast(*this); } @@ -245,15 +251,6 @@ SdkRequestType& Executable(*this); } -//----- -template -void Executable::onSelectNode( - const std::shared_ptr& node) -{ - node->setMinBackoff(mCurrentMinBackoff); - node->setMaxBackoff(mCurrentMaxBackoff); -} - //----- template typename Executable::ExecutionStatus @@ -269,7 +266,6 @@ Executable case Status::BUSY: return ExecutionStatus::SERVER_ERROR; case Status::OK: - case Status::SUCCESS: return ExecutionStatus::SUCCESS; // Let derived class handle this status, assume request error default: @@ -296,36 +292,84 @@ void Executable -std::shared_ptr -Executable::getNodeForExecute( - const std::vector>& nodes) const +std::vector> +Executable::getNodesFromNodeAccountIds( + const Client& client) const +{ + std::vector> nodes; + + // If only a single node is explicitly set, still return all the proxies for that node. It's possible the node itself + // still works but something could be wrong with the proxy, in which case trying a different proxy would work. + if (mNodeAccountIds.size() == 1) + { + nodes = client.getNetwork()->getNodeProxies(*mNodeAccountIds.cbegin()); + + // Still verify the node account ID mapped to a valid Node. + if (nodes.empty()) + { + throw IllegalStateException("Node account ID " + mNodeAccountIds.cbegin()->toString() + + " did not map to a valid node in the input Client's network."); + } + + return nodes; + } + + // If there are multiple nodes, this Executable should simply try a different node instead of a different proxy on the + // same node. + for (const AccountId& accountId : mNodeAccountIds) + { + const std::vector> nodeProxies = client.getNetwork()->getNodeProxies(accountId); + + // Verify the node account ID mapped to a valid Node. + if (nodeProxies.empty()) + { + throw IllegalStateException("Node account ID " + accountId.toString() + + " did not map to a valid node in the input Client's network."); + } + + // Pick a random proxy from the proxy list to add to the node list. + nodes.push_back( + nodeProxies.at(internal::Utilities::getRandomNumber(0U, static_cast(nodeProxies.size()) - 1U))); + } + + return nodes; +} + +//----- +template +unsigned int Executable::getNodeIndexForExecute( + const std::vector>& nodes, + unsigned int attempt) const { - // Keep track of the best candidate node and its delay. - std::shared_ptr candidateNode = nullptr; + // Keep track of the best candidate node and its delay (initialize to make compiler happy, but this should never be + // returned without being provided an actual legitimate value). + unsigned int candidateNodeIndex = -1U; std::chrono::duration candidateDelay(std::numeric_limits::max()); - for (const auto& node : nodes) + // Start looking at nodes at the attempt index, but wrap if there's been more attempts than nodes. + for (unsigned int i = attempt % nodes.size(); i < nodes.size(); ++i) { + const std::shared_ptr& node = nodes.at(i); if (!node->isHealthy()) { // Mark this the candidate node if it has the smaller delay than the previous candidate. const std::chrono::duration backoffTime = node->getRemainingTimeForBackoff(); if (backoffTime < candidateDelay) { - candidateNode = node; + candidateNodeIndex = i; candidateDelay = backoffTime; } } - // If this node is healthy, then return it. + // If this node is healthy, then its usable. else { - return node; + return i; } } - // No nodes are healthy, return the one with the smallest delay. - return candidateNode; + // No nodes are healthy, return the index of the one with the smallest delay. + return candidateNodeIndex; } /** diff --git a/sdk/main/src/FileAppendTransaction.cc b/sdk/main/src/FileAppendTransaction.cc index b988e7666..51958de40 100644 --- a/sdk/main/src/FileAppendTransaction.cc +++ b/sdk/main/src/FileAppendTransaction.cc @@ -30,28 +30,28 @@ namespace Hedera { //----- FileAppendTransaction::FileAppendTransaction() + : ChunkedTransaction() { - setMaxTransactionFee(Hbar(5LL)); - setChunkSize(DEFAULT_CHUNK_SIZE); + setDefaultMaxTransactionFee(Hbar(5LL)); + setChunkSize(2048U); setShouldGetReceipt(true); } //----- FileAppendTransaction::FileAppendTransaction(const proto::TransactionBody& transactionBody) + : ChunkedTransaction(transactionBody) { - if (!transactionBody.has_fileappend()) - { - throw std::invalid_argument("Transaction body doesn't contain FileAppend data"); - } - - const proto::FileAppendTransactionBody& body = transactionBody.fileappend(); - - if (body.has_fileid()) - { - mFileId = FileId::fromProtobuf(body.fileid()); - } + setShouldGetReceipt(true); + initFromSourceTransactionBody(); +} - setData(internal::Utilities::stringToByteVector(body.contents())); +//----- +FileAppendTransaction::FileAppendTransaction( + const std::map>& transactions) + : ChunkedTransaction(transactions) +{ + setShouldGetReceipt(true); + initFromSourceTransactionBody(); } //----- @@ -79,20 +79,12 @@ FileAppendTransaction& FileAppendTransaction::setContents(std::string_view conte } //----- -proto::Transaction FileAppendTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status FileAppendTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status FileAppendTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kFileAppend, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kFileAppend, request, deadline, response); } //----- @@ -102,11 +94,38 @@ void FileAppendTransaction::addToBody(proto::TransactionBody& body) const } //----- -proto::FileAppendTransactionBody* FileAppendTransaction::build() const +void FileAppendTransaction::addToChunk(uint32_t chunk, uint32_t, proto::TransactionBody& body) const +{ + body.set_allocated_fileappend(build(static_cast(chunk))); +} + +//----- +void FileAppendTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_fileappend()) + { + throw std::invalid_argument("Transaction body doesn't contain FileAppend data"); + } + + const proto::FileAppendTransactionBody& body = transactionBody.fileappend(); + + if (body.has_fileid()) + { + mFileId = FileId::fromProtobuf(body.fileid()); + } + + setData(internal::Utilities::stringToByteVector(body.contents())); +} + +//----- +proto::FileAppendTransactionBody* FileAppendTransaction::build(int chunk) const { auto body = std::make_unique(); body->set_allocated_fileid(mFileId.toProtobuf().release()); - body->set_contents(internal::Utilities::byteVectorToString(getData())); + body->set_contents(internal::Utilities::byteVectorToString( + (chunk >= 0) ? getDataForChunk(static_cast(chunk)) : getData())); return body.release(); } diff --git a/sdk/main/src/FileContentsQuery.cc b/sdk/main/src/FileContentsQuery.cc index 49e56cad9..4333239b9 100644 --- a/sdk/main/src/FileContentsQuery.cc +++ b/sdk/main/src/FileContentsQuery.cc @@ -18,9 +18,6 @@ * */ #include "FileContentsQuery.h" -#include "Client.h" -#include "Status.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include "impl/Utilities.h" @@ -39,48 +36,37 @@ FileContentsQuery& FileContentsQuery::setFileId(const FileId& fileId) } //----- -proto::Query FileContentsQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +FileContents FileContentsQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::FileGetContentsQuery* getFileContentsQuery = query.mutable_filegetcontents(); - - proto::QueryHeader* header = getFileContentsQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getFileContentsQuery->set_allocated_fileid(mFileId.toProtobuf().release()); - - return query; + return internal::Utilities::stringToByteVector(response.filegetcontents().filecontents().contents()); } //----- -FileContents FileContentsQuery::mapResponse(const proto::Response& response) const +grpc::Status FileContentsQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return internal::Utilities::stringToByteVector(response.filegetcontents().filecontents().contents()); + return node->submitQuery(proto::Query::QueryCase::kFileGetContents, request, deadline, response); } //----- -Status FileContentsQuery::mapResponseStatus(const proto::Response& response) const +proto::Query FileContentsQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at( - response.contractgetbytecoderesponse().header().nodetransactionprecheckcode()); + auto fileGetContentsQuery = std::make_unique(); + fileGetContentsQuery->set_allocated_header(header); + fileGetContentsQuery->set_allocated_fileid(mFileId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_filegetcontents(fileGetContentsQuery.release()); + return query; } //----- -grpc::Status FileContentsQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader FileContentsQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kFileGetContents, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.filegetcontents().header()); + return response.filegetcontents().header(); } } // namespace Hedera diff --git a/sdk/main/src/FileCreateTransaction.cc b/sdk/main/src/FileCreateTransaction.cc index 889c2d9c1..feb5695bf 100644 --- a/sdk/main/src/FileCreateTransaction.cc +++ b/sdk/main/src/FileCreateTransaction.cc @@ -32,31 +32,24 @@ namespace Hedera //----- FileCreateTransaction::FileCreateTransaction() { - setMaxTransactionFee(Hbar(5LL)); + setDefaultMaxTransactionFee(Hbar(5LL)); } //----- FileCreateTransaction::FileCreateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_filecreate()) - { - throw std::invalid_argument("Transaction body doesn't contain FileCreate data"); - } - - const proto::FileCreateTransactionBody& body = transactionBody.filecreate(); - - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } - - if (body.has_keys()) - { - mKeys = KeyList::fromProtobuf(body.keys()); - } + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); +} - mContents = internal::Utilities::stringToByteVector(body.contents()); - mFileMemo = body.memo(); +//----- +FileCreateTransaction::FileCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); } //----- @@ -101,20 +94,12 @@ FileCreateTransaction& FileCreateTransaction::setFileMemo(std::string_view memo) } //----- -proto::Transaction FileCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status FileCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status FileCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kFileCreate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kFileCreate, request, deadline, response); } //----- @@ -123,6 +108,32 @@ void FileCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_filecreate(build()); } +//----- +void FileCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_filecreate()) + { + throw std::invalid_argument("Transaction body doesn't contain FileCreate data"); + } + + const proto::FileCreateTransactionBody& body = transactionBody.filecreate(); + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } + + if (body.has_keys()) + { + mKeys = KeyList::fromProtobuf(body.keys()); + } + + mContents = internal::Utilities::stringToByteVector(body.contents()); + mFileMemo = body.memo(); +} + //----- proto::FileCreateTransactionBody* FileCreateTransaction::build() const { diff --git a/sdk/main/src/FileDeleteTransaction.cc b/sdk/main/src/FileDeleteTransaction.cc index cb501decf..f4682d02c 100644 --- a/sdk/main/src/FileDeleteTransaction.cc +++ b/sdk/main/src/FileDeleteTransaction.cc @@ -29,18 +29,17 @@ namespace Hedera { //----- FileDeleteTransaction::FileDeleteTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_filedelete()) - { - throw std::invalid_argument("Transaction body doesn't contain FileDelete data"); - } - - const proto::FileDeleteTransactionBody& body = transactionBody.filedelete(); + initFromSourceTransactionBody(); +} - if (body.has_fileid()) - { - mFileId = FileId::fromProtobuf(body.fileid()); - } +//----- +FileDeleteTransaction::FileDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -52,20 +51,12 @@ FileDeleteTransaction& FileDeleteTransaction::setFileId(const FileId& fileId) } //----- -proto::Transaction FileDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status FileDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status FileDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kFileDelete, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kFileDelete, request, deadline, response); } //----- @@ -74,6 +65,24 @@ void FileDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_filedelete(build()); } +//----- +void FileDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_filedelete()) + { + throw std::invalid_argument("Transaction body doesn't contain FileDelete data"); + } + + const proto::FileDeleteTransactionBody& body = transactionBody.filedelete(); + + if (body.has_fileid()) + { + mFileId = FileId::fromProtobuf(body.fileid()); + } +} + //----- proto::FileDeleteTransactionBody* FileDeleteTransaction::build() const { diff --git a/sdk/main/src/FileInfoQuery.cc b/sdk/main/src/FileInfoQuery.cc index f7dd9b296..81b96c0bb 100644 --- a/sdk/main/src/FileInfoQuery.cc +++ b/sdk/main/src/FileInfoQuery.cc @@ -18,11 +18,7 @@ * */ #include "FileInfoQuery.h" -#include "Client.h" -#include "FileId.h" #include "FileInfo.h" -#include "Status.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -40,47 +36,37 @@ FileInfoQuery& FileInfoQuery::setFileId(const FileId& fileId) } //----- -proto::Query FileInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +FileInfo FileInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::FileGetInfoQuery* getFileInfoQuery = query.mutable_filegetinfo(); - - proto::QueryHeader* header = getFileInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getFileInfoQuery->set_allocated_fileid(mFileId.toProtobuf().release()); - - return query; + return FileInfo::fromProtobuf(response.filegetinfo().fileinfo()); } //----- -FileInfo FileInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status FileInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return FileInfo::fromProtobuf(response.filegetinfo().fileinfo()); + return node->submitQuery(proto::Query::QueryCase::kFileGetInfo, request, deadline, response); } //----- -Status FileInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query FileInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.filegetinfo().header().nodetransactionprecheckcode()); + auto fileGetInfoQuery = std::make_unique(); + fileGetInfoQuery->set_allocated_header(header); + fileGetInfoQuery->set_allocated_fileid(mFileId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_filegetinfo(fileGetInfoQuery.release()); + return query; } //----- -grpc::Status FileInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader FileInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kFileGetInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.filegetinfo().header()); + return response.filegetinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/FileUpdateTransaction.cc b/sdk/main/src/FileUpdateTransaction.cc index 1e3f813ec..94d93ae77 100644 --- a/sdk/main/src/FileUpdateTransaction.cc +++ b/sdk/main/src/FileUpdateTransaction.cc @@ -31,35 +31,17 @@ namespace Hedera { //----- FileUpdateTransaction::FileUpdateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_fileupdate()) - { - throw std::invalid_argument("Transaction body doesn't contain FileUpdate data"); - } - - const proto::FileUpdateTransactionBody& body = transactionBody.fileupdate(); - - if (body.has_fileid()) - { - mFileId = FileId::fromProtobuf(body.fileid()); - } - - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } - - if (body.has_keys()) - { - mKeys = KeyList::fromProtobuf(body.keys()); - } - - mContents = internal::Utilities::stringToByteVector(body.contents()); + initFromSourceTransactionBody(); +} - if (body.has_memo()) - { - mFileMemo = body.memo().value(); - } +//----- +FileUpdateTransaction::FileUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -120,20 +102,12 @@ FileUpdateTransaction& FileUpdateTransaction::setFileMemo(std::string_view memo) } //----- -proto::Transaction FileUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status FileUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status FileUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kFileUpdate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kFileUpdate, request, deadline, response); } //----- @@ -142,6 +116,41 @@ void FileUpdateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_fileupdate(build()); } +//----- +void FileUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_fileupdate()) + { + throw std::invalid_argument("Transaction body doesn't contain FileUpdate data"); + } + + const proto::FileUpdateTransactionBody& body = transactionBody.fileupdate(); + + if (body.has_fileid()) + { + mFileId = FileId::fromProtobuf(body.fileid()); + } + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } + + if (body.has_keys()) + { + mKeys = KeyList::fromProtobuf(body.keys()); + } + + mContents = internal::Utilities::stringToByteVector(body.contents()); + + if (body.has_memo()) + { + mFileMemo = body.memo().value(); + } +} + //----- proto::FileUpdateTransactionBody* FileUpdateTransaction::build() const { diff --git a/sdk/main/src/FreezeTransaction.cc b/sdk/main/src/FreezeTransaction.cc index ee64924d6..a35b3a0fc 100644 --- a/sdk/main/src/FreezeTransaction.cc +++ b/sdk/main/src/FreezeTransaction.cc @@ -31,27 +31,17 @@ namespace Hedera { //----- FreezeTransaction::FreezeTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_freeze()) - { - throw std::invalid_argument("Transaction body doesn't contain Freeze data"); - } - - const proto::FreezeTransactionBody& body = transactionBody.freeze(); - - if (body.has_update_file()) - { - mFileId = FileId::fromProtobuf(body.update_file()); - } - - mFileHash = internal::Utilities::stringToByteVector(body.file_hash()); - - if (body.has_start_time()) - { - mStartTime = internal::TimestampConverter::fromProtobuf(body.start_time()); - } + initFromSourceTransactionBody(); +} - mFreezeType = gProtobufFreezeTypeToFreezeType.at(body.freeze_type()); +//----- +FreezeTransaction::FreezeTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -87,19 +77,12 @@ FreezeTransaction& FreezeTransaction::setFreezeType(const FreezeType& type) } //----- -proto::Transaction FreezeTransaction::makeRequest(const Client& client, const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status FreezeTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status FreezeTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kFreeze, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kFreeze, request, deadline, response); } //----- @@ -108,6 +91,33 @@ void FreezeTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_freeze(build()); } +//----- +void FreezeTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_freeze()) + { + throw std::invalid_argument("Transaction body doesn't contain Freeze data"); + } + + const proto::FreezeTransactionBody& body = transactionBody.freeze(); + + if (body.has_update_file()) + { + mFileId = FileId::fromProtobuf(body.update_file()); + } + + mFileHash = internal::Utilities::stringToByteVector(body.file_hash()); + + if (body.has_start_time()) + { + mStartTime = internal::TimestampConverter::fromProtobuf(body.start_time()); + } + + mFreezeType = gProtobufFreezeTypeToFreezeType.at(body.freeze_type()); +} + //----- proto::FreezeTransactionBody* FreezeTransaction::build() const { diff --git a/sdk/main/src/NetworkVersionInfoQuery.cc b/sdk/main/src/NetworkVersionInfoQuery.cc index 123a2d815..786091bd0 100644 --- a/sdk/main/src/NetworkVersionInfoQuery.cc +++ b/sdk/main/src/NetworkVersionInfoQuery.cc @@ -32,47 +32,36 @@ namespace Hedera { //----- -proto::Query NetworkVersionInfoQuery::makeRequest(const Client& client, - const std::shared_ptr& node) const +NetworkVersionInfo NetworkVersionInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::NetworkGetVersionInfoQuery* getNetworkVersionInfoQuery = query.mutable_networkgetversioninfo(); - - proto::QueryHeader* header = getNetworkVersionInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - return query; + return NetworkVersionInfo::fromProtobuf(response.networkgetversioninfo()); } //----- -NetworkVersionInfo NetworkVersionInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status NetworkVersionInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return NetworkVersionInfo::fromProtobuf(response.networkgetversioninfo()); + return node->submitQuery(proto::Query::QueryCase::kNetworkGetVersionInfo, request, deadline, response); } //----- -Status NetworkVersionInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query NetworkVersionInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.networkgetversioninfo().header().nodetransactionprecheckcode()); + auto networkVersionInfoQuery = std::make_unique(); + networkVersionInfoQuery->set_allocated_header(header); + + proto::Query query; + query.set_allocated_networkgetversioninfo(networkVersionInfoQuery.release()); + return query; } //----- -grpc::Status NetworkVersionInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader NetworkVersionInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kNetworkGetVersionInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.networkgetversioninfo().header()); + return response.networkgetversioninfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/PublicKey.cc b/sdk/main/src/PublicKey.cc index 875d75356..c029bd376 100644 --- a/sdk/main/src/PublicKey.cc +++ b/sdk/main/src/PublicKey.cc @@ -48,6 +48,24 @@ std::unique_ptr PublicKey::fromStringDer(std::string_view key) throw BadKeyException("Key type cannot be determined from input DER-encoded hex string"); } +//----- +std::unique_ptr PublicKey::fromBytes(const std::vector& bytes) +{ + if (bytes.size() == ED25519PublicKey::KEY_SIZE) + { + return ED25519PublicKey::fromBytes(bytes); + } + else if (bytes.size() == ECDSAsecp256k1PublicKey::COMPRESSED_KEY_SIZE || + bytes.size() == ECDSAsecp256k1PublicKey::UNCOMPRESSED_KEY_SIZE) + { + return ECDSAsecp256k1PublicKey::fromBytes(bytes); + } + else + { + return PublicKey::fromBytesDer(bytes); + } +} + //----- std::unique_ptr PublicKey::fromBytesDer(const std::vector& bytes) { @@ -73,7 +91,7 @@ std::unique_ptr PublicKey::fromAliasBytes(const std::vector key = Key::fromProtobuf(protoKey); auto* publicKey = dynamic_cast(key.get())) { - key.release(); + key.release(); // NOLINT return std::unique_ptr(publicKey); } else diff --git a/sdk/main/src/Query.cc b/sdk/main/src/Query.cc index 1066d6968..93fef51ef 100644 --- a/sdk/main/src/Query.cc +++ b/sdk/main/src/Query.cc @@ -20,9 +20,13 @@ #include "Query.h" #include "AccountBalance.h" #include "AccountBalanceQuery.h" +#include "AccountInfo.h" +#include "AccountInfoQuery.h" #include "AccountRecords.h" #include "AccountRecordsQuery.h" #include "AccountStakersQuery.h" +#include "Client.h" +#include "ContractByteCodeQuery.h" #include "ContractCallQuery.h" #include "ContractFunctionResult.h" #include "ContractInfo.h" @@ -30,29 +34,247 @@ #include "FileContentsQuery.h" #include "FileInfo.h" #include "FileInfoQuery.h" +#include "Hbar.h" #include "NetworkVersionInfo.h" #include "NetworkVersionInfoQuery.h" #include "ScheduleInfo.h" #include "ScheduleInfoQuery.h" +#include "Status.h" #include "TokenInfo.h" #include "TokenInfoQuery.h" #include "TokenNftInfo.h" #include "TokenNftInfoQuery.h" #include "TopicInfo.h" #include "TopicInfoQuery.h" +#include "TransactionId.h" #include "TransactionReceipt.h" #include "TransactionReceiptQuery.h" #include "TransactionRecord.h" #include "TransactionRecordQuery.h" +#include "TransferTransaction.h" +#include "exceptions/MaxQueryPaymentExceededException.h" +#include "exceptions/UninitializedException.h" +#include "impl/Network.h" + +#include +#include +#include +#include namespace Hedera { +//----- +template +struct Query::QueryImpl +{ + // The explicit amount to pay for this Query. + std::optional mPayment; + + // The maximum amount to pay for this Query. + std::optional mMaxPayment; + + // Is this Query meant to get the cost? + bool mGetCost = false; + + // The cost to execute this Query. + Hbar mCost; + + // The Client that should be used to pay for the payment transaction of this Query. + const Client* mClient = nullptr; +}; + +//----- +template +SdkRequestType& Query::setQueryPayment(const Hbar& amount) +{ + mImpl->mPayment = amount; + return static_cast(*this); +} + +//----- +template +SdkRequestType& Query::setMaxQueryPayment(const Hbar& maxAmount) +{ + mImpl->mMaxPayment = maxAmount; + return static_cast(*this); +} + +//----- +template +Hbar Query::getCost(const Client& client) +{ + return getCost(client, client.getRequestTimeout()); +} + +//----- +template +Hbar Query::getCost(const Client& client, const std::chrono::duration& timeout) +{ + mImpl->mGetCost = true; + Executable::execute(client, timeout); + mImpl->mGetCost = false; + + return mImpl->mCost; +} + +//----- +template +void Query::saveCostFromHeader(const proto::ResponseHeader& header) const +{ + if (mImpl->mGetCost) + { + mImpl->mCost = Hbar(static_cast(header.cost()), HbarUnit::TINYBAR()); + } +} + +//----- +template +bool Query::isCostQuery() const +{ + return mImpl->mGetCost; +} + +//----- +template +Query::Query() + : mImpl(std::make_unique()) +{ +} + +//----- +template +Query::~Query() = default; + +//----- +template +Query::Query(const Query& other) + : mImpl(std::make_unique(*other.mImpl)) +{ +} + +//----- +template +Query& Query::operator=( + const Query& other) +{ + if (this != &other) + { + mImpl = std::make_unique(*other.mImpl); + } + + return *this; +} + +//----- +template +Query::Query(Query&& other) noexcept + : mImpl(std::move(other.mImpl)) +{ + // Leave moved-from object in a valid state. + other.mImpl = std::make_unique(); +} + +//----- +template +Query& Query::operator=( + Query&& other) noexcept +{ + if (this != &other) + { + mImpl = std::move(other.mImpl); + + // Leave moved-from object in a valid state. + other.mImpl = std::make_unique(); + } + + return *this; +} + +//----- +template +proto::Query Query::makeRequest(unsigned int index) const +{ + auto header = std::make_unique(); + + if (isPaymentRequired() && !mImpl->mGetCost) + { + // Get the node account ID for this index. + const AccountId accountId = + Executable::getNodeAccountIds().at(index); + + header->set_allocated_payment( + std::make_unique( + TransferTransaction() + .setTransactionId(TransactionId::generate(mImpl->mClient->getOperatorAccountId().value())) + .setNodeAccountIds({ accountId }) + .addHbarTransfer(mImpl->mClient->getOperatorAccountId().value(), mImpl->mCost.negated()) + .addHbarTransfer(accountId, mImpl->mCost) + .freeze() + .signWith(mImpl->mClient->getOperatorPublicKey(), mImpl->mClient->getOperatorSigner()) + // There's only one node account ID, therefore only one Transaction protobuf object will be created, and that + // will be put in the 0th index. + .makeRequest(0U)) + .release()); + } + + header->set_responsetype(mImpl->mGetCost ? proto::ResponseType::COST_ANSWER : proto::ResponseType::ANSWER_ONLY); + return buildRequest(header.release()); +} + +//----- +template +Status Query::mapResponseStatus(const proto::Response& response) const +{ + return gProtobufResponseCodeToStatus.at(mapResponseHeader(response).nodetransactionprecheckcode()); +} + +//----- +template +void Query::onExecute(const Client& client) +{ + // Set the node IDs if none have been manually set. + if (Executable::getNodeAccountIds().empty()) + { + // Make sure the client has a valid network. + if (!client.getNetwork()) + { + throw UninitializedException("Client has not been initialized with a valid network"); + } + + // Have the Client's network generate the node account IDs to which to send this Transaction. + Executable::setNodeAccountIds( + client.getNetwork()->getNodeAccountIdsForExecute()); + } + + // There's nothing else to do if this Query is free or is meant to get the cost. + if (!isPaymentRequired() || mImpl->mGetCost) + { + return; + } + + // Save the Client for use later to generate payment Transaction protobuf objects. + mImpl->mClient = &client; + + // Get the cost and make sure it's willing to be paid. + mImpl->mCost = getCost(client); + if (mImpl->mCost.toTinybars() > ((mImpl->mMaxPayment.has_value()) ? mImpl->mMaxPayment->toTinybars() + : ((client.getMaxQueryPayment().has_value()) + ? client.getMaxQueryPayment()->toTinybars() + : DEFAULT_MAX_QUERY_PAYMENT.toTinybars()))) + { + throw MaxQueryPaymentExceededException("Cost to execute Query (" + std::to_string(mImpl->mCost.toTinybars()) + + HbarUnit::TINYBAR().getSymbol() + ") is larger than allowed amount."); + } +} + /** * Explicit template instantiations. */ template class Query; +template class Query; template class Query; template class Query; +template class Query; template class Query; template class Query; template class Query; diff --git a/sdk/main/src/ScheduleCreateTransaction.cc b/sdk/main/src/ScheduleCreateTransaction.cc index 34a050c7a..663afda81 100644 --- a/sdk/main/src/ScheduleCreateTransaction.cc +++ b/sdk/main/src/ScheduleCreateTransaction.cc @@ -55,8 +55,10 @@ struct ScheduleCreateTransaction::ScheduleCreateTransactionImpl //----- ScheduleCreateTransaction::ScheduleCreateTransaction() + : Transaction() + , mImpl(std::make_unique()) { - initImpl(); + setDefaultMaxTransactionFee(Hbar(5LL)); } //----- @@ -64,7 +66,8 @@ ScheduleCreateTransaction::~ScheduleCreateTransaction() = default; //----- ScheduleCreateTransaction::ScheduleCreateTransaction(const ScheduleCreateTransaction& other) - : mImpl(std::make_unique(*other.mImpl)) + : Transaction(other) + , mImpl(std::make_unique(*other.mImpl)) { } @@ -73,6 +76,7 @@ ScheduleCreateTransaction& ScheduleCreateTransaction::operator=(const ScheduleCr { if (this != &other) { + Transaction::operator=(other); mImpl = std::make_unique(*other.mImpl); } @@ -81,10 +85,11 @@ ScheduleCreateTransaction& ScheduleCreateTransaction::operator=(const ScheduleCr //----- ScheduleCreateTransaction::ScheduleCreateTransaction(ScheduleCreateTransaction&& other) noexcept - : mImpl(std::move(other.mImpl)) + : Transaction(std::move(other)) + , mImpl(std::move(other.mImpl)) // NOLINT { // Leave the moved-from ScheduleCreateTransaction in a valid state. - other.mImpl = std::make_unique(); + other.mImpl = std::make_unique(); // NOLINT } //----- @@ -92,7 +97,8 @@ ScheduleCreateTransaction& ScheduleCreateTransaction::operator=(ScheduleCreateTr { if (this != &other) { - mImpl = std::make_unique(*other.mImpl); + Transaction::operator=(std::move(other)); + mImpl = std::move(other.mImpl); // NOLINT // Leave the moved-from ScheduleCreateTransaction in a valid state. other.mImpl = std::make_unique(); @@ -104,39 +110,20 @@ ScheduleCreateTransaction& ScheduleCreateTransaction::operator=(ScheduleCreateTr //----- ScheduleCreateTransaction::ScheduleCreateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) + , mImpl(std::make_unique()) { - initImpl(); - - if (!transactionBody.has_schedulecreate()) - { - throw std::invalid_argument("Transaction body doesn't contain ScheduleCreate data"); - } - - const proto::ScheduleCreateTransactionBody& body = transactionBody.schedulecreate(); - - if (body.has_scheduledtransactionbody()) - { - mImpl->mTransactionToSchedule = WrappedTransaction::fromProtobuf(body.scheduledtransactionbody()); - } - - mImpl->mMemo = body.memo(); - - if (body.has_adminkey()) - { - mImpl->mAdminKey = Key::fromProtobuf(body.adminkey()); - } - - if (body.has_payeraccountid()) - { - mImpl->mPayerAccountId = AccountId::fromProtobuf(body.payeraccountid()); - } - - if (body.has_expiration_time()) - { - mImpl->mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiration_time()); - } + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); +} - mImpl->mWaitForExpiration = body.wait_for_expiry(); +//----- +ScheduleCreateTransaction::ScheduleCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) + , mImpl(std::make_unique()) +{ + setDefaultMaxTransactionFee(Hbar(5LL)); + initFromSourceTransactionBody(); } //----- @@ -225,20 +212,12 @@ bool ScheduleCreateTransaction::isWaitForExpiry() const } //----- -proto::Transaction ScheduleCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ScheduleCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ScheduleCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kScheduleCreate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kScheduleCreate, request, deadline, response); } //----- @@ -247,11 +226,48 @@ void ScheduleCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_schedulecreate(build()); } +//----- +void ScheduleCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_schedulecreate()) + { + throw std::invalid_argument("Transaction body doesn't contain ScheduleCreate data"); + } + + const proto::ScheduleCreateTransactionBody& body = transactionBody.schedulecreate(); + + if (body.has_scheduledtransactionbody()) + { + mImpl->mTransactionToSchedule = WrappedTransaction::fromProtobuf(body.scheduledtransactionbody()); + } + + mImpl->mMemo = body.memo(); + + if (body.has_adminkey()) + { + mImpl->mAdminKey = Key::fromProtobuf(body.adminkey()); + } + + if (body.has_payeraccountid()) + { + mImpl->mPayerAccountId = AccountId::fromProtobuf(body.payeraccountid()); + } + + if (body.has_expiration_time()) + { + mImpl->mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiration_time()); + } + + mImpl->mWaitForExpiration = body.wait_for_expiry(); +} + //----- proto::ScheduleCreateTransactionBody* ScheduleCreateTransaction::build() const { auto body = std::make_unique(); - + body->set_allocated_scheduledtransactionbody(mImpl->mTransactionToSchedule.toSchedulableProtobuf().release()); body->set_memo(mImpl->mMemo); @@ -275,10 +291,4 @@ proto::ScheduleCreateTransactionBody* ScheduleCreateTransaction::build() const return body.release(); } -//----- -void ScheduleCreateTransaction::initImpl() -{ - mImpl = std::make_unique(); -} - } // namespace Hedera diff --git a/sdk/main/src/ScheduleDeleteTransaction.cc b/sdk/main/src/ScheduleDeleteTransaction.cc index 58569b953..46338f360 100644 --- a/sdk/main/src/ScheduleDeleteTransaction.cc +++ b/sdk/main/src/ScheduleDeleteTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera ScheduleDeleteTransaction::ScheduleDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_scheduledelete()) - { - throw std::invalid_argument("Transaction body doesn't contain ScheduleDelete data"); - } - - const proto::ScheduleDeleteTransactionBody& body = transactionBody.scheduledelete(); + initFromSourceTransactionBody(); +} - if (body.has_scheduleid()) - { - mScheduleId = ScheduleId::fromProtobuf(body.scheduleid()); - } +//----- +ScheduleDeleteTransaction::ScheduleDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -53,20 +51,12 @@ ScheduleDeleteTransaction& ScheduleDeleteTransaction::setScheduleId(const Schedu } //----- -proto::Transaction ScheduleDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ScheduleDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ScheduleDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kScheduleDelete, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kScheduleDelete, request, deadline, response); } //----- @@ -75,6 +65,24 @@ void ScheduleDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_scheduledelete(build()); } +//----- +void ScheduleDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_scheduledelete()) + { + throw std::invalid_argument("Transaction body doesn't contain ScheduleDelete data"); + } + + const proto::ScheduleDeleteTransactionBody& body = transactionBody.scheduledelete(); + + if (body.has_scheduleid()) + { + mScheduleId = ScheduleId::fromProtobuf(body.scheduleid()); + } +} + //----- proto::ScheduleDeleteTransactionBody* ScheduleDeleteTransaction::build() const { diff --git a/sdk/main/src/ScheduleInfoQuery.cc b/sdk/main/src/ScheduleInfoQuery.cc index 55601a39a..3df0c5e11 100644 --- a/sdk/main/src/ScheduleInfoQuery.cc +++ b/sdk/main/src/ScheduleInfoQuery.cc @@ -18,10 +18,7 @@ * */ #include "ScheduleInfoQuery.h" -#include "Client.h" #include "ScheduleInfo.h" -#include "TransactionRecord.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -39,47 +36,37 @@ ScheduleInfoQuery& ScheduleInfoQuery::setScheduleId(const ScheduleId& scheduleId } //----- -proto::Query ScheduleInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +ScheduleInfo ScheduleInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::ScheduleGetInfoQuery* getScheduleInfoQuery = query.mutable_schedulegetinfo(); - - proto::QueryHeader* header = getScheduleInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getScheduleInfoQuery->set_allocated_scheduleid(mScheduleId.toProtobuf().release()); - - return query; + return ScheduleInfo::fromProtobuf(response.schedulegetinfo().scheduleinfo()); } //----- -ScheduleInfo ScheduleInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status ScheduleInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return ScheduleInfo::fromProtobuf(response.schedulegetinfo().scheduleinfo()); + return node->submitQuery(proto::Query::QueryCase::kScheduleGetInfo, request, deadline, response); } //----- -Status ScheduleInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query ScheduleInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.schedulegetinfo().header().nodetransactionprecheckcode()); + auto scheduleGetInfoQuery = std::make_unique(); + scheduleGetInfoQuery->set_allocated_header(header); + scheduleGetInfoQuery->set_allocated_scheduleid(mScheduleId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_schedulegetinfo(scheduleGetInfoQuery.release()); + return query; } //----- -grpc::Status ScheduleInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader ScheduleInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kScheduleGetInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.schedulegetinfo().header()); + return response.schedulegetinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/ScheduleSignTransaction.cc b/sdk/main/src/ScheduleSignTransaction.cc index d4b835882..b31e9b9c6 100644 --- a/sdk/main/src/ScheduleSignTransaction.cc +++ b/sdk/main/src/ScheduleSignTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera ScheduleSignTransaction::ScheduleSignTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_schedulesign()) - { - throw std::invalid_argument("Transaction body doesn't contain ScheduleSign data"); - } - - const proto::ScheduleSignTransactionBody& body = transactionBody.schedulesign(); + initFromSourceTransactionBody(); +} - if (body.has_scheduleid()) - { - mScheduleId = ScheduleId::fromProtobuf(body.scheduleid()); - } +//----- +ScheduleSignTransaction::ScheduleSignTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -61,20 +59,12 @@ ScheduleSignTransaction& ScheduleSignTransaction::clearScheduleId() } //----- -proto::Transaction ScheduleSignTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status ScheduleSignTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status ScheduleSignTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kScheduleSign, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kScheduleSign, request, deadline, response); } //----- @@ -83,6 +73,24 @@ void ScheduleSignTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_schedulesign(build()); } +//----- +void ScheduleSignTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_schedulesign()) + { + throw std::invalid_argument("Transaction body doesn't contain ScheduleSign data"); + } + + const proto::ScheduleSignTransactionBody& body = transactionBody.schedulesign(); + + if (body.has_scheduleid()) + { + mScheduleId = ScheduleId::fromProtobuf(body.scheduleid()); + } +} + //----- proto::ScheduleSignTransactionBody* ScheduleSignTransaction::build() const { diff --git a/sdk/main/src/SystemDeleteTransaction.cc b/sdk/main/src/SystemDeleteTransaction.cc index a93fca414..167f33d1c 100644 --- a/sdk/main/src/SystemDeleteTransaction.cc +++ b/sdk/main/src/SystemDeleteTransaction.cc @@ -32,26 +32,15 @@ namespace Hedera SystemDeleteTransaction::SystemDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_systemdelete()) - { - throw std::invalid_argument("Transaction body doesn't contain SystemDelete data"); - } - - const proto::SystemDeleteTransactionBody& body = transactionBody.systemdelete(); - - if (body.has_fileid()) - { - mFileId = FileId::fromProtobuf(body.fileid()); - } - else if (body.has_contractid()) - { - mContractId = ContractId::fromProtobuf(body.contractid()); - } + initFromSourceTransactionBody(); +} - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } +//----- +SystemDeleteTransaction::SystemDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -82,20 +71,12 @@ SystemDeleteTransaction& SystemDeleteTransaction::setExpirationTime( } //----- -proto::Transaction SystemDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status SystemDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status SystemDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kSystemDelete, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kSystemDelete, request, deadline, response); } //----- @@ -104,6 +85,33 @@ void SystemDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_systemdelete(build()); } +//----- +void SystemDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_systemdelete()) + { + throw std::invalid_argument("Transaction body doesn't contain SystemDelete data"); + } + + const proto::SystemDeleteTransactionBody& body = transactionBody.systemdelete(); + + if (body.has_fileid()) + { + mFileId = FileId::fromProtobuf(body.fileid()); + } + else if (body.has_contractid()) + { + mContractId = ContractId::fromProtobuf(body.contractid()); + } + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } +} + //----- proto::SystemDeleteTransactionBody* SystemDeleteTransaction::build() const { diff --git a/sdk/main/src/SystemUndeleteTransaction.cc b/sdk/main/src/SystemUndeleteTransaction.cc index a295a6b34..08ed8015f 100644 --- a/sdk/main/src/SystemUndeleteTransaction.cc +++ b/sdk/main/src/SystemUndeleteTransaction.cc @@ -32,21 +32,15 @@ namespace Hedera SystemUndeleteTransaction::SystemUndeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_systemundelete()) - { - throw std::invalid_argument("Transaction body doesn't contain SystemUndelete data"); - } - - const proto::SystemUndeleteTransactionBody& body = transactionBody.systemundelete(); + initFromSourceTransactionBody(); +} - if (body.has_fileid()) - { - mFileId = FileId::fromProtobuf(body.fileid()); - } - else if (body.has_contractid()) - { - mContractId = ContractId::fromProtobuf(body.contractid()); - } +//----- +SystemUndeleteTransaction::SystemUndeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -68,20 +62,12 @@ SystemUndeleteTransaction& SystemUndeleteTransaction::setContractId(const Contra } //----- -proto::Transaction SystemUndeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status SystemUndeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status SystemUndeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kSystemUndelete, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kSystemUndelete, request, deadline, response); } //----- @@ -90,6 +76,28 @@ void SystemUndeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_systemundelete(build()); } +//----- +void SystemUndeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_systemundelete()) + { + throw std::invalid_argument("Transaction body doesn't contain SystemUndelete data"); + } + + const proto::SystemUndeleteTransactionBody& body = transactionBody.systemundelete(); + + if (body.has_fileid()) + { + mFileId = FileId::fromProtobuf(body.fileid()); + } + else if (body.has_contractid()) + { + mContractId = ContractId::fromProtobuf(body.contractid()); + } +} + //----- proto::SystemUndeleteTransactionBody* SystemUndeleteTransaction::build() const { diff --git a/sdk/main/src/TokenAssociateTransaction.cc b/sdk/main/src/TokenAssociateTransaction.cc index fbf6a7f7d..8125a8e05 100644 --- a/sdk/main/src/TokenAssociateTransaction.cc +++ b/sdk/main/src/TokenAssociateTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenAssociateTransaction::TokenAssociateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenassociate()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenAssociate data"); - } - - const proto::TokenAssociateTransactionBody& body = transactionBody.tokenassociate(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.tokens_size(); ++i) - { - mTokenIds.push_back(TokenId::fromProtobuf(body.tokens(i))); - } +//----- +TokenAssociateTransaction::TokenAssociateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenAssociateTransaction& TokenAssociateTransaction::setTokenIds(const std::vec } //----- -proto::Transaction TokenAssociateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenAssociateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenAssociateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenAssociate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenAssociate, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenAssociateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenassociate(build()); } +//----- +void TokenAssociateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenassociate()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenAssociate data"); + } + + const proto::TokenAssociateTransactionBody& body = transactionBody.tokenassociate(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + for (int i = 0; i < body.tokens_size(); ++i) + { + mTokenIds.push_back(TokenId::fromProtobuf(body.tokens(i))); + } +} + //----- proto::TokenAssociateTransactionBody* TokenAssociateTransaction::build() const { diff --git a/sdk/main/src/TokenBurnTransaction.cc b/sdk/main/src/TokenBurnTransaction.cc index 25eb04cf5..44f18ca70 100644 --- a/sdk/main/src/TokenBurnTransaction.cc +++ b/sdk/main/src/TokenBurnTransaction.cc @@ -31,24 +31,15 @@ namespace Hedera TokenBurnTransaction::TokenBurnTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenburn()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenBurn data"); - } - - const proto::TokenBurnTransactionBody& body = transactionBody.tokenburn(); - - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } - - mAmount = body.amount(); + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.serialnumbers_size(); ++i) - { - mSerialNumbers.push_back(static_cast(body.serialnumbers(i))); - } +//----- +TokenBurnTransaction::TokenBurnTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -76,19 +67,12 @@ TokenBurnTransaction& TokenBurnTransaction::setSerialNumbers(const std::vector&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenBurnTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenBurnTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenBurn, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenBurn, request, deadline, response); } //----- @@ -97,6 +81,31 @@ void TokenBurnTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenburn(build()); } +//----- +void TokenBurnTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenburn()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenBurn data"); + } + + const proto::TokenBurnTransactionBody& body = transactionBody.tokenburn(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } + + mAmount = body.amount(); + + for (int i = 0; i < body.serialnumbers_size(); ++i) + { + mSerialNumbers.push_back(static_cast(body.serialnumbers(i))); + } +} + //----- proto::TokenBurnTransactionBody* TokenBurnTransaction::build() const { diff --git a/sdk/main/src/TokenCreateTransaction.cc b/sdk/main/src/TokenCreateTransaction.cc index 666179493..200f37230 100644 --- a/sdk/main/src/TokenCreateTransaction.cc +++ b/sdk/main/src/TokenCreateTransaction.cc @@ -34,90 +34,24 @@ namespace Hedera //----- TokenCreateTransaction::TokenCreateTransaction() { - setMaxTransactionFee(Hbar(50LL)); + setDefaultMaxTransactionFee(Hbar(40LL)); } //----- TokenCreateTransaction::TokenCreateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_tokencreation()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenCreate data"); - } - - const proto::TokenCreateTransactionBody& body = transactionBody.tokencreation(); - - mTokenName = body.name(); - mTokenSymbol = body.symbol(); - mDecimals = body.decimals(); - mInitialSupply = body.initialsupply(); - - if (body.has_treasury()) - { - mTreasuryAccountId = AccountId::fromProtobuf(body.treasury()); - } - - if (body.has_adminkey()) - { - mAdminKey = Key::fromProtobuf(body.adminkey()); - } - - if (body.has_kyckey()) - { - mKycKey = Key::fromProtobuf(body.kyckey()); - } - - if (body.has_freezekey()) - { - mFreezeKey = Key::fromProtobuf(body.freezekey()); - } - - if (body.has_wipekey()) - { - mWipeKey = Key::fromProtobuf(body.wipekey()); - } - - if (body.has_supplykey()) - { - mSupplyKey = Key::fromProtobuf(body.supplykey()); - } - - mFreezeDefault = body.freezedefault(); - - if (body.has_expiry()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiry()); - } - - if (body.has_autorenewaccount()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - mTokenMemo = body.memo(); - mTokenType = gProtobufTokenTypeToTokenType.at(body.tokentype()); - mSupplyType = gProtobufTokenSupplyTypeToTokenSupplyType.at(body.supplytype()); - mMaxSupply = static_cast(body.maxsupply()); - - if (body.has_fee_schedule_key()) - { - mFeeScheduleKey = Key::fromProtobuf(body.fee_schedule_key()); - } - - for (int i = 0; i < body.custom_fees_size(); ++i) - { - mCustomFees.push_back(CustomFee::fromProtobuf(body.custom_fees(i))); - } + setDefaultMaxTransactionFee(Hbar(40LL)); + initFromSourceTransactionBody(); +} - if (body.has_pause_key()) - { - mPauseKey = Key::fromProtobuf(body.pause_key()); - } +//----- +TokenCreateTransaction::TokenCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + setDefaultMaxTransactionFee(Hbar(40LL)); + initFromSourceTransactionBody(); } //----- @@ -290,20 +224,12 @@ TokenCreateTransaction& TokenCreateTransaction::setPauseKey(const std::shared_pt } //----- -proto::Transaction TokenCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenCreation, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenCreation, request, deadline, response); } //----- @@ -312,6 +238,91 @@ void TokenCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokencreation(build()); } +//----- +void TokenCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokencreation()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenCreate data"); + } + + const proto::TokenCreateTransactionBody& body = transactionBody.tokencreation(); + + mTokenName = body.name(); + mTokenSymbol = body.symbol(); + mDecimals = body.decimals(); + mInitialSupply = body.initialsupply(); + + if (body.has_treasury()) + { + mTreasuryAccountId = AccountId::fromProtobuf(body.treasury()); + } + + if (body.has_adminkey()) + { + mAdminKey = Key::fromProtobuf(body.adminkey()); + } + + if (body.has_kyckey()) + { + mKycKey = Key::fromProtobuf(body.kyckey()); + } + + if (body.has_freezekey()) + { + mFreezeKey = Key::fromProtobuf(body.freezekey()); + } + + if (body.has_wipekey()) + { + mWipeKey = Key::fromProtobuf(body.wipekey()); + } + + if (body.has_supplykey()) + { + mSupplyKey = Key::fromProtobuf(body.supplykey()); + } + + mFreezeDefault = body.freezedefault(); + + if (body.has_expiry()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiry()); + } + + if (body.has_autorenewaccount()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + mTokenMemo = body.memo(); + mTokenType = gProtobufTokenTypeToTokenType.at(body.tokentype()); + mSupplyType = gProtobufTokenSupplyTypeToTokenSupplyType.at(body.supplytype()); + mMaxSupply = static_cast(body.maxsupply()); + + if (body.has_fee_schedule_key()) + { + mFeeScheduleKey = Key::fromProtobuf(body.fee_schedule_key()); + } + + for (int i = 0; i < body.custom_fees_size(); ++i) + { + mCustomFees.push_back(CustomFee::fromProtobuf(body.custom_fees(i))); + } + + if (body.has_pause_key()) + { + mPauseKey = Key::fromProtobuf(body.pause_key()); + } +} + //----- proto::TokenCreateTransactionBody* TokenCreateTransaction::build() const { diff --git a/sdk/main/src/TokenDeleteTransaction.cc b/sdk/main/src/TokenDeleteTransaction.cc index 89db7ff9a..443b623c6 100644 --- a/sdk/main/src/TokenDeleteTransaction.cc +++ b/sdk/main/src/TokenDeleteTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera TokenDeleteTransaction::TokenDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokendeletion()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenDelete data"); - } - - const proto::TokenDeleteTransactionBody& body = transactionBody.tokendeletion(); + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenDeleteTransaction::TokenDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -53,20 +51,12 @@ TokenDeleteTransaction& TokenDeleteTransaction::setTokenId(const TokenId& tokenI } //----- -proto::Transaction TokenDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenDeletion, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenDeletion, request, deadline, response); } //----- @@ -75,6 +65,24 @@ void TokenDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokendeletion(build()); } +//----- +void TokenDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokendeletion()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenDelete data"); + } + + const proto::TokenDeleteTransactionBody& body = transactionBody.tokendeletion(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenDeleteTransactionBody* TokenDeleteTransaction::build() const { diff --git a/sdk/main/src/TokenDissociateTransaction.cc b/sdk/main/src/TokenDissociateTransaction.cc index 2777aa923..ba4208016 100644 --- a/sdk/main/src/TokenDissociateTransaction.cc +++ b/sdk/main/src/TokenDissociateTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenDissociateTransaction::TokenDissociateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokendissociate()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenDissociate data"); - } - - const proto::TokenDissociateTransactionBody& body = transactionBody.tokendissociate(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.tokens_size(); ++i) - { - mTokenIds.push_back(TokenId::fromProtobuf(body.tokens(i))); - } +//----- +TokenDissociateTransaction::TokenDissociateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenDissociateTransaction& TokenDissociateTransaction::setTokenIds(const std::v } //----- -proto::Transaction TokenDissociateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenDissociateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenDissociateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenDissociate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenDissociate, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenDissociateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokendissociate(build()); } +//----- +void TokenDissociateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokendissociate()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenDissociate data"); + } + + const proto::TokenDissociateTransactionBody& body = transactionBody.tokendissociate(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + for (int i = 0; i < body.tokens_size(); ++i) + { + mTokenIds.push_back(TokenId::fromProtobuf(body.tokens(i))); + } +} + //----- proto::TokenDissociateTransactionBody* TokenDissociateTransaction::build() const { diff --git a/sdk/main/src/TokenFeeScheduleUpdateTransaction.cc b/sdk/main/src/TokenFeeScheduleUpdateTransaction.cc index dfdc3d2ea..a685e29e2 100644 --- a/sdk/main/src/TokenFeeScheduleUpdateTransaction.cc +++ b/sdk/main/src/TokenFeeScheduleUpdateTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenFeeScheduleUpdateTransaction::TokenFeeScheduleUpdateTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_token_fee_schedule_update()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenFeeScheduleUpdate data"); - } - - const proto::TokenFeeScheduleUpdateTransactionBody& body = transactionBody.token_fee_schedule_update(); - - if (body.has_token_id()) - { - mTokenId = TokenId::fromProtobuf(body.token_id()); - } + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.custom_fees_size(); ++i) - { - mCustomFees.push_back(CustomFee::fromProtobuf(body.custom_fees(i))); - } +//----- +TokenFeeScheduleUpdateTransaction::TokenFeeScheduleUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -67,20 +60,13 @@ TokenFeeScheduleUpdateTransaction& TokenFeeScheduleUpdateTransaction::setCustomF } //----- -proto::Transaction TokenFeeScheduleUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenFeeScheduleUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenFeeScheduleUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenFeeScheduleUpdate, makeRequest(client, node), deadline, response); + proto::TransactionBody::DataCase::kTokenFeeScheduleUpdate, request, deadline, response); } //----- @@ -89,6 +75,29 @@ void TokenFeeScheduleUpdateTransaction::addToBody(proto::TransactionBody& body) body.set_allocated_token_fee_schedule_update(build()); } +//----- +void TokenFeeScheduleUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_token_fee_schedule_update()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenFeeScheduleUpdate data"); + } + + const proto::TokenFeeScheduleUpdateTransactionBody& body = transactionBody.token_fee_schedule_update(); + + if (body.has_token_id()) + { + mTokenId = TokenId::fromProtobuf(body.token_id()); + } + + for (int i = 0; i < body.custom_fees_size(); ++i) + { + mCustomFees.push_back(CustomFee::fromProtobuf(body.custom_fees(i))); + } +} + //----- proto::TokenFeeScheduleUpdateTransactionBody* TokenFeeScheduleUpdateTransaction::build() const { diff --git a/sdk/main/src/TokenFreezeTransaction.cc b/sdk/main/src/TokenFreezeTransaction.cc index 2c1606747..721c4a318 100644 --- a/sdk/main/src/TokenFreezeTransaction.cc +++ b/sdk/main/src/TokenFreezeTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenFreezeTransaction::TokenFreezeTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenfreeze()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenFreeze data"); - } - - const proto::TokenFreezeAccountTransactionBody& body = transactionBody.tokenfreeze(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenFreezeTransaction::TokenFreezeTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenFreezeTransaction& TokenFreezeTransaction::setTokenId(const TokenId& tokenI } //----- -proto::Transaction TokenFreezeTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenFreezeTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenFreezeTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenFreeze, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenFreeze, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenFreezeTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenfreeze(build()); } +//----- +void TokenFreezeTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenfreeze()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenFreeze data"); + } + + const proto::TokenFreezeAccountTransactionBody& body = transactionBody.tokenfreeze(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenFreezeAccountTransactionBody* TokenFreezeTransaction::build() const { diff --git a/sdk/main/src/TokenGrantKycTransaction.cc b/sdk/main/src/TokenGrantKycTransaction.cc index e99021fe3..91a260300 100644 --- a/sdk/main/src/TokenGrantKycTransaction.cc +++ b/sdk/main/src/TokenGrantKycTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenGrantKycTransaction::TokenGrantKycTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokengrantkyc()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenGrantKyc data"); - } - - const proto::TokenGrantKycTransactionBody& body = transactionBody.tokengrantkyc(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenGrantKycTransaction::TokenGrantKycTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenGrantKycTransaction& TokenGrantKycTransaction::setTokenId(const TokenId& to } //----- -proto::Transaction TokenGrantKycTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenGrantKycTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenGrantKycTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenGrantKyc, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenGrantKyc, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenGrantKycTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokengrantkyc(build()); } +//----- +void TokenGrantKycTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokengrantkyc()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenGrantKyc data"); + } + + const proto::TokenGrantKycTransactionBody& body = transactionBody.tokengrantkyc(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenGrantKycTransactionBody* TokenGrantKycTransaction::build() const { diff --git a/sdk/main/src/TokenInfoQuery.cc b/sdk/main/src/TokenInfoQuery.cc index 325c5a380..2be359bcb 100644 --- a/sdk/main/src/TokenInfoQuery.cc +++ b/sdk/main/src/TokenInfoQuery.cc @@ -18,10 +18,7 @@ * */ #include "TokenInfoQuery.h" -#include "Client.h" #include "TokenInfo.h" -#include "TransactionRecord.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -39,47 +36,37 @@ TokenInfoQuery& TokenInfoQuery::setTokenId(const TokenId& tokenId) } //----- -proto::Query TokenInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +TokenInfo TokenInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::TokenGetInfoQuery* getTokenInfoQuery = query.mutable_tokengetinfo(); - - proto::QueryHeader* header = getTokenInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getTokenInfoQuery->set_allocated_token(mTokenId.toProtobuf().release()); - - return query; + return TokenInfo::fromProtobuf(response.tokengetinfo().tokeninfo()); } //----- -TokenInfo TokenInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status TokenInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return TokenInfo::fromProtobuf(response.tokengetinfo().tokeninfo()); + return node->submitQuery(proto::Query::QueryCase::kTokenGetInfo, request, deadline, response); } //----- -Status TokenInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query TokenInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.tokengetinfo().header().nodetransactionprecheckcode()); + auto tokenGetInfoQuery = std::make_unique(); + tokenGetInfoQuery->set_allocated_header(header); + tokenGetInfoQuery->set_allocated_token(mTokenId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_tokengetinfo(tokenGetInfoQuery.release()); + return query; } //----- -grpc::Status TokenInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader TokenInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kTokenGetInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.tokengetinfo().header()); + return response.tokengetinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/TokenMintTransaction.cc b/sdk/main/src/TokenMintTransaction.cc index 13e190c11..be8db9bc1 100644 --- a/sdk/main/src/TokenMintTransaction.cc +++ b/sdk/main/src/TokenMintTransaction.cc @@ -31,25 +31,17 @@ namespace Hedera { //----- TokenMintTransaction::TokenMintTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_tokenmint()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenMint data"); - } - - const proto::TokenMintTransactionBody& body = transactionBody.tokenmint(); - - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } - - mAmount = body.amount(); + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.metadata_size(); ++i) - { - mMetadataList.push_back(internal::Utilities::stringToByteVector(body.metadata(i))); - } +//----- +TokenMintTransaction::TokenMintTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -85,19 +77,12 @@ TokenMintTransaction& TokenMintTransaction::addMetadata(const std::vector&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenMintTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenMintTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenMint, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenMint, request, deadline, response); } //----- @@ -106,6 +91,31 @@ void TokenMintTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenmint(build()); } +//----- +void TokenMintTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenmint()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenMint data"); + } + + const proto::TokenMintTransactionBody& body = transactionBody.tokenmint(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } + + mAmount = body.amount(); + + for (int i = 0; i < body.metadata_size(); ++i) + { + mMetadataList.push_back(internal::Utilities::stringToByteVector(body.metadata(i))); + } +} + //----- proto::TokenMintTransactionBody* TokenMintTransaction::build() const { diff --git a/sdk/main/src/TokenNftInfoQuery.cc b/sdk/main/src/TokenNftInfoQuery.cc index 34f9b666a..4d4e5fa0f 100644 --- a/sdk/main/src/TokenNftInfoQuery.cc +++ b/sdk/main/src/TokenNftInfoQuery.cc @@ -39,47 +39,37 @@ TokenNftInfoQuery& TokenNftInfoQuery::setNftId(const NftId& nft) } //----- -proto::Query TokenNftInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +TokenNftInfo TokenNftInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::TokenGetNftInfoQuery* getTokenNftInfoQuery = query.mutable_tokengetnftinfo(); - - proto::QueryHeader* header = getTokenNftInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getTokenNftInfoQuery->set_allocated_nftid(mNftId.toProtobuf().release()); - - return query; + return TokenNftInfo::fromProtobuf(response.tokengetnftinfo().nft()); } //----- -TokenNftInfo TokenNftInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status TokenNftInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return TokenNftInfo::fromProtobuf(response.tokengetnftinfo().nft()); + return node->submitQuery(proto::Query::QueryCase::kTokenGetNftInfo, request, deadline, response); } //----- -Status TokenNftInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query TokenNftInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.tokengetnftinfo().header().nodetransactionprecheckcode()); + auto tokenGetNftInfoQuery = std::make_unique(); + tokenGetNftInfoQuery->set_allocated_header(header); + tokenGetNftInfoQuery->set_allocated_nftid(mNftId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_tokengetnftinfo(tokenGetNftInfoQuery.release()); + return query; } //----- -grpc::Status TokenNftInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader TokenNftInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery(proto::Query::QueryCase::kTokenGetNftInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.tokengetnftinfo().header()); + return response.tokengetnftinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/TokenPauseTransaction.cc b/sdk/main/src/TokenPauseTransaction.cc index 8b302d246..f71c1edeb 100644 --- a/sdk/main/src/TokenPauseTransaction.cc +++ b/sdk/main/src/TokenPauseTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera TokenPauseTransaction::TokenPauseTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_token_pause()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenPause data"); - } - - const proto::TokenPauseTransactionBody& body = transactionBody.token_pause(); + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenPauseTransaction::TokenPauseTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -53,20 +51,12 @@ TokenPauseTransaction& TokenPauseTransaction::setTokenId(const TokenId& tokenId) } //----- -proto::Transaction TokenPauseTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenPauseTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenPauseTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenPause, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenPause, request, deadline, response); } //----- @@ -75,6 +65,24 @@ void TokenPauseTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_token_pause(build()); } +//----- +void TokenPauseTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_token_pause()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenPause data"); + } + + const proto::TokenPauseTransactionBody& body = transactionBody.token_pause(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenPauseTransactionBody* TokenPauseTransaction::build() const { diff --git a/sdk/main/src/TokenRevokeKycTransaction.cc b/sdk/main/src/TokenRevokeKycTransaction.cc index 1fe18b6f7..813a2e0c0 100644 --- a/sdk/main/src/TokenRevokeKycTransaction.cc +++ b/sdk/main/src/TokenRevokeKycTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenRevokeKycTransaction::TokenRevokeKycTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenrevokekyc()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenRevokeKyc data"); - } - - const proto::TokenRevokeKycTransactionBody& body = transactionBody.tokenrevokekyc(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenRevokeKycTransaction::TokenRevokeKycTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenRevokeKycTransaction& TokenRevokeKycTransaction::setTokenId(const TokenId& } //----- -proto::Transaction TokenRevokeKycTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenRevokeKycTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenRevokeKycTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenRevokeKyc, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenRevokeKyc, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenRevokeKycTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenrevokekyc(build()); } +//----- +void TokenRevokeKycTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenrevokekyc()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenRevokeKyc data"); + } + + const proto::TokenRevokeKycTransactionBody& body = transactionBody.tokenrevokekyc(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenRevokeKycTransactionBody* TokenRevokeKycTransaction::build() const { diff --git a/sdk/main/src/TokenUnfreezeTransaction.cc b/sdk/main/src/TokenUnfreezeTransaction.cc index 2693f1cdb..04086399e 100644 --- a/sdk/main/src/TokenUnfreezeTransaction.cc +++ b/sdk/main/src/TokenUnfreezeTransaction.cc @@ -31,22 +31,15 @@ namespace Hedera TokenUnfreezeTransaction::TokenUnfreezeTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenunfreeze()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenUnfreeze data"); - } - - const proto::TokenUnfreezeAccountTransactionBody& body = transactionBody.tokenunfreeze(); - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenUnfreezeTransaction::TokenUnfreezeTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -66,20 +59,12 @@ TokenUnfreezeTransaction& TokenUnfreezeTransaction::setTokenId(const TokenId& to } //----- -proto::Transaction TokenUnfreezeTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenUnfreezeTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenUnfreezeTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenUnfreeze, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenUnfreeze, request, deadline, response); } //----- @@ -88,6 +73,29 @@ void TokenUnfreezeTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenunfreeze(build()); } +//----- +void TokenUnfreezeTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenunfreeze()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenUnfreeze data"); + } + + const proto::TokenUnfreezeAccountTransactionBody& body = transactionBody.tokenunfreeze(); + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenUnfreezeAccountTransactionBody* TokenUnfreezeTransaction::build() const { diff --git a/sdk/main/src/TokenUnpauseTransaction.cc b/sdk/main/src/TokenUnpauseTransaction.cc index 7fd9e38ac..9f325de2c 100644 --- a/sdk/main/src/TokenUnpauseTransaction.cc +++ b/sdk/main/src/TokenUnpauseTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera TokenUnpauseTransaction::TokenUnpauseTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_token_unpause()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenUnpause data"); - } - - const proto::TokenUnpauseTransactionBody& body = transactionBody.token_unpause(); + initFromSourceTransactionBody(); +} - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } +//----- +TokenUnpauseTransaction::TokenUnpauseTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -53,20 +51,12 @@ TokenUnpauseTransaction& TokenUnpauseTransaction::setTokenId(const TokenId& toke } //----- -proto::Transaction TokenUnpauseTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenUnpauseTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenUnpauseTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenUnpause, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenUnpause, request, deadline, response); } //----- @@ -75,6 +65,24 @@ void TokenUnpauseTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_token_unpause(build()); } +//----- +void TokenUnpauseTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_token_unpause()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenUnpause data"); + } + + const proto::TokenUnpauseTransactionBody& body = transactionBody.token_unpause(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } +} + //----- proto::TokenUnpauseTransactionBody* TokenUnpauseTransaction::build() const { diff --git a/sdk/main/src/TokenUpdateTransaction.cc b/sdk/main/src/TokenUpdateTransaction.cc index 8386a47d0..a63614821 100644 --- a/sdk/main/src/TokenUpdateTransaction.cc +++ b/sdk/main/src/TokenUpdateTransaction.cc @@ -32,81 +32,17 @@ namespace Hedera { //----- TokenUpdateTransaction::TokenUpdateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_tokenupdate()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenUpdate data"); - } - - const proto::TokenUpdateTransactionBody& body = transactionBody.tokenupdate(); - - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } - - mTokenName = body.name(); - mTokenSymbol = body.symbol(); - - if (body.has_treasury()) - { - mTreasuryAccountId = AccountId::fromProtobuf(body.treasury()); - } - - if (body.has_adminkey()) - { - mAdminKey = Key::fromProtobuf(body.adminkey()); - } - - if (body.has_kyckey()) - { - mKycKey = Key::fromProtobuf(body.kyckey()); - } - - if (body.has_freezekey()) - { - mFreezeKey = Key::fromProtobuf(body.freezekey()); - } - - if (body.has_wipekey()) - { - mWipeKey = Key::fromProtobuf(body.wipekey()); - } - - if (body.has_supplykey()) - { - mSupplyKey = Key::fromProtobuf(body.supplykey()); - } - - if (body.has_autorenewaccount()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } - - if (body.has_expiry()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiry()); - } - - if (body.has_memo()) - { - mTokenMemo = body.memo().value(); - } - - if (body.has_fee_schedule_key()) - { - mFeeScheduleKey = Key::fromProtobuf(body.fee_schedule_key()); - } + initFromSourceTransactionBody(); +} - if (body.has_pause_key()) - { - mPauseKey = Key::fromProtobuf(body.pause_key()); - } +//----- +TokenUpdateTransaction::TokenUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -231,20 +167,12 @@ TokenUpdateTransaction& TokenUpdateTransaction::setPauseKey(const std::shared_pt } //----- -proto::Transaction TokenUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenUpdate, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenUpdate, request, deadline, response); } //----- @@ -253,6 +181,87 @@ void TokenUpdateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenupdate(build()); } +//----- +void TokenUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenupdate()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenUpdate data"); + } + + const proto::TokenUpdateTransactionBody& body = transactionBody.tokenupdate(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } + + mTokenName = body.name(); + mTokenSymbol = body.symbol(); + + if (body.has_treasury()) + { + mTreasuryAccountId = AccountId::fromProtobuf(body.treasury()); + } + + if (body.has_adminkey()) + { + mAdminKey = Key::fromProtobuf(body.adminkey()); + } + + if (body.has_kyckey()) + { + mKycKey = Key::fromProtobuf(body.kyckey()); + } + + if (body.has_freezekey()) + { + mFreezeKey = Key::fromProtobuf(body.freezekey()); + } + + if (body.has_wipekey()) + { + mWipeKey = Key::fromProtobuf(body.wipekey()); + } + + if (body.has_supplykey()) + { + mSupplyKey = Key::fromProtobuf(body.supplykey()); + } + + if (body.has_autorenewaccount()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + if (body.has_expiry()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expiry()); + } + + if (body.has_memo()) + { + mTokenMemo = body.memo().value(); + } + + if (body.has_fee_schedule_key()) + { + mFeeScheduleKey = Key::fromProtobuf(body.fee_schedule_key()); + } + + if (body.has_pause_key()) + { + mPauseKey = Key::fromProtobuf(body.pause_key()); + } +} + //----- proto::TokenUpdateTransactionBody* TokenUpdateTransaction::build() const { diff --git a/sdk/main/src/TokenWipeTransaction.cc b/sdk/main/src/TokenWipeTransaction.cc index 8ba977292..fc092e9a6 100644 --- a/sdk/main/src/TokenWipeTransaction.cc +++ b/sdk/main/src/TokenWipeTransaction.cc @@ -31,29 +31,15 @@ namespace Hedera TokenWipeTransaction::TokenWipeTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_tokenwipe()) - { - throw std::invalid_argument("Transaction body doesn't contain TokenWipe data"); - } - - const proto::TokenWipeAccountTransactionBody& body = transactionBody.tokenwipe(); - - if (body.has_token()) - { - mTokenId = TokenId::fromProtobuf(body.token()); - } - - if (body.has_account()) - { - mAccountId = AccountId::fromProtobuf(body.account()); - } - - mAmount = body.amount(); + initFromSourceTransactionBody(); +} - for (int i = 0; i < body.serialnumbers_size(); ++i) - { - mSerialNumbers.push_back(static_cast(body.serialnumbers(i))); - } +//----- +TokenWipeTransaction::TokenWipeTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -89,19 +75,12 @@ TokenWipeTransaction& TokenWipeTransaction::setSerialNumbers(const std::vector&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TokenWipeTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TokenWipeTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kTokenWipe, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kTokenWipe, request, deadline, response); } //----- @@ -110,6 +89,36 @@ void TokenWipeTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_tokenwipe(build()); } +//----- +void TokenWipeTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_tokenwipe()) + { + throw std::invalid_argument("Transaction body doesn't contain TokenWipe data"); + } + + const proto::TokenWipeAccountTransactionBody& body = transactionBody.tokenwipe(); + + if (body.has_token()) + { + mTokenId = TokenId::fromProtobuf(body.token()); + } + + if (body.has_account()) + { + mAccountId = AccountId::fromProtobuf(body.account()); + } + + mAmount = body.amount(); + + for (int i = 0; i < body.serialnumbers_size(); ++i) + { + mSerialNumbers.push_back(static_cast(body.serialnumbers(i))); + } +} + //----- proto::TokenWipeAccountTransactionBody* TokenWipeTransaction::build() const { diff --git a/sdk/main/src/TopicCreateTransaction.cc b/sdk/main/src/TopicCreateTransaction.cc index 7dc6bb41b..387bd2735 100644 --- a/sdk/main/src/TopicCreateTransaction.cc +++ b/sdk/main/src/TopicCreateTransaction.cc @@ -30,35 +30,17 @@ namespace Hedera { //----- TopicCreateTransaction::TopicCreateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_consensuscreatetopic()) - { - throw std::invalid_argument("Transaction body doesn't contain ConsensusCreateTopic data"); - } - - const proto::ConsensusCreateTopicTransactionBody& body = transactionBody.consensuscreatetopic(); - - mMemo = body.memo(); - - if (body.has_adminkey()) - { - mAdminKey = Key::fromProtobuf(body.adminkey()); - } - - if (body.has_submitkey()) - { - mSubmitKey = Key::fromProtobuf(body.submitkey()); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } + initFromSourceTransactionBody(); +} - if (body.has_autorenewaccount()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); - } +//----- +TopicCreateTransaction::TopicCreateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -102,20 +84,12 @@ TopicCreateTransaction& TopicCreateTransaction::setAutoRenewAccountId(const Acco } //----- -proto::Transaction TopicCreateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TopicCreateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TopicCreateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kConsensusCreateTopic, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kConsensusCreateTopic, request, deadline, response); } //----- @@ -124,6 +98,41 @@ void TopicCreateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_consensuscreatetopic(build()); } +//----- +void TopicCreateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_consensuscreatetopic()) + { + throw std::invalid_argument("Transaction body doesn't contain ConsensusCreateTopic data"); + } + + const proto::ConsensusCreateTopicTransactionBody& body = transactionBody.consensuscreatetopic(); + + mMemo = body.memo(); + + if (body.has_adminkey()) + { + mAdminKey = Key::fromProtobuf(body.adminkey()); + } + + if (body.has_submitkey()) + { + mSubmitKey = Key::fromProtobuf(body.submitkey()); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + if (body.has_autorenewaccount()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); + } +} + //----- proto::ConsensusCreateTopicTransactionBody* TopicCreateTransaction::build() const { diff --git a/sdk/main/src/TopicDeleteTransaction.cc b/sdk/main/src/TopicDeleteTransaction.cc index 9958610c9..7b281a717 100644 --- a/sdk/main/src/TopicDeleteTransaction.cc +++ b/sdk/main/src/TopicDeleteTransaction.cc @@ -31,17 +31,15 @@ namespace Hedera TopicDeleteTransaction::TopicDeleteTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_consensusdeletetopic()) - { - throw std::invalid_argument("Transaction body doesn't contain ConsensusDeleteTopic data"); - } - - const proto::ConsensusDeleteTopicTransactionBody& body = transactionBody.consensusdeletetopic(); + initFromSourceTransactionBody(); +} - if (body.has_topicid()) - { - mTopicId = TopicId::fromProtobuf(body.topicid()); - } +//----- +TopicDeleteTransaction::TopicDeleteTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -53,20 +51,12 @@ TopicDeleteTransaction& TopicDeleteTransaction::setTopicId(const TopicId& TopicI } //----- -proto::Transaction TopicDeleteTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TopicDeleteTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TopicDeleteTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kConsensusDeleteTopic, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kConsensusDeleteTopic, request, deadline, response); } //----- @@ -75,6 +65,24 @@ void TopicDeleteTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_consensusdeletetopic(build()); } +//----- +void TopicDeleteTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_consensusdeletetopic()) + { + throw std::invalid_argument("Transaction body doesn't contain ConsensusDeleteTopic data"); + } + + const proto::ConsensusDeleteTopicTransactionBody& body = transactionBody.consensusdeletetopic(); + + if (body.has_topicid()) + { + mTopicId = TopicId::fromProtobuf(body.topicid()); + } +} + //----- proto::ConsensusDeleteTopicTransactionBody* TopicDeleteTransaction::build() const { diff --git a/sdk/main/src/TopicInfoQuery.cc b/sdk/main/src/TopicInfoQuery.cc index bcbacf4fe..eb398da01 100644 --- a/sdk/main/src/TopicInfoQuery.cc +++ b/sdk/main/src/TopicInfoQuery.cc @@ -39,48 +39,37 @@ TopicInfoQuery& TopicInfoQuery::setTopicId(const TopicId& topicId) } //----- -proto::Query TopicInfoQuery::makeRequest(const Client& client, const std::shared_ptr& node) const +TopicInfo TopicInfoQuery::mapResponse(const proto::Response& response) const { - proto::Query query; - proto::ConsensusGetTopicInfoQuery* getTopicInfoQuery = query.mutable_consensusgettopicinfo(); - - proto::QueryHeader* header = getTopicInfoQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getTopicInfoQuery->set_allocated_topicid(mTopicId.toProtobuf().release()); - - return query; + return TopicInfo::fromProtobuf(response.consensusgettopicinfo()); } //----- -TopicInfo TopicInfoQuery::mapResponse(const proto::Response& response) const +grpc::Status TopicInfoQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return TopicInfo::fromProtobuf(response.consensusgettopicinfo()); + return node->submitQuery(proto::Query::QueryCase::kConsensusGetTopicInfo, request, deadline, response); } //----- -Status TopicInfoQuery::mapResponseStatus(const proto::Response& response) const +proto::Query TopicInfoQuery::buildRequest(proto::QueryHeader* header) const { - return gProtobufResponseCodeToStatus.at(response.consensusgettopicinfo().header().nodetransactionprecheckcode()); + auto consensusGetTopicInfoQuery = std::make_unique(); + consensusGetTopicInfoQuery->set_allocated_header(header); + consensusGetTopicInfoQuery->set_allocated_topicid(mTopicId.toProtobuf().release()); + + proto::Query query; + query.set_allocated_consensusgettopicinfo(consensusGetTopicInfoQuery.release()); + return query; } //----- -grpc::Status TopicInfoQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::ResponseHeader TopicInfoQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kConsensusGetTopicInfo, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.consensusgettopicinfo().header()); + return response.consensusgettopicinfo().header(); } } // namespace Hedera diff --git a/sdk/main/src/TopicMessageQuery.cc b/sdk/main/src/TopicMessageQuery.cc index 3b7dc91bd..ec6e8ae5e 100644 --- a/sdk/main/src/TopicMessageQuery.cc +++ b/sdk/main/src/TopicMessageQuery.cc @@ -50,7 +50,7 @@ enum class CallStatus std::shared_ptr getConnectedMirrorNode(const std::shared_ptr& network) { std::shared_ptr node = network->getNextMirrorNode(); - while (!node->connect(std::chrono::system_clock::now() + std::chrono::seconds(2))) + while (node->channelFailedToConnect()) { node = network->getNextMirrorNode(); } @@ -189,7 +189,7 @@ void startSubscription( } else { - // An error occurred. Whether retrying or not, cancel the call and shutdown the queue. + // An error occurred. Whether retrying or not, cancel the call and close the queue. contexts.back()->TryCancel(); queues.back()->Shutdown(); diff --git a/sdk/main/src/TopicMessageSubmitTransaction.cc b/sdk/main/src/TopicMessageSubmitTransaction.cc index 5c68e3a85..ca4bd981d 100644 --- a/sdk/main/src/TopicMessageSubmitTransaction.cc +++ b/sdk/main/src/TopicMessageSubmitTransaction.cc @@ -24,24 +24,26 @@ #include #include #include +#include +#include #include +#include namespace Hedera { //----- TopicMessageSubmitTransaction::TopicMessageSubmitTransaction(const proto::TransactionBody& transactionBody) + : ChunkedTransaction(transactionBody) { - if (!transactionBody.has_consensussubmitmessage()) - { - throw std::invalid_argument("Transaction body doesn't contain ConsensusSubmitMessage data"); - } - - const proto::ConsensusSubmitMessageTransactionBody& body = transactionBody.consensussubmitmessage(); + initFromSourceTransactionBody(); +} - if (body.has_topicid()) - { - mTopicId = TopicId::fromProtobuf(body.topicid()); - } +//----- +TopicMessageSubmitTransaction::TopicMessageSubmitTransaction( + const std::map>& transactions) + : ChunkedTransaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -69,38 +71,78 @@ TopicMessageSubmitTransaction& TopicMessageSubmitTransaction::setMessage(std::st } //----- -void TopicMessageSubmitTransaction::onChunk(const TransactionId& transactionId, int32_t chunk, int32_t total) +grpc::Status TopicMessageSubmitTransaction::submitRequest(const proto::Transaction& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::TransactionResponse* response) const { - mInitialTransactionId = transactionId; - mChunkNum = chunk; - mTotalNumOfChunks = total; + return node->submitTransaction( + proto::TransactionBody::DataCase::kConsensusSubmitMessage, request, deadline, response); } //----- -proto::Transaction TopicMessageSubmitTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const +void TopicMessageSubmitTransaction::addToBody(proto::TransactionBody& body) const { - return signTransaction(generateTransactionBody(&client), client); + body.set_allocated_consensussubmitmessage(build()); } //----- -grpc::Status TopicMessageSubmitTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::TransactionResponse* response) const +void TopicMessageSubmitTransaction::addToChunk(uint32_t chunk, uint32_t total, proto::TransactionBody& body) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kConsensusSubmitMessage, makeRequest(client, node), deadline, response); + body.set_allocated_consensussubmitmessage(build(static_cast(chunk))); + body.mutable_consensussubmitmessage()->mutable_chunkinfo()->set_allocated_initialtransactionid( + getTransactionId().toProtobuf().release()); + body.mutable_consensussubmitmessage()->mutable_chunkinfo()->set_number(static_cast(chunk + 1)); + body.mutable_consensussubmitmessage()->mutable_chunkinfo()->set_total(static_cast(total)); } //----- -void TopicMessageSubmitTransaction::addToBody(proto::TransactionBody& body) const +void TopicMessageSubmitTransaction::initFromSourceTransactionBody() { - body.set_allocated_consensussubmitmessage(build()); + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_consensussubmitmessage()) + { + throw std::invalid_argument("Transaction body doesn't contain ConsensusSubmitMessage data"); + } + + if (const proto::ConsensusSubmitMessageTransactionBody& body = transactionBody.consensussubmitmessage(); + body.has_topicid()) + { + mTopicId = TopicId::fromProtobuf(body.topicid()); + } + + // Construct the data from the various Transaction protobuf objects. + std::string data; + bool dataStillExists = true; + for (unsigned int i = 0; dataStillExists; ++i) + { + proto::Transaction tx; + + try + { + tx = getTransactionProtobufObject(i * static_cast(getNodeAccountIds().size())); + } + catch (const std::out_of_range&) + { + dataStillExists = false; + break; + } + + proto::SignedTransaction signedTx; + signedTx.ParseFromArray(tx.signedtransactionbytes().data(), static_cast(tx.signedtransactionbytes().size())); + + proto::TransactionBody txBody; + txBody.ParseFromArray(signedTx.bodybytes().data(), static_cast(signedTx.bodybytes().size())); + + data += txBody.consensussubmitmessage().message(); + } + + setData(data); } //----- -proto::ConsensusSubmitMessageTransactionBody* TopicMessageSubmitTransaction::build() const +proto::ConsensusSubmitMessageTransactionBody* TopicMessageSubmitTransaction::build(int chunk) const { auto body = std::make_unique(); @@ -109,12 +151,8 @@ proto::ConsensusSubmitMessageTransactionBody* TopicMessageSubmitTransaction::bui body->set_allocated_topicid(mTopicId.toProtobuf().release()); } - body->set_message(internal::Utilities::byteVectorToString(getData())); - - body->mutable_chunkinfo()->set_allocated_initialtransactionid(mInitialTransactionId.toProtobuf().release()); - body->mutable_chunkinfo()->set_total(mTotalNumOfChunks); - body->mutable_chunkinfo()->set_number(mChunkNum + 1); - + body->set_message(internal::Utilities::byteVectorToString( + (chunk >= 0) ? getDataForChunk(static_cast(chunk)) : getData())); return body.release(); } diff --git a/sdk/main/src/TopicUpdateTransaction.cc b/sdk/main/src/TopicUpdateTransaction.cc index fe3a7b10a..785e73623 100644 --- a/sdk/main/src/TopicUpdateTransaction.cc +++ b/sdk/main/src/TopicUpdateTransaction.cc @@ -32,48 +32,17 @@ namespace Hedera { //----- TopicUpdateTransaction::TopicUpdateTransaction(const proto::TransactionBody& transactionBody) + : Transaction(transactionBody) { - if (!transactionBody.has_consensusupdatetopic()) - { - throw std::invalid_argument("Transaction body doesn't contain ConsensusUpdateTopic data"); - } - - const proto::ConsensusUpdateTopicTransactionBody& body = transactionBody.consensusupdatetopic(); - - if (body.has_topicid()) - { - mTopicId = TopicId::fromProtobuf(body.topicid()); - } - - if (body.has_memo()) - { - mMemo = body.memo().value(); - } - - if (body.has_expirationtime()) - { - mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); - } - - if (body.has_adminkey()) - { - mAdminKey = Key::fromProtobuf(body.adminkey()); - } - - if (body.has_submitkey()) - { - mSubmitKey = Key::fromProtobuf(body.submitkey()); - } - - if (body.has_autorenewperiod()) - { - mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); - } + initFromSourceTransactionBody(); +} - if (body.has_autorenewaccount()) - { - mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); - } +//----- +TopicUpdateTransaction::TopicUpdateTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -165,20 +134,12 @@ TopicUpdateTransaction& TopicUpdateTransaction::clearAutoRenewAccountId() } //----- -proto::Transaction TopicUpdateTransaction::makeRequest(const Client& client, - const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TopicUpdateTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TopicUpdateTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kConsensusUpdateTopic, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kConsensusUpdateTopic, request, deadline, response); } //----- @@ -187,6 +148,54 @@ void TopicUpdateTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_consensusupdatetopic(build()); } +//----- +void TopicUpdateTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_consensusupdatetopic()) + { + throw std::invalid_argument("Transaction body doesn't contain ConsensusUpdateTopic data"); + } + + const proto::ConsensusUpdateTopicTransactionBody& body = transactionBody.consensusupdatetopic(); + + if (body.has_topicid()) + { + mTopicId = TopicId::fromProtobuf(body.topicid()); + } + + if (body.has_memo()) + { + mMemo = body.memo().value(); + } + + if (body.has_expirationtime()) + { + mExpirationTime = internal::TimestampConverter::fromProtobuf(body.expirationtime()); + } + + if (body.has_adminkey()) + { + mAdminKey = Key::fromProtobuf(body.adminkey()); + } + + if (body.has_submitkey()) + { + mSubmitKey = Key::fromProtobuf(body.submitkey()); + } + + if (body.has_autorenewperiod()) + { + mAutoRenewPeriod = internal::DurationConverter::fromProtobuf(body.autorenewperiod()); + } + + if (body.has_autorenewaccount()) + { + mAutoRenewAccountId = AccountId::fromProtobuf(body.autorenewaccount()); + } +} + //----- proto::ConsensusUpdateTopicTransactionBody* TopicUpdateTransaction::build() const { diff --git a/sdk/main/src/Transaction.cc b/sdk/main/src/Transaction.cc index ffbcaba0f..9fbb368fc 100644 --- a/sdk/main/src/Transaction.cc +++ b/sdk/main/src/Transaction.cc @@ -28,7 +28,7 @@ #include "ContractDeleteTransaction.h" #include "ContractExecuteTransaction.h" #include "ContractUpdateTransaction.h" -#include "ED25519PublicKey.h" +#include "Defaults.h" #include "EthereumTransaction.h" #include "FileAppendTransaction.h" #include "FileCreateTransaction.h" @@ -36,6 +36,7 @@ #include "FileUpdateTransaction.h" #include "FreezeTransaction.h" #include "PrivateKey.h" +#include "PublicKey.h" #include "ScheduleCreateTransaction.h" #include "ScheduleDeleteTransaction.h" #include "ScheduleSignTransaction.h" @@ -66,10 +67,11 @@ #include "TransferTransaction.h" #include "WrappedTransaction.h" #include "exceptions/IllegalStateException.h" -#include "exceptions/UnsupportedOperationException.h" +#include "exceptions/UninitializedException.h" #include "impl/DurationConverter.h" -#include "impl/Node.h" +#include "impl/Network.h" #include "impl/Utilities.h" +#include "impl/openssl_utils/OpenSSLUtils.h" #include #include @@ -80,43 +82,108 @@ namespace Hedera { +//----- +template +struct Transaction::TransactionImpl +{ + // The source TransactionBody protobuf object from which derived transactions should use to construct themselves. The + // Transaction base class will use this to get the Transaction-specific fields, and then pass it to the derived class + // to pick up its own data. It also acts as the "source of truth" when generating SignedTransaction and Transaction + // protobuf objects to send to the network. + proto::TransactionBody mSourceTransactionBody; + + // List of completed Transaction protobuf objects ready to be sent. These are functionally identical, the only + // difference is the node to which they are sent. + std::vector mTransactions; + + // List of SignedTransaction protobuf objects. The index of these SignedTransactions match up with their corresponding + // Transaction protobuf object in mTransactions. + std::vector mSignedTransactions; + + // A list of PublicKeys with their signer functions that should sign the TransactionBody protobuf objects this + // Transaction creates. If the signer function associated with a public key is empty, that means that the private key + // associated with that public key has already contributed a signature, but the signer is not available (probably + // because this Transaction was created fromBytes(), or the signature was contributed manually via addSignature()). + std::unordered_map, std::function(const std::vector&)>> + mSignatories; + + // Is this Transaction frozen? + bool mIsFrozen = false; + + // The ID of this Transaction. + TransactionId mTransactionId; + + // The maximum transaction fee willing to be paid to execute this Transaction. If not set, this Transaction will use + // the Client's set maximum transaction fee. If that's not set, mDefaultMaxTransactionFee is used. + std::optional mMaxTransactionFee; + + // The default maximum transaction fee. This can be adjusted by derived Transaction classes if those Transactions + // generally cost more. + Hbar mDefaultMaxTransactionFee = DEFAULT_MAX_TRANSACTION_FEE; + + // The length of time this Transaction will remain valid. + std::chrono::duration mTransactionValidDuration = DEFAULT_TRANSACTION_VALID_DURATION; + + // The memo to be associated with this Transaction. + std::string mTransactionMemo; + + // Should this Transaction regenerate its TransactionId upon a TRANSACTION_EXPIRED response from the network? If not + // set, this Transaction will use the Client's set transaction ID regeneration policy. If that's not set, the default + // behavior is to regenerate the transaction ID. + std::optional mTransactionIdRegenerationPolicy; +}; + //----- template WrappedTransaction Transaction::fromBytes(const std::vector& bytes) { + // Keep a list of all transactions that were serialized. + std::map> transactions; + + proto::Transaction tx; + proto::SignedTransaction signedTx; proto::TransactionBody txBody; - // TransactionList protobuf object + // Serialized object is a TransactionList protobuf object. if (proto::TransactionList txList; txList.ParseFromArray(bytes.data(), static_cast(bytes.size())) && txList.transaction_list_size() > 0) { - proto::SignedTransaction signedTx; - signedTx.ParseFromArray(txList.transaction_list(0).signedtransactionbytes().data(), - static_cast(txList.transaction_list(0).signedtransactionbytes().size())); - txBody.ParseFromArray(signedTx.bodybytes().data(), static_cast(signedTx.bodybytes().size())); + for (int i = 0; i < txList.transaction_list_size(); ++i) + { + tx = txList.transaction_list(i); + + signedTx.ParseFromArray(tx.signedtransactionbytes().data(), static_cast(tx.signedtransactionbytes().size())); + txBody.ParseFromArray(signedTx.bodybytes().data(), static_cast(signedTx.bodybytes().size())); + + transactions[TransactionId::fromProtobuf(txBody.transactionid())] + [AccountId::fromProtobuf(txBody.nodeaccountid())] = tx; + } } - // Transaction protobuf object - if (proto::Transaction tx; txBody.data_case() == proto::TransactionBody::DataCase::DATA_NOT_SET && - tx.ParseFromArray(bytes.data(), static_cast(bytes.size())) && - !tx.signedtransactionbytes().empty()) + // Transaction protobuf object. + else if (txBody.data_case() == proto::TransactionBody::DataCase::DATA_NOT_SET && + tx.ParseFromArray(bytes.data(), static_cast(bytes.size())) && !tx.signedtransactionbytes().empty()) { - proto::SignedTransaction signedTx; signedTx.ParseFromArray(tx.signedtransactionbytes().data(), static_cast(tx.signedtransactionbytes().size())); txBody.ParseFromArray(signedTx.bodybytes().data(), static_cast(signedTx.bodybytes().size())); + + transactions[TransactionId::fromProtobuf(txBody.transactionid())][AccountId::fromProtobuf(txBody.nodeaccountid())] = + tx; } - // SignedTransaction protobuf object - if (proto::SignedTransaction signedTx; txBody.data_case() == proto::TransactionBody::DataCase::DATA_NOT_SET && - signedTx.ParseFromArray(bytes.data(), static_cast(bytes.size())) && - !signedTx.bodybytes().empty()) + // TransactionBody protobuf object. + else if (txBody.data_case() == proto::TransactionBody::DataCase::DATA_NOT_SET && + txBody.ParseFromArray(bytes.data(), static_cast(bytes.size()))) { - txBody.ParseFromArray(signedTx.bodybytes().data(), static_cast(signedTx.bodybytes().size())); + signedTx.set_bodybytes(txBody.SerializeAsString()); + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + + transactions[TransactionId::fromProtobuf(txBody.transactionid())][AccountId::fromProtobuf(txBody.nodeaccountid())] = + tx; } - // If not a TransactionBody protobuf object, throw - if (txBody.data_case() == proto::TransactionBody::DataCase::DATA_NOT_SET && - !txBody.ParseFromArray(bytes.data(), static_cast(bytes.size()))) + // If not any Transaction, throw. + else { throw std::invalid_argument("Unable to construct Transaction from input bytes"); } @@ -124,90 +191,110 @@ WrappedTransaction Transaction::fromBytes(const std::vector +std::vector Transaction::toBytes() const +{ + if (!isFrozen()) + { + throw IllegalStateException("Transaction must be frozen before conversion to bytes will be stable."); + } + + buildAllTransactions(); + + proto::TransactionList txList; + for (const auto& tx : mImpl->mTransactions) + { + *txList.add_transaction_list() = tx; + } + + return internal::Utilities::stringToByteVector(txList.SerializeAsString()); +} + //----- template SdkRequestType& Transaction::sign(const PrivateKey* key) @@ -221,43 +308,141 @@ SdkRequestType& Transaction::signWith( const std::shared_ptr& key, const std::function(const std::vector&)>& signer) { - if (!mIsFrozen) + if (!isFrozen()) { throw IllegalStateException("Transaction must be frozen in order to sign"); } - mSignatures.emplace_back(key, signer); + if (!keyAlreadySigned(key)) + { + // Adding a signature will require all Transaction protobuf objects to be regenerated. + mImpl->mTransactions.clear(); + mImpl->mTransactions.resize(mImpl->mSignedTransactions.size()); + mImpl->mSignatories[key] = signer; + } return static_cast(*this); } +//----- +template +SdkRequestType& Transaction::signWithOperator(const Client& client) +{ + if (!client.getOperatorAccountId().has_value()) + { + throw UninitializedException("Input client has no operator."); + } + + freezeWith(&client); + + return signWith(client.getOperatorPublicKey(), client.getOperatorSigner()); +} + +//----- +template +SdkRequestType& Transaction::addSignature(const std::shared_ptr& publicKey, + const std::vector& signature) +{ + // A signature can only be added for Transactions being sent to exactly one node. + requireOneNodeAccountId(); + + // A signature can only be added to frozen Transactions. + if (!isFrozen()) + { + throw IllegalStateException("Adding a signature to a Transaction requires the Transaction to be frozen"); + } + + // If this PublicKey has already signed this Transaction, the signature doesn't need to be added again. + if (keyAlreadySigned(publicKey)) + { + return static_cast(*this); + } + + // Adding a signature will require all Transaction protobuf objects to be regenerated. + mImpl->mTransactions.clear(); + mImpl->mTransactions.resize(mImpl->mSignedTransactions.size()); + mImpl->mSignatories.emplace(publicKey, std::function(const std::vector&)>()); + + // Add the signature to the SignedTransaction protobuf object. Since there's only one node account ID, there's only + // one SignedTransaction protobuf object in the vector. + *mImpl->mSignedTransactions.begin()->mutable_sigmap()->add_sigpair() = *publicKey->toSignaturePairProtobuf(signature); + + return static_cast(*this); +} + +//----- +template +std::map, std::vector>> +Transaction::getSignatures() const +{ + if (mImpl->mSignatories.empty()) + { + return {}; + } + + // Build all the Transaction protobuf objects to generate the signatures for each key. + buildAllTransactions(); + return getSignaturesInternal(); +} + +//----- +template +SdkRequestType& Transaction::freeze() +{ + return freezeWith(nullptr); +} + //----- template SdkRequestType& Transaction::freezeWith(const Client* client) { - if (mIsFrozen) + if (isFrozen()) { return static_cast(*this); } - if (mTransactionId == TransactionId()) + if (mImpl->mTransactionId == TransactionId()) { if (!client) { throw IllegalStateException( - "If no client is provided to freeze transaction, the transaction ID must be manually set"); + "If no client is provided to freeze transaction, the transaction ID must be manually set."); } if (!client->getOperatorAccountId().has_value()) { - throw IllegalStateException("Client operator has not been initialized and cannot freeze transaction"); + throw UninitializedException("Client operator has not been initialized and cannot freeze transaction."); } // Generate a transaction ID with the client. - mTransactionId = TransactionId::generate(client->getOperatorAccountId().value()); + mImpl->mTransactionId = TransactionId::generate(client->getOperatorAccountId().value()); } - mIsFrozen = true; + if (Executable:: + getNodeAccountIds() + .empty()) + { + if (!client) + { + throw IllegalStateException( + "If no client is provided to freeze transaction, the node account IDs must be manually set."); + } + + // Make sure the client has a valid network. + if (!client->getNetwork()) + { + throw UninitializedException("Client has not been initialized with a valid network"); + } + + // Have the Client's network generate the node account IDs to which to send this Transaction. + Executable::setNodeAccountIds( + client->getNetwork()->getNodeAccountIdsForExecute()); + } + + // Generate the SignedTransaction protobuf objects. + generateSignedTransactions(client); + + mImpl->mIsFrozen = true; return static_cast(*this); } @@ -273,17 +458,78 @@ ScheduleCreateTransaction Transaction::schedule() const throw IllegalStateException("Underlying transaction for a scheduled transaction cannot have node account IDs set"); } + updateSourceTransactionBody(nullptr); return ScheduleCreateTransaction().setScheduledTransaction( - WrappedTransaction::fromProtobuf(generateTransactionBody(nullptr))); + WrappedTransaction::fromProtobuf(mImpl->mSourceTransactionBody)); } //----- template -SdkRequestType& Transaction::setValidTransactionDuration(const std::chrono::duration& duration) +std::vector Transaction::getTransactionHash() const +{ + if (!isFrozen()) + { + throw IllegalStateException("Transaction must be frozen in order to calculate the hash"); + } + + // Use the first transaction's hash. + buildTransaction(0U); + return internal::OpenSSLUtils::computeSHA384( + internal::Utilities::stringToByteVector(getTransactionProtobufObject(0U).signedtransactionbytes())); +} + +//----- +template +std::map> Transaction::getTransactionHashPerNode() const +{ + if (!isFrozen()) + { + throw IllegalStateException("Transaction must be frozen in order to calculate the hash"); + } + + buildAllTransactions(); + const std::vector nodeAccountIds = + Executable:: + getNodeAccountIds(); + + std::map> hashes; + for (unsigned int i = 0; i < mImpl->mTransactions.size(); ++i) + { + hashes[nodeAccountIds.at(i)] = internal::OpenSSLUtils::computeSHA384( + internal::Utilities::stringToByteVector(getTransactionProtobufObject(i).signedtransactionbytes())); + } + + return hashes; +} + +//----- +template +void Transaction::requireOneNodeAccountId() const +{ + if (Executable:: + getNodeAccountIds() + .size() != 1ULL) + { + throw IllegalStateException("Transaction does not have exactly one node account ID set"); + } +} + +//----- +template +SdkRequestType& Transaction::setTransactionId(const TransactionId& id) { requireNotFrozen(); + mImpl->mTransactionId = id; + return static_cast(*this); +} - mTransactionValidDuration = duration; +//----- +template +SdkRequestType& Transaction::setNodeAccountIds(std::vector nodeAccountIds) +{ + requireNotFrozen(); + Executable::setNodeAccountIds( + std::move(nodeAccountIds)); return static_cast(*this); } @@ -292,28 +538,25 @@ template SdkRequestType& Transaction::setMaxTransactionFee(const Hbar& fee) { requireNotFrozen(); - - mMaxTransactionFee = fee; + mImpl->mMaxTransactionFee = fee; return static_cast(*this); } //----- template -SdkRequestType& Transaction::setTransactionMemo(const std::string& memo) +SdkRequestType& Transaction::setValidTransactionDuration(const std::chrono::duration& duration) { requireNotFrozen(); - - mTransactionMemo = memo; + mImpl->mTransactionValidDuration = duration; return static_cast(*this); } //----- template -SdkRequestType& Transaction::setTransactionId(const TransactionId& id) +SdkRequestType& Transaction::setTransactionMemo(const std::string& memo) { requireNotFrozen(); - - mTransactionId = id; + mImpl->mTransactionMemo = memo; return static_cast(*this); } @@ -322,8 +565,7 @@ template SdkRequestType& Transaction::setRegenerateTransactionIdPolicy(bool regenerate) { requireNotFrozen(); - - mTransactionIdRegenerationPolicy = regenerate; + mImpl->mTransactionIdRegenerationPolicy = regenerate; return static_cast(*this); } @@ -331,162 +573,390 @@ SdkRequestType& Transaction::setRegenerateTransactionIdPolicy(bo template TransactionId Transaction::getTransactionId() const { - if (mTransactionId == TransactionId() && !mIsFrozen) + if (mImpl->mTransactionId == TransactionId() && !isFrozen()) { throw IllegalStateException("No transaction ID generated yet. Try freezing the transaction"); } - return mTransactionId; + return mImpl->mTransactionId; } //----- template -Transaction::Transaction(const proto::TransactionBody& transactionBody) +std::optional Transaction::getMaxTransactionFee() const { - if (transactionBody.has_nodeaccountid()) - { - mNodeAccountId = AccountId::fromProtobuf(transactionBody.nodeaccountid()); - } + return mImpl->mMaxTransactionFee; +} - mTransactionMemo = transactionBody.memo(); +//----- +template +Hbar Transaction::getDefaultMaxTransactionFee() const +{ + return mImpl->mDefaultMaxTransactionFee; +} - if (transactionBody.has_transactionvalidduration()) - { - mTransactionValidDuration = internal::DurationConverter::fromProtobuf(transactionBody.transactionvalidduration()); - } +//----- +template +std::chrono::duration Transaction::getValidTransactionDuration() const +{ + return mImpl->mTransactionValidDuration; +} + +//----- +template +std::string Transaction::getTransactionMemo() const +{ + return mImpl->mTransactionMemo; +} + +//----- +template +std::optional Transaction::getRegenerateTransactionIdPolicy() const +{ + return mImpl->mTransactionIdRegenerationPolicy; +} + +//----- +template +Transaction::Transaction() + : Executable() + , mImpl(std::make_unique()) +{ +} - if (transactionBody.has_transactionid()) +//----- +template +Transaction::~Transaction() = default; + +//----- +template +Transaction::Transaction(const Transaction& other) + : Executable(other) + , mImpl(std::make_unique(*other.mImpl)) +{ +} + +//----- +template +Transaction& Transaction::operator=(const Transaction& other) +{ + if (this != &other) { - mTransactionId = TransactionId::fromProtobuf(transactionBody.transactionid()); + Executable::operator=(other); + mImpl = std::make_unique(*other.mImpl); } - if (transactionBody.transactionfee() != static_cast(DEFAULT_MAX_TRANSACTION_FEE.toTinybars())) + return *this; +} + +//----- +template +Transaction::Transaction(Transaction&& other) noexcept + : Executable(std::move(other)) + , mImpl(std::move(other.mImpl)) // NOLINT +{ + // Leave moved-from object in a valid state. + other.mImpl = std::make_unique(); // NOLINT +} + +//----- +template +Transaction& Transaction::operator=(Transaction&& other) noexcept +{ + if (this != &other) { - mMaxTransactionFee = Hbar(static_cast(transactionBody.transactionfee()), HbarUnit::TINYBAR()); + Executable::operator=( + std::move(other)); + mImpl = std::move(other.mImpl); // NOLINT + + // Leave moved-from object in a valid state. + other.mImpl = std::make_unique(); } + + return *this; } //----- template -void Transaction::onSelectNode(const std::shared_ptr& node) +Transaction::Transaction(const proto::TransactionBody& txBody) + : Executable() + , mImpl(std::make_unique()) { - Executable::onSelectNode(node); - mNodeAccountId = node->getAccountId(); + if (txBody.has_transactionid()) + { + mImpl->mTransactionId = TransactionId::fromProtobuf(txBody.transactionid()); + } + + if (txBody.transactionfee() > 0ULL) + { + mImpl->mMaxTransactionFee = Hbar(static_cast(txBody.transactionfee()), HbarUnit::TINYBAR()); + } + + if (txBody.has_transactionvalidduration()) + { + mImpl->mTransactionValidDuration = internal::DurationConverter::fromProtobuf(txBody.transactionvalidduration()); + } + + mImpl->mTransactionMemo = txBody.memo(); + mImpl->mSourceTransactionBody = txBody; } //----- template -proto::Transaction Transaction::signTransaction(const proto::TransactionBody& transaction, - const Client& client) const +Transaction::Transaction( + const std::map>& transactions) + : Executable() + , mImpl(std::make_unique()) { - // Make sure the operator has been set, and therefore has an account ID and key. - if (client.getOperatorAccountId() && client.getOperatorPublicKey()) + if (transactions.empty()) { - // Generate a signature from the TransactionBody - auto transactionBodySerialized = std::make_unique(transaction.SerializeAsString()); - std::vector signature = client.sign(internal::Utilities::stringToByteVector(*transactionBodySerialized)); + return; + } - // Generate a protobuf SignaturePair from a protobuf SignatureMap - auto signatureMap = std::make_unique(); - proto::SignaturePair* signaturePair = signatureMap->add_sigpair(); - signaturePair->set_allocated_pubkeyprefix( - new std::string(internal::Utilities::byteVectorToString(client.getOperatorPublicKey()->toBytesRaw()))); + // The node account IDs get added as a batch so just add them to a separate vector for now. + std::vector nodeAccountIds; + nodeAccountIds.reserve(transactions.cbegin()->second.size()); - if (dynamic_cast(client.getOperatorPublicKey().get())) - { - signaturePair->set_allocated_ed25519(new std::string(internal::Utilities::byteVectorToString(signature))); - } - else - { - signaturePair->set_allocated_ecdsa_secp256k1(new std::string(internal::Utilities::byteVectorToString(signature))); - } + for (const auto& [accountId, protoTx] : transactions.cbegin()->second) + { + nodeAccountIds.push_back(accountId); + addTransaction(protoTx); - // Add other signatures - for (const auto& [publicKey, signer] : mSignatures) + if (mImpl->mSignatories.empty()) { - signature = signer(internal::Utilities::stringToByteVector(*transactionBodySerialized)); - signaturePair = signatureMap->add_sigpair(); - signaturePair->set_allocated_pubkeyprefix( - new std::string(internal::Utilities::byteVectorToString(publicKey->toBytesRaw()))); - - if (dynamic_cast(publicKey.get())) + const proto::SignedTransaction& signedTx = mImpl->mSignedTransactions.back(); + for (int i = 0; i < signedTx.sigmap().sigpair_size(); ++i) { - signaturePair->set_allocated_ed25519(new std::string(internal::Utilities::byteVectorToString(signature))); - } - else - { - signaturePair->set_allocated_ecdsa_secp256k1( - new std::string(internal::Utilities::byteVectorToString(signature))); + mImpl->mSignatories.emplace( + PublicKey::fromBytes(internal::Utilities::stringToByteVector(signedTx.sigmap().sigpair(i).pubkeyprefix())), + std::function(const std::vector&)>()); } } + } - // Create a protobuf SignedTransaction from the TransactionBody and SignatureMap - proto::SignedTransaction signedTransaction; - signedTransaction.set_allocated_bodybytes(transactionBodySerialized.release()); - signedTransaction.set_allocated_sigmap(signatureMap.release()); + // Set the source TransactionBody. + proto::TransactionBody txBody; + txBody.ParseFromArray(mImpl->mSignedTransactions.cbegin()->bodybytes().data(), + static_cast(mImpl->mSignedTransactions.cbegin()->bodybytes().size())); + mImpl->mSourceTransactionBody = txBody; + + // Set other fields based on the source TransactionBody. + mImpl->mTransactionId = transactions.cbegin()->first; + Executable::setNodeAccountIds( + nodeAccountIds); - // Serialize the protobuf SignedTransaction to a protobuf Transaction - proto::Transaction transactionToReturn; - transactionToReturn.set_allocated_signedtransactionbytes(new std::string(signedTransaction.SerializeAsString())); + if (mImpl->mSourceTransactionBody.transactionfee() > 0LL) + { + mImpl->mMaxTransactionFee = + Hbar(static_cast(mImpl->mSourceTransactionBody.transactionfee()), HbarUnit::TINYBAR()); + } - return transactionToReturn; + if (mImpl->mSourceTransactionBody.has_transactionvalidduration()) + { + mImpl->mTransactionValidDuration = + internal::DurationConverter::fromProtobuf(mImpl->mSourceTransactionBody.transactionvalidduration()); } - throw std::invalid_argument("Invalid client used to sign transaction"); + mImpl->mTransactionMemo = mImpl->mSourceTransactionBody.memo(); + + // This constructor is only used in fromBytes(), which means a Transaction was frozen and serialized using toBytes(). + // As such, this Transaction should be constructed as frozen. + mImpl->mIsFrozen = true; +} + +//----- +template +proto::Transaction Transaction::makeRequest(unsigned int index) const +{ + buildTransaction(index); + return getTransactionProtobufObject(index); } //----- template -proto::TransactionBody Transaction::generateTransactionBody(const Client* client) const +void Transaction::buildAllTransactions() const { - proto::TransactionBody body; - body.set_allocated_transactionid(mTransactionId.toProtobuf().release()); - body.set_transactionfee(static_cast(getMaxTransactionFee(client).toTinybars())); - body.set_memo(mTransactionMemo); - body.set_allocated_transactionvalidduration(internal::DurationConverter::toProtobuf(mTransactionValidDuration)); - body.set_allocated_nodeaccountid(mNodeAccountId.toProtobuf().release()); + // Go through each SignedTransaction protobuf object and add all signatures to its SignatureMap protobuf object. + for (unsigned int i = 0; i < mImpl->mSignedTransactions.size(); ++i) + { + buildTransaction(i); + } +} - // Add derived Transaction fields to TransactionBody. - addToBody(body); +//----- +template +void Transaction::generateSignedTransactions(const Client* client) +{ + // Update this Transaction's source TransactionBody protobuf object. + updateSourceTransactionBody(client); - return body; + // Add a SignedTransaction protobuf object for each node account ID based off of this Transaction's + // mSourceTransactionBody. + addSignedTransactionForEachNode(mImpl->mSourceTransactionBody); } //----- template -void Transaction::requireNotFrozen() const +void Transaction::updateSourceTransactionBody(const Client* client) const { - if (mIsFrozen) + if (mImpl->mTransactionId != TransactionId()) { - throw IllegalStateException("Transaction is immutable and cannot be edited"); + mImpl->mSourceTransactionBody.set_allocated_transactionid(mImpl->mTransactionId.toProtobuf().release()); } + + if (mImpl->mMaxTransactionFee.has_value()) + { + mImpl->mSourceTransactionBody.set_transactionfee(static_cast(mImpl->mMaxTransactionFee->toTinybars())); + } + else if (client && client->getMaxTransactionFee().has_value()) + { + mImpl->mSourceTransactionBody.set_transactionfee( + static_cast(client->getMaxTransactionFee()->toTinybars())); + } + else + { + mImpl->mSourceTransactionBody.set_transactionfee( + static_cast(mImpl->mDefaultMaxTransactionFee.toTinybars())); + } + + mImpl->mSourceTransactionBody.set_allocated_transactionvalidduration( + internal::DurationConverter::toProtobuf(mImpl->mTransactionValidDuration)); + mImpl->mSourceTransactionBody.set_memo(mImpl->mTransactionMemo); + + // Add derived Transaction fields to mSourceTransactionBody. + addToBody(mImpl->mSourceTransactionBody); } //----- template -void Transaction::onExecute(const Client& client) +void Transaction::addTransaction(const proto::Transaction& transaction) +{ + // Add the Transaction protobuf object to the Transaction protobuf object list. + mImpl->mTransactions.push_back(transaction); + + // Parse the Transaction protobuf object into a SignedTransaction protobuf object. + proto::SignedTransaction signedTx; + signedTx.ParseFromArray(transaction.signedtransactionbytes().data(), + static_cast(transaction.signedtransactionbytes().size())); + + // Add the SignedTransaction protobuf object to the SignedTransaction protobuf object list. + addTransaction(signedTx); +} + +//----- +template +void Transaction::addTransaction(const proto::SignedTransaction& transaction) +{ + mImpl->mSignedTransactions.push_back(transaction); +} + +//----- +template +void Transaction::addSignedTransactionForEachNode(proto::TransactionBody& transactionBody) { - if (!mIsFrozen) + // For each node account ID, generate the SignedTransaction protobuf object. + for (const AccountId& accountId : + Executable:: + getNodeAccountIds()) { - freezeWith(&client); + transactionBody.set_allocated_nodeaccountid(accountId.toProtobuf().release()); + + proto::SignedTransaction signedTransaction; + signedTransaction.set_bodybytes(transactionBody.SerializeAsString()); + addTransaction(signedTransaction); } + + transactionBody.clear_nodeaccountid(); +} + +//----- +template +void Transaction::clearTransactions() +{ + mImpl->mSignedTransactions.clear(); + mImpl->mTransactions.clear(); } //----- template -Hbar Transaction::getMaxTransactionFee(const Client* client) const +void Transaction::requireNotFrozen() const { - if (mMaxTransactionFee.has_value()) + if (isFrozen()) { - return mMaxTransactionFee.value(); + throw IllegalStateException("Transaction is immutable and cannot be edited"); } +} + +//----- +template +bool Transaction::isFrozen() const +{ + return mImpl->mIsFrozen; +} - if (client && client->getMaxTransactionFee().has_value()) +//----- +template +void Transaction::setDefaultMaxTransactionFee(const Hbar& fee) +{ + mImpl->mDefaultMaxTransactionFee = fee; +} + +//----- +template +std::map, std::vector>> +Transaction::getSignaturesInternal(size_t offset) const +{ + // Get each node account ID that the Transaction protobuf objects will be sent. + const std::vector nodeAccountIds = + Executable:: + getNodeAccountIds(); + + std::map, std::vector>> signatures; + for (int i = 0; i < nodeAccountIds.size(); ++i) { - return client->getMaxTransactionFee().value(); + const proto::SignatureMap& signatureMap = + mImpl->mSignedTransactions.at(offset * nodeAccountIds.size() + i).sigmap(); + for (const auto& [key, signer] : mImpl->mSignatories) + { + const std::string rawPublicKeyBytes = internal::Utilities::byteVectorToString(key->toBytesRaw()); + for (int j = 0; j < signatureMap.sigpair_size(); ++j) + { + const proto::SignaturePair& signaturePair = signatureMap.sigpair(j); + if (signaturePair.has_ed25519() && signaturePair.ed25519() == rawPublicKeyBytes) + { + signatures[nodeAccountIds.at(i)][key] = internal::Utilities::stringToByteVector(signaturePair.ed25519()); + } + else if (signaturePair.has_ecdsa_secp256k1() && signaturePair.ecdsa_secp256k1() == rawPublicKeyBytes) + { + signatures[nodeAccountIds.at(i)][key] = + internal::Utilities::stringToByteVector(signaturePair.ecdsa_secp256k1()); + } + } + } } - return DEFAULT_MAX_TRANSACTION_FEE; + return signatures; +} + +//----- +template +proto::Transaction Transaction::getTransactionProtobufObject(unsigned int index) const +{ + return mImpl->mTransactions.at(index); +} + +//----- +template +proto::TransactionBody Transaction::getSourceTransactionBody() const +{ + return mImpl->mSourceTransactionBody; +} + +//----- +template +TransactionId Transaction::getCurrentTransactionId() const +{ + return mImpl->mTransactionId; } //----- @@ -494,7 +964,7 @@ template TransactionResponse Transaction::mapResponse(const proto::TransactionResponse& response) const { TransactionResponse txResp = TransactionResponse::fromProtobuf(response); - txResp.mTransactionId = mTransactionId; + txResp.mTransactionId = getCurrentTransactionId(); return txResp; } @@ -520,38 +990,100 @@ typename ExecutablemTransactionIdRegenerationPolicy.has_value()) { - shouldRegenerate = *mTransactionIdRegenerationPolicy; + shouldRegenerate = mImpl->mTransactionIdRegenerationPolicy.value(); } // Follow the Client's policy if this Transaction's policy hasn't been explicitly set and the Client's policy has - // been - else if (const std::optional clientTxIdRegenPolicy = client.getTransactionIdRegenerationPolicy(); - clientTxIdRegenPolicy) + // been. + else if (client.getTransactionIdRegenerationPolicy().has_value()) { - shouldRegenerate = *clientTxIdRegenPolicy; + shouldRegenerate = client.getTransactionIdRegenerationPolicy().value(); } if (shouldRegenerate) { - // Regenerate the transaction ID and return RETRY if transaction IDs are allowed to be regenerated. - mTransactionId = TransactionId::generate(mTransactionId.getAccountId()); + // If transaction IDs are allowed to be regenerated, regenerate the transaction ID and the Transaction protobuf + // objects. + mImpl->mTransactionId = TransactionId::generate(mImpl->mTransactionId.getAccountId()); + + // Regenerate the SignedTransaction protobuf objects. + clearTransactions(); + generateSignedTransactions(&client); + + // Retry execution with the new transaction ID. return Executable:: ExecutionStatus::RETRY; } else { - // Return REQUEST_ERROR if the transaction expired but transaction IDs aren't allowed to be regenerated + // Return REQUEST_ERROR if the transaction expired but transaction IDs aren't allowed to be regenerated. return Executable:: ExecutionStatus::REQUEST_ERROR; } } +//----- +template +void Transaction::onExecute(const Client& client) +{ + if (!isFrozen()) + { + freezeWith(&client); + } + + // Sign with the operator if the operator's presence, and if it's paying for the Transaction. + if (client.getOperatorAccountId().has_value() && + client.getOperatorAccountId().value() == mImpl->mTransactionId.getAccountId()) + { + signWithOperator(client); + } +} + +//----- +template +void Transaction::buildTransaction(unsigned int index) const +{ + // If the Transaction protobuf object is already built for this index, there's no need to do anything else. + if (!getTransactionProtobufObject(index).signedtransactionbytes().empty()) + { + return; + } + + // For each PublicKey and signer function, generate a signature of the TransactionBody protobuf object bytes held in + // the SignedTransaction protobuf object at the provided index. + proto::SignedTransaction& signedTransaction = mImpl->mSignedTransactions[index]; + for (const auto& [publicKey, signer] : mImpl->mSignatories) + { + // If there is no signer function, the signature has already been generated for the SignedTransaction (either added + // manually with addSignature() or this Transaction came from fromBytes()). + if (signer) + { + *signedTransaction.mutable_sigmap()->add_sigpair() = *publicKey->toSignaturePairProtobuf( + signer(internal::Utilities::stringToByteVector(signedTransaction.bodybytes()))); + } + } + + mImpl->mTransactions[index].set_signedtransactionbytes(signedTransaction.SerializeAsString()); +} + +//----- +template +bool Transaction::keyAlreadySigned(const std::shared_ptr& publicKey) const +{ + const std::vector publicKeyBytes = publicKey->toBytesDer(); + return std::any_of( + mImpl->mSignatories.cbegin(), + mImpl->mSignatories.cend(), + [&publicKeyBytes]( + const std::pair, std::function(const std::vector&)>>& + toSign) { return toSign.first->toBytesDer() == publicKeyBytes; }); +} + /** * Explicit template instantiations. */ diff --git a/sdk/main/src/TransactionId.cc b/sdk/main/src/TransactionId.cc index b9054fcaa..d465c061f 100644 --- a/sdk/main/src/TransactionId.cc +++ b/sdk/main/src/TransactionId.cc @@ -67,6 +67,12 @@ bool TransactionId::operator==(const TransactionId& other) const return (mValidTransactionTime == other.mValidTransactionTime) && (mAccountId == other.mAccountId); } +//----- +bool TransactionId::operator!=(const TransactionId& other) const +{ + return !operator==(other); +} + //----- std::unique_ptr TransactionId::toProtobuf() const { diff --git a/sdk/main/src/TransactionReceiptQuery.cc b/sdk/main/src/TransactionReceiptQuery.cc index f737e6926..29e43b162 100644 --- a/sdk/main/src/TransactionReceiptQuery.cc +++ b/sdk/main/src/TransactionReceiptQuery.cc @@ -50,23 +50,6 @@ TransactionReceiptQuery& TransactionReceiptQuery::setIncludeDuplicates(bool dupl return *this; } -//----- -proto::Query TransactionReceiptQuery::makeRequest(const Client&, const std::shared_ptr&) const -{ - proto::Query query; - proto::TransactionGetReceiptQuery* getTransactionReceiptQuery = query.mutable_transactiongetreceipt(); - - proto::QueryHeader* header = getTransactionReceiptQuery->mutable_header(); - header->set_responsetype(proto::ANSWER_ONLY); - - // This is a free query, so no payment required - getTransactionReceiptQuery->set_allocated_transactionid(mTransactionId->toProtobuf().release()); - getTransactionReceiptQuery->set_include_child_receipts(mIncludeChildren); - getTransactionReceiptQuery->set_includeduplicates(mIncludeDuplicates); - - return query; -} - //----- TransactionReceipt TransactionReceiptQuery::mapResponse(const proto::Response& response) const { @@ -74,9 +57,12 @@ TransactionReceipt TransactionReceiptQuery::mapResponse(const proto::Response& r } //----- -Status TransactionReceiptQuery::mapResponseStatus(const proto::Response& response) const +grpc::Status TransactionReceiptQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return gProtobufResponseCodeToStatus.at(response.transactiongetreceipt().header().nodetransactionprecheckcode()); + return node->submitQuery(proto::Query::QueryCase::kTransactionGetReceipt, request, deadline, response); } //----- @@ -87,38 +73,63 @@ TransactionReceiptQuery::determineStatus(Status status, const Client& client, co baseStatus = Executable::determineStatus( status, client, response); - baseStatus == ExecutionStatus::SERVER_ERROR || baseStatus == ExecutionStatus::REQUEST_ERROR) + baseStatus == ExecutionStatus::SERVER_ERROR) { - if (status == Status::RECEIPT_NOT_FOUND) - { - return ExecutionStatus::RETRY; - } - return baseStatus; } - // TransactionReceiptQuery should wait until the receipt is actually generated. That status data is contained in the - // protobuf receipt. - switch (gProtobufResponseCodeToStatus.at(response.transactiongetreceipt().receipt().status())) + switch (status) { case Status::BUSY: case Status::UNKNOWN: case Status::RECEIPT_NOT_FOUND: - case Status::OK: + case Status::RECORD_NOT_FOUND: return ExecutionStatus::RETRY; + + case Status::OK: + { + switch (gProtobufResponseCodeToStatus.at(response.transactiongetreceipt().receipt().status())) + { + case Status::BUSY: + case Status::UNKNOWN: + case Status::OK: + case Status::RECEIPT_NOT_FOUND: + case Status::RECORD_NOT_FOUND: + return ExecutionStatus::RETRY; + default: + return ExecutionStatus::SUCCESS; + } + } + default: - return ExecutionStatus::SUCCESS; + return ExecutionStatus::REQUEST_ERROR; } } //----- -grpc::Status TransactionReceiptQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::Query TransactionReceiptQuery::buildRequest(proto::QueryHeader* header) const +{ + auto transactionGetReceiptQuery = std::make_unique(); + transactionGetReceiptQuery->set_allocated_header(header); + + if (mTransactionId.has_value()) + { + transactionGetReceiptQuery->set_allocated_transactionid(mTransactionId->toProtobuf().release()); + } + + transactionGetReceiptQuery->set_includeduplicates(mIncludeDuplicates); + transactionGetReceiptQuery->set_include_child_receipts(mIncludeChildren); + + proto::Query query; + query.set_allocated_transactiongetreceipt(transactionGetReceiptQuery.release()); + return query; +} + +//----- +proto::ResponseHeader TransactionReceiptQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kTransactionGetReceipt, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.transactiongetreceipt().header()); + return response.transactiongetreceipt().header(); } } // namespace Hedera diff --git a/sdk/main/src/TransactionRecordQuery.cc b/sdk/main/src/TransactionRecordQuery.cc index ea20197b3..e2fdb4344 100644 --- a/sdk/main/src/TransactionRecordQuery.cc +++ b/sdk/main/src/TransactionRecordQuery.cc @@ -18,10 +18,8 @@ * */ #include "TransactionRecordQuery.h" -#include "Client.h" #include "Status.h" #include "TransactionRecord.h" -#include "TransferTransaction.h" #include "impl/Node.h" #include @@ -40,30 +38,6 @@ TransactionRecordQuery& TransactionRecordQuery::setTransactionId(const Transacti return *this; } -//----- -proto::Query TransactionRecordQuery::makeRequest(const Client& client, - const std::shared_ptr& node) const -{ - proto::Query query; - proto::TransactionGetRecordQuery* getTransactionRecordQuery = query.mutable_transactiongetrecord(); - - proto::QueryHeader* header = getTransactionRecordQuery->mutable_header(); - header->set_responsetype(proto::ResponseType::ANSWER_ONLY); - - TransferTransaction tx = TransferTransaction() - .setTransactionId(TransactionId::generate(*client.getOperatorAccountId())) - .setNodeAccountIds({ node->getAccountId() }) - .setMaxTransactionFee(Hbar(1LL)) - .addHbarTransfer(*client.getOperatorAccountId(), Hbar(-1LL)) - .addHbarTransfer(node->getAccountId(), Hbar(1LL)); - tx.onSelectNode(node); - header->set_allocated_payment(new proto::Transaction(tx.makeRequest(client, node))); - - getTransactionRecordQuery->set_allocated_transactionid(mTransactionId->toProtobuf().release()); - - return query; -} - //----- TransactionRecord TransactionRecordQuery::mapResponse(const proto::Response& response) const { @@ -71,9 +45,12 @@ TransactionRecord TransactionRecordQuery::mapResponse(const proto::Response& res } //----- -Status TransactionRecordQuery::mapResponseStatus(const proto::Response& response) const +grpc::Status TransactionRecordQuery::submitRequest(const proto::Query& request, + const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, + proto::Response* response) const { - return gProtobufResponseCodeToStatus.at(response.transactiongetrecord().header().nodetransactionprecheckcode()); + return node->submitQuery(proto::Query::QueryCase::kTransactionGetRecord, request, deadline, response); } //----- @@ -84,38 +61,65 @@ TransactionRecordQuery::determineStatus(Status status, const Client& client, con baseStatus = Executable::determineStatus( status, client, response); - baseStatus == ExecutionStatus::SERVER_ERROR || baseStatus == ExecutionStatus::REQUEST_ERROR) + baseStatus == ExecutionStatus::SERVER_ERROR) { - if (status == Status::RECORD_NOT_FOUND) - { - return ExecutionStatus::RETRY; - } - return baseStatus; } - // TransactionRecordQuery should wait until the receipt is actually generated. That status data is contained in the - // protobuf receipt. - switch (gProtobufResponseCodeToStatus.at(response.transactiongetrecord().transactionrecord().receipt().status())) + switch (status) { case Status::BUSY: case Status::UNKNOWN: + case Status::RECEIPT_NOT_FOUND: case Status::RECORD_NOT_FOUND: - case Status::OK: return ExecutionStatus::RETRY; + + case Status::OK: + { + if (isCostQuery()) + { + return ExecutionStatus::SUCCESS; + } + + switch (gProtobufResponseCodeToStatus.at(response.transactiongetrecord().transactionrecord().receipt().status())) + { + case Status::BUSY: + case Status::UNKNOWN: + case Status::OK: + case Status::RECEIPT_NOT_FOUND: + case Status::RECORD_NOT_FOUND: + return ExecutionStatus::RETRY; + default: + return ExecutionStatus::SUCCESS; + } + } + default: - return ExecutionStatus::SUCCESS; + return ExecutionStatus::REQUEST_ERROR; } } //----- -grpc::Status TransactionRecordQuery::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, - const std::shared_ptr& node, - proto::Response* response) const +proto::Query TransactionRecordQuery::buildRequest(proto::QueryHeader* header) const +{ + auto transactionGetRecordQuery = std::make_unique(); + transactionGetRecordQuery->set_allocated_header(header); + + if (mTransactionId.has_value()) + { + transactionGetRecordQuery->set_allocated_transactionid(mTransactionId->toProtobuf().release()); + } + + proto::Query query; + query.set_allocated_transactiongetrecord(transactionGetRecordQuery.release()); + return query; +} + +//----- +proto::ResponseHeader TransactionRecordQuery::mapResponseHeader(const proto::Response& response) const { - return node->submitQuery( - proto::Query::QueryCase::kTransactionGetRecord, makeRequest(client, node), deadline, response); + saveCostFromHeader(response.transactiongetrecord().header()); + return response.transactiongetrecord().header(); } } // namespace Hedera diff --git a/sdk/main/src/TransferTransaction.cc b/sdk/main/src/TransferTransaction.cc index 864f6c277..1255f03f5 100644 --- a/sdk/main/src/TransferTransaction.cc +++ b/sdk/main/src/TransferTransaction.cc @@ -27,52 +27,19 @@ namespace Hedera { - //----- TransferTransaction::TransferTransaction(const proto::TransactionBody& transactionBody) : Transaction(transactionBody) { - if (!transactionBody.has_cryptotransfer()) - { - throw std::invalid_argument("Transaction body doesn't contain CryptoTransfer data"); - } - - const proto::CryptoTransferTransactionBody& body = transactionBody.cryptotransfer(); - - for (int i = 0; i < body.transfers().accountamounts_size(); ++i) - { - const proto::AccountAmount& accountAmount = body.transfers().accountamounts(i); - mHbarTransfers.push_back(HbarTransfer() - .setAccountId(AccountId::fromProtobuf(accountAmount.accountid())) - .setAmount(Hbar(accountAmount.amount(), HbarUnit::TINYBAR())) - .setApproved(accountAmount.is_approval())); - } - - for (int i = 0; i < body.tokentransfers_size(); ++i) - { - const proto::TokenTransferList& transfer = body.tokentransfers(i); - const TokenId tokenId = TokenId::fromProtobuf(transfer.token()); - - for (int j = 0; j < transfer.transfers_size(); ++j) - { - const proto::AccountAmount& accountAmount = transfer.transfers(j); - mTokenTransfers.emplace_back(tokenId, - AccountId::fromProtobuf(accountAmount.accountid()), - accountAmount.amount(), - transfer.expected_decimals().value(), - accountAmount.is_approval()); - } + initFromSourceTransactionBody(); +} - for (int j = 0; j < transfer.nfttransfers_size(); ++j) - { - const proto::NftTransfer& nftTransfer = transfer.nfttransfers(j); - mNftTransfers.push_back(TokenNftTransfer() - .setNftId(NftId(tokenId, static_cast(nftTransfer.serialnumber()))) - .setSenderAccountId(AccountId::fromProtobuf(nftTransfer.senderaccountid())) - .setReceiverAccountId(AccountId::fromProtobuf(nftTransfer.receiveraccountid())) - .setApproval(nftTransfer.is_approval())); - } - } +//----- +TransferTransaction::TransferTransaction( + const std::map>& transactions) + : Transaction(transactions) +{ + initFromSourceTransactionBody(); } //----- @@ -225,19 +192,12 @@ std::unordered_map TransferTransaction::getTokenIdDecimals() } //----- -proto::Transaction TransferTransaction::makeRequest(const Client& client, const std::shared_ptr&) const -{ - return signTransaction(generateTransactionBody(&client), client); -} - -//----- -grpc::Status TransferTransaction::submitRequest(const Client& client, - const std::chrono::system_clock::time_point& deadline, +grpc::Status TransferTransaction::submitRequest(const proto::Transaction& request, const std::shared_ptr& node, + const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) const { - return node->submitTransaction( - proto::TransactionBody::DataCase::kCryptoTransfer, makeRequest(client, node), deadline, response); + return node->submitTransaction(proto::TransactionBody::DataCase::kCryptoTransfer, request, deadline, response); } //----- @@ -246,6 +206,54 @@ void TransferTransaction::addToBody(proto::TransactionBody& body) const body.set_allocated_cryptotransfer(build()); } +//----- +void TransferTransaction::initFromSourceTransactionBody() +{ + const proto::TransactionBody transactionBody = getSourceTransactionBody(); + + if (!transactionBody.has_cryptotransfer()) + { + throw std::invalid_argument("Transaction body doesn't contain CryptoTransfer data"); + } + + const proto::CryptoTransferTransactionBody& body = transactionBody.cryptotransfer(); + + for (int i = 0; i < body.transfers().accountamounts_size(); ++i) + { + const proto::AccountAmount& accountAmount = body.transfers().accountamounts(i); + mHbarTransfers.push_back(HbarTransfer() + .setAccountId(AccountId::fromProtobuf(accountAmount.accountid())) + .setAmount(Hbar(accountAmount.amount(), HbarUnit::TINYBAR())) + .setApproved(accountAmount.is_approval())); + } + + for (int i = 0; i < body.tokentransfers_size(); ++i) + { + const proto::TokenTransferList& transfer = body.tokentransfers(i); + const TokenId tokenId = TokenId::fromProtobuf(transfer.token()); + + for (int j = 0; j < transfer.transfers_size(); ++j) + { + const proto::AccountAmount& accountAmount = transfer.transfers(j); + mTokenTransfers.emplace_back(tokenId, + AccountId::fromProtobuf(accountAmount.accountid()), + accountAmount.amount(), + transfer.expected_decimals().value(), + accountAmount.is_approval()); + } + + for (int j = 0; j < transfer.nfttransfers_size(); ++j) + { + const proto::NftTransfer& nftTransfer = transfer.nfttransfers(j); + mNftTransfers.push_back(TokenNftTransfer() + .setNftId(NftId(tokenId, static_cast(nftTransfer.serialnumber()))) + .setSenderAccountId(AccountId::fromProtobuf(nftTransfer.senderaccountid())) + .setReceiverAccountId(AccountId::fromProtobuf(nftTransfer.receiveraccountid())) + .setApproval(nftTransfer.is_approval())); + } + } +} + //----- proto::CryptoTransferTransactionBody* TransferTransaction::build() const { diff --git a/sdk/main/src/WrappedTransaction.cc b/sdk/main/src/WrappedTransaction.cc index 540b1e823..be2926a0f 100644 --- a/sdk/main/src/WrappedTransaction.cc +++ b/sdk/main/src/WrappedTransaction.cc @@ -20,6 +20,7 @@ #include "WrappedTransaction.h" #include "exceptions/UninitializedException.h" +#include #include namespace Hedera @@ -394,125 +395,245 @@ std::unique_ptr WrappedTransaction::toProtobuf() const switch (getTransactionType()) { case ACCOUNT_ALLOWANCE_APPROVE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case ACCOUNT_ALLOWANCE_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case ACCOUNT_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case ACCOUNT_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case ACCOUNT_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case CONTRACT_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case CONTRACT_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case CONTRACT_EXECUTE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case CONTRACT_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case ETHEREUM_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case FILE_APPEND_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case FILE_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case FILE_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case FILE_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case FREEZE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case SCHEDULE_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case SCHEDULE_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case SCHEDULE_SIGN_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case SYSTEM_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case SYSTEM_UNDELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_ASSOCIATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_BURN_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_DISSOCIATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_FEE_SCHEDULE_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_FREEZE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_GRANT_KYC_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_MINT_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_PAUSE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_REVOKE_KYC_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_UNFREEZE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_UNPAUSE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOKEN_WIPE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOPIC_CREATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOPIC_DELETE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOPIC_MESSAGE_SUBMIT_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TOPIC_UPDATE_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } case TRANSFER_TRANSACTION: - return std::make_unique( - getTransaction()->generateTransactionBody(nullptr)); + { + const auto transaction = getTransaction(); + transaction->updateSourceTransactionBody(nullptr); + return std::make_unique(transaction->getSourceTransactionBody()); + } default: { throw UninitializedException("WrappedTransaction doesn't contain a Transaction"); diff --git a/sdk/main/src/impl/BaseNetwork.cc b/sdk/main/src/impl/BaseNetwork.cc new file mode 100644 index 000000000..cc5ac2b45 --- /dev/null +++ b/sdk/main/src/impl/BaseNetwork.cc @@ -0,0 +1,288 @@ +/*- + * + * 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 "impl/BaseNetwork.h" +#include "AccountId.h" +#include "impl/BaseNodeAddress.h" +#include "impl/MirrorNetwork.h" +#include "impl/MirrorNode.h" +#include "impl/Network.h" +#include "impl/Node.h" +#include "impl/Utilities.h" + +#include + +namespace Hedera::internal +{ +//----- +template +NetworkType& BaseNetwork::setNetwork( + const std::unordered_map& network) +{ + // New containers to hold new network. + std::unordered_map>> newNetwork; + std::unordered_set> newNodes; + + // Go through each entry in the new network list and either move the NodeType that already exists for that entry to + // the newNodes list, or create a new NodeType for that entry. + for (const auto& [address, key] : network) + { + // Determine if this entry already has a NodeType. + bool entryAlreadyExists = false; + for (const auto& node : mNodes) + { + if (node->getAddress().toString() == address && node->getKey() == key) + { + // Move this node to the newNodes set and go to the next entry. + mNodes.erase(node); + newNodes.insert(node); + newNetwork[key].insert(node); + entryAlreadyExists = true; + break; + } + } + + // If the entry was found, go to the next entry. + if (entryAlreadyExists) + { + continue; + } + + // If an entry doesn't exist, create one and add it to the nodes lists and network. + const std::shared_ptr newNode = createNodeFromNetworkEntry(address, key); + newNodes.insert(newNode); + newNetwork[key].insert(newNode); + } + + // The remaining nodes in mNodes need to be closed and removed. + for (const std::shared_ptr& node : mNodes) + { + node->close(); + removeNodeFromNetwork(node); + } + + // Set the new nodes list and network. + mNodes = newNodes; + mNetwork = newNetwork; + mHealthyNodes.clear(); + + readmitNodes(); + + return static_cast(*this); +} + +//----- +template +void BaseNetwork::increaseBackoff(const std::shared_ptr& node) +{ + node->increaseBackoff(); + mHealthyNodes.erase(node); +} + +//----- +template +void BaseNetwork::decreaseBackoff(const std::shared_ptr& node) const +{ + node->decreaseBackoff(); +} + +//----- +template +std::vector> BaseNetwork::getNodeProxies(const KeyType& key) +{ + readmitNodes(); + return { mNetwork[key].cbegin(), mNetwork[key].cend() }; +} + +//----- +template +void BaseNetwork::close() const +{ + for (const std::shared_ptr& node : mNodes) + { + node->close(); + } +} + +//----- +template +NetworkType& BaseNetwork::setMaxNodeAttempts(unsigned int attempts) +{ + mMaxNodeAttempts = attempts; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setMinNodeBackoff( + const std::chrono::duration& backoff) +{ + mMinNodeBackoff = backoff; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setMaxNodeBackoff( + const std::chrono::duration& backoff) +{ + mMaxNodeBackoff = backoff; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setMinNodeReadmitTime( + const std::chrono::duration& time) +{ + mMinNodeReadmitTime = time; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setMaxNodeReadmitTime( + const std::chrono::duration& time) +{ + mMaxNodeReadmitTime = time; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setCloseTimeout(const std::chrono::duration& timeout) +{ + mCloseTimeout = timeout; + return static_cast(*this); +} + +//----- +template +NetworkType& BaseNetwork::setLedgerId(const LedgerId& ledgerId) +{ + mLedgerId = ledgerId; + return static_cast(*this); +} + +//----- +template +std::vector> BaseNetwork::getNumberOfMostHealthyNodes( + unsigned int count) +{ + // First, remove any nodes from the network that have exceeded the maximum number of node attempts. + if (mMaxNodeAttempts > 0U) + { + auto nodeIter = mNodes.begin(); + while (nodeIter != mNodes.end()) + { + if ((*nodeIter)->getBadGrpcStatusCount() >= mMaxNodeAttempts) + { + (*nodeIter)->close(); + removeNodeFromNetwork(*nodeIter); + } + else + { + ++nodeIter; + } + } + } + + std::unordered_set> nodes; + while (count > nodes.size()) + { + // Readmit nodes each time one is fetched. Since readmitting only happens periodically, calling this each time + // should not have a significant impact on performance. + readmitNodes(); + + // If there are no healthy nodes, wait until one can be readmitted. + if (mHealthyNodes.empty()) + { + std::this_thread::sleep_for(mEarliestReadmitTime - std::chrono::system_clock::now()); + continue; + } + + // Add a random node (it won't be added if its repeated). + auto iter = mHealthyNodes.cbegin(); + std::advance(iter, internal::Utilities::getRandomNumber(0U, static_cast(mHealthyNodes.size()) - 1U)); + nodes.insert(*iter); + } + + return { nodes.cbegin(), nodes.cend() }; +} + +//----- +template +void BaseNetwork::setTransportSecurityInternal(TLSBehavior tls) +{ + mTransportSecurity = tls; +} + +//----- +template +void BaseNetwork::readmitNodes() +{ + const std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + + // Do nothing if the time for node re-admittance hasn't been reached yet. + if (now <= mEarliestReadmitTime) + { + return; + } + + // Determine the next earliest readmit time. + std::chrono::system_clock::time_point nextEarliestReadmitTime = + now + std::chrono::duration_cast(mMaxNodeReadmitTime); + + for (const auto& node : mNodes) + { + if (node->getReadmitTime() > now && node->getReadmitTime() < nextEarliestReadmitTime) + { + nextEarliestReadmitTime = node->getReadmitTime(); + } + } + + // Set the next earliest readmit time. + mEarliestReadmitTime = nextEarliestReadmitTime; + + // Readmit nodes as healthy if they're passed their readmit time. + for (const auto& node : mNodes) + { + if (mHealthyNodes.find(node) == mHealthyNodes.end() && node->getReadmitTime() <= now) + { + mHealthyNodes.insert(node); + } + } +} + +//----- +template +void BaseNetwork::removeNodeFromNetwork(const std::shared_ptr& node) +{ + mNetwork[node->getKey()].erase(node); + mNodes.erase(node); + mHealthyNodes.erase(node); +} + +/** + * Explicit template instantiations. + */ +template class BaseNetwork; +template class BaseNetwork; + +} // namespace Hedera::internal diff --git a/sdk/main/src/impl/BaseNode.cc b/sdk/main/src/impl/BaseNode.cc new file mode 100644 index 000000000..c13f06a56 --- /dev/null +++ b/sdk/main/src/impl/BaseNode.cc @@ -0,0 +1,179 @@ +/*- + * + * 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 "impl/BaseNode.h" +#include "impl/BaseNodeAddress.h" +#include "impl/HederaCertificateVerifier.h" +#include "impl/MirrorNode.h" +#include "impl/Node.h" + +#include +#include +#include +#include + +namespace Hedera::internal +{ +//----- +template +void BaseNode::close() +{ + closeStubs(); + + // The connection is closed automatically upon destruction of the channel. + mChannel = nullptr; +} + +//----- +template +void BaseNode::increaseBackoff() +{ + ++mBadGrpcStatusCount; + mReadmitTime = + std::chrono::system_clock::now() + std::chrono::duration_cast(mCurrentBackoff); + mCurrentBackoff *= 2.0; + + // Make sure the current backoff doesn't go over the max backoff. + if (mCurrentBackoff > mMaxNodeBackoff) + { + mCurrentBackoff = mMaxNodeBackoff; + } +} + +//----- +template +void BaseNode::decreaseBackoff() +{ + mCurrentBackoff /= 2.0; + + // Make sure the current backoff doesn't go below the min backoff. + if (mCurrentBackoff < mMinNodeBackoff) + { + mCurrentBackoff = mMinNodeBackoff; + } +} + +//----- +template +bool BaseNode::isHealthy() const +{ + return mReadmitTime < std::chrono::system_clock::now(); +} + +//----- +template +bool BaseNode::channelFailedToConnect() +{ + if (mIsConnected) + { + return false; + } + + const std::chrono::system_clock::time_point timeoutTime = std::chrono::system_clock::now() + GET_STATE_TIMEOUT; + mIsConnected = getChannel()->WaitForConnected(timeoutTime); + + return !mIsConnected; +} + +//----- +template +std::chrono::duration BaseNode::getRemainingTimeForBackoff() const +{ + return mReadmitTime - std::chrono::system_clock::now(); +} + +//----- +template +NodeType& BaseNode::setMinNodeBackoff(const std::chrono::duration& backoff) +{ + if (mCurrentBackoff == mMinNodeBackoff) + { + mCurrentBackoff = backoff; + } + + mMinNodeBackoff = backoff; + return static_cast(*this); +} + +//----- +template +NodeType& BaseNode::setMaxNodeBackoff(const std::chrono::duration& backoff) +{ + mMaxNodeBackoff = backoff; + return static_cast(*this); +} + +//----- +template +BaseNode::BaseNode(BaseNodeAddress address) + : mAddress(std::move(address)) +{ +} + +//----- +template +NodeType& BaseNode::setAddress(const BaseNodeAddress& address) +{ + // Close the connection since the address is changing. + close(); + + mAddress = address; + return static_cast(*this); +} + +//----- +template +std::shared_ptr BaseNode::getChannel() +{ + if (!mChannel) + { + grpc::ChannelArguments channelArguments; + channelArguments.SetInt(GRPC_ARG_ENABLE_RETRIES, 0); + channelArguments.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000); + channelArguments.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); + + if (const std::string authority = getAuthority(); !authority.empty()) + { + channelArguments.SetString(GRPC_ARG_DEFAULT_AUTHORITY, authority); + } + + mChannel = grpc::CreateCustomChannel(mAddress.toString(), + mAddress.isTransportSecurity() ? getTlsChannelCredentials() + : grpc::InsecureChannelCredentials(), + channelArguments); + initializeStubs(mChannel); + } + + return mChannel; +} + +//----- +template +std::shared_ptr BaseNode::getTlsChannelCredentials() const +{ + return grpc::experimental::TlsCredentials(grpc::experimental::TlsChannelCredentialsOptions()); +} + +/** + * Explicit template instantiations. + */ +template class BaseNode; +template class BaseNode; + +} // namespace Hedera::internal diff --git a/sdk/main/src/impl/BaseNodeAddress.cc b/sdk/main/src/impl/BaseNodeAddress.cc new file mode 100644 index 000000000..0a0fd9104 --- /dev/null +++ b/sdk/main/src/impl/BaseNodeAddress.cc @@ -0,0 +1,88 @@ +/*- + * + * 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 "impl/BaseNodeAddress.h" + +#include +#include + +namespace Hedera::internal +{ +//----- +BaseNodeAddress::BaseNodeAddress(std::string_view name, std::string_view address, unsigned int port) + : mName(name) + , mAddress(address) + , mPort(port) +{ +} + +//----- +BaseNodeAddress BaseNodeAddress::fromString(std::string_view address) +{ + if (const std::string_view inProcessPrefix = "in-process:"; address.find(inProcessPrefix) == 0ULL) + { + address.remove_prefix(inProcessPrefix.size()); + return BaseNodeAddress(address, "", 0U); + } + + const size_t colonIndex = address.find(':'); + if (colonIndex == std::string::npos) + { + throw std::invalid_argument("Input BaseNodeAddress is malformed"); + } + + const std::string_view ipAddressV4 = address.substr(0, colonIndex); + const std::string_view portStr = address.substr(colonIndex + 1, address.size() - colonIndex - 1); + unsigned int port; + if (const auto result = std::from_chars(portStr.data(), portStr.data() + portStr.size(), port); + result.ptr != portStr.data() + portStr.size() || result.ec != std::errc()) + { + throw std::invalid_argument("Input BaseNodeAddress is malformed"); + } + + return BaseNodeAddress("", ipAddressV4, port); +} + +//----- +bool BaseNodeAddress::operator==(const BaseNodeAddress& other) const +{ + return (!mName.empty()) ? (mName == other.mName) : ((mAddress == other.mAddress) && (mPort == other.mPort)); +} + +//----- +BaseNodeAddress BaseNodeAddress::toSecure() const +{ + return BaseNodeAddress( + mName, mAddress, (mPort == PORT_MIRROR_PLAIN || mPort == PORT_MIRROR_TLS) ? PORT_MIRROR_TLS : PORT_NODE_TLS); +} + +//----- +BaseNodeAddress BaseNodeAddress::toInsecure() const +{ + return BaseNodeAddress( + mName, mAddress, (mPort == PORT_MIRROR_PLAIN || mPort == PORT_MIRROR_TLS) ? PORT_MIRROR_PLAIN : PORT_NODE_PLAIN); +} + +//----- +std::string BaseNodeAddress::toString() const +{ + return (!mName.empty()) ? "in-process:" + mName : mAddress + ':' + std::to_string(mPort); +} + +} // namespace Hedera::internal diff --git a/sdk/main/src/impl/Endpoint.cc b/sdk/main/src/impl/Endpoint.cc index 586d322d7..d90a208c2 100644 --- a/sdk/main/src/impl/Endpoint.cc +++ b/sdk/main/src/impl/Endpoint.cc @@ -18,40 +18,47 @@ * */ #include "impl/Endpoint.h" +#include "impl/Utilities.h" #include -#include namespace Hedera::internal { //----- Endpoint Endpoint::fromProtobuf(const proto::ServiceEndpoint& protoServiceEndpoint) { - return { IPv4Address::fromString(protoServiceEndpoint.ipaddressv4()), - static_cast(protoServiceEndpoint.port() & 0x00000000ffffffffL) }; + return Endpoint() + .setAddress(IPv4Address::fromBytes(Utilities::stringToByteVector(protoServiceEndpoint.ipaddressv4()))) + .setPort(static_cast(protoServiceEndpoint.port())); } //----- -Endpoint::Endpoint(const IPv4Address& ipAddressV4, int port) - : mAddress(ipAddressV4) - , mPort(port) +std::unique_ptr Endpoint::toProtobuf() const { - // TODO: here we change the port to the TLS port, since the existing serialization of the testnet address book doesn't - // include TLS endpoints. Once we have an up to date serialization, remove this - if (mPort == 50211) - { - mPort = 50212; - } + auto proto = std::make_unique(); + proto->set_ipaddressv4(Utilities::byteVectorToString(mAddress.toBytes())); + proto->set_port(static_cast(mPort)); + return proto; } //----- std::string Endpoint::toString() const { - std::stringstream outputStream; + return mAddress.toString() + ':' + std::to_string(mPort); +} - outputStream << mAddress.toString() << ":" << mPort; +//----- +Endpoint& Endpoint::setAddress(const IPv4Address& address) +{ + mAddress = address; + return *this; +} - return outputStream.str(); +//----- +Endpoint& Endpoint::setPort(unsigned int port) +{ + mPort = port; + return *this; } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/HederaCertificateVerifier.cc b/sdk/main/src/impl/HederaCertificateVerifier.cc index 49deb918b..2c7236c1e 100644 --- a/sdk/main/src/impl/HederaCertificateVerifier.cc +++ b/sdk/main/src/impl/HederaCertificateVerifier.cc @@ -43,10 +43,11 @@ bool HederaCertificateVerifier::Verify(grpc::experimental::TlsCustomVerification { *sync_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "Hash of node certificate chain doesn't match hash contained in address book"); - return true; } - - *sync_status = grpc::Status(grpc::StatusCode::OK, "Certificate chain hash matches expected"); + else + { + *sync_status = grpc::Status(grpc::StatusCode::OK, "Certificate chain hash matches expected"); + } // always true, since this is called synchronously return true; diff --git a/sdk/main/src/impl/IPv4Address.cc b/sdk/main/src/impl/IPv4Address.cc index d8bae33c2..6d6dcc382 100644 --- a/sdk/main/src/impl/IPv4Address.cc +++ b/sdk/main/src/impl/IPv4Address.cc @@ -18,57 +18,37 @@ * */ #include "impl/IPv4Address.h" -#include "impl/Utilities.h" -#include -#include -#include +#include namespace Hedera::internal { -IPv4Address::IPv4Address(std::byte octet1, std::byte octet2, std::byte octet3, std::byte octet4) - : mOctet1(octet1) - , mOctet2(octet2) - , mOctet3(octet3) - , mOctet4(octet4) +//----- +IPv4Address IPv4Address::fromBytes(const std::vector& bytes) { -} - -IPv4Address IPv4Address::fromString(std::string_view address) -{ - // The input string is in byte format, where each byte represents a single IP address octet. - if (address.size() == 4) + if (bytes.size() != 4) { - const std::vector byteVector = Utilities::stringToByteVector(address); - return { byteVector.at(0), byteVector.at(1), byteVector.at(2), byteVector.at(3) }; + throw std::invalid_argument("Incorrect byte array size, should be 4 bytes but is " + std::to_string(bytes.size())); } - try - { - std::vector byteVector; - std::string_view octet; - for (int i = 0; i < 3; ++i) - { - octet = address.substr(0, address.find_first_of('.')); - byteVector.push_back(Utilities::stringToByte(octet)); - address.remove_prefix(octet.size() + 1); - } + IPv4Address iPv4Address; + std::copy(bytes.cbegin(), bytes.cend(), iPv4Address.mAddress.begin()); + return iPv4Address; +} - byteVector.push_back(Utilities::stringToByte(address)); - return { byteVector.at(0), byteVector.at(1), byteVector.at(2), byteVector.at(3) }; - } - catch (const std::exception&) - { - throw std::invalid_argument("Input IPv4Address is malformed"); - } +//----- +std::vector IPv4Address::toBytes() const +{ + return { mAddress.at(0), mAddress.at(1), mAddress.at(2), mAddress.at(3) }; } +//----- std::string IPv4Address::toString() const { - return std::to_string(std::to_integer(mOctet1)) + '.' + - std::to_string(std::to_integer(mOctet2)) + '.' + - std::to_string(std::to_integer(mOctet3)) + '.' + - std::to_string(std::to_integer(mOctet4)); + return std::to_string(std::to_integer(mAddress.at(0))) + '.' + + std::to_string(std::to_integer(mAddress.at(1))) + '.' + + std::to_string(std::to_integer(mAddress.at(2))) + '.' + + std::to_string(std::to_integer(mAddress.at(3))); } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/MirrorNetwork.cc b/sdk/main/src/impl/MirrorNetwork.cc index fd31b3e19..56ce2d55e 100644 --- a/sdk/main/src/impl/MirrorNetwork.cc +++ b/sdk/main/src/impl/MirrorNetwork.cc @@ -19,8 +19,7 @@ */ #include "impl/MirrorNetwork.h" #include "impl/MirrorNode.h" - -#include +#include "impl/Utilities.h" namespace Hedera::internal { @@ -57,35 +56,48 @@ MirrorNetwork MirrorNetwork::forNetwork(const std::vector& networkM } //----- -std::shared_ptr MirrorNetwork::getNextMirrorNode() const +MirrorNetwork& MirrorNetwork::setNetwork(const std::vector& network) { - if (mNodes.empty()) + std::unordered_map networkMap; + for (const auto& address : network) { - return nullptr; + networkMap.try_emplace(address, BaseNodeAddress::fromString(address)); } - static std::random_device rd; - static std::mt19937 gen(rd()); - std::uniform_int_distribution distribution(0, static_cast(mNodes.size()) - 1); - return mNodes.at(distribution(gen)); + BaseNetwork::setNetwork(networkMap); + return *this; } //----- -void MirrorNetwork::close() const +std::vector MirrorNetwork::getNetwork() const { - for (const auto& node : mNodes) + std::vector network; + for (const auto& [address, nodes] : BaseNetwork::getNetworkInternal()) { - node->shutdown(); + network.push_back(address.toString()); } + + return network; } //----- -void MirrorNetwork::setNetwork(const std::vector& addresses) +std::shared_ptr MirrorNetwork::getNextMirrorNode() const { - for (const std::string& str : addresses) + if (getNodes().empty()) { - mNodes.push_back(std::make_shared(str)); + return nullptr; } + + auto nodeIter = getNodes().cbegin(); + std::advance(nodeIter, Utilities::getRandomNumber(0U, static_cast(getNodes().size()) - 1U)); + return *nodeIter; +} + +//----- +std::shared_ptr MirrorNetwork::createNodeFromNetworkEntry(std::string_view address, + const BaseNodeAddress&) const +{ + return std::make_shared(address); } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/MirrorNode.cc b/sdk/main/src/impl/MirrorNode.cc index 3fc1f0f67..91d725d69 100644 --- a/sdk/main/src/impl/MirrorNode.cc +++ b/sdk/main/src/impl/MirrorNode.cc @@ -18,93 +18,35 @@ * */ #include "impl/MirrorNode.h" -#include "exceptions/UninitializedException.h" -#include "impl/HederaCertificateVerifier.h" - -#include -#include +#include "impl/BaseNodeAddress.h" namespace Hedera::internal { //----- -MirrorNode::MirrorNode(std::string_view address) - : mAddress(address) -{ -} - -//----- -bool MirrorNode::connect(const std::chrono::system_clock::time_point& timeout) -{ - return mIsInitialized || initializeChannel(timeout); -} - -//----- -void MirrorNode::shutdown() -{ - mConsensusStub = nullptr; - mChannel = nullptr; - - mIsInitialized = false; -} - -//----- -void MirrorNode::setMinBackoff(const std::chrono::duration& backoff) -{ - mMinBackoff = backoff; -} - -//----- -void MirrorNode::setMaxBackoff(const std::chrono::duration& backoff) -{ - mMaxBackoff = backoff; -} - -//----- -bool MirrorNode::isHealthy() const -{ - return mReadmitTime < std::chrono::system_clock::now(); -} - -//----- -void MirrorNode::increaseBackoff() +MirrorNode::MirrorNode(const BaseNodeAddress& address) + : BaseNode(address) { - mReadmitTime = - std::chrono::system_clock::now() + std::chrono::duration_cast(mCurrentBackoff); - mCurrentBackoff = std::min(mCurrentBackoff * 2, mMaxBackoff); } //----- -void MirrorNode::decreaseBackoff() +MirrorNode::MirrorNode(std::string_view address) + : BaseNode(BaseNodeAddress::fromString(address)) { - mCurrentBackoff /= 2.0; - mCurrentBackoff = std::max(mCurrentBackoff / 2.0, mMinBackoff); } //----- -std::chrono::duration MirrorNode::getRemainingTimeForBackoff() const +void MirrorNode::initializeStubs(const std::shared_ptr& channel) { - return mReadmitTime - std::chrono::system_clock::now(); + if (!mConsensusStub) + { + mConsensusStub = com::hedera::mirror::api::proto::ConsensusService::NewStub(channel); + } } //----- -bool MirrorNode::initializeChannel(const std::chrono::system_clock::time_point& deadline) +void MirrorNode::closeStubs() { - shutdown(); - - grpc::ChannelArguments channelArguments; - channelArguments.SetInt(GRPC_ARG_ENABLE_RETRIES, 0); - channelArguments.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000); - channelArguments.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); - - mChannel = grpc::CreateCustomChannel(mAddress, grpc::InsecureChannelCredentials(), channelArguments); - - if (mChannel->WaitForConnected(deadline)) - { - mConsensusStub = com::hedera::mirror::api::proto::ConsensusService::NewStub(mChannel); - mIsInitialized = true; - } - - return mIsInitialized; + mConsensusStub = nullptr; } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/Network.cc b/sdk/main/src/impl/Network.cc index 65605ef89..0461e98c7 100644 --- a/sdk/main/src/impl/Network.cc +++ b/sdk/main/src/impl/Network.cc @@ -18,109 +18,197 @@ * */ #include "impl/Network.h" - #include "AccountId.h" +#include "impl/Endpoint.h" +#include "impl/NodeAddress.h" + +#include +#include +#include namespace Hedera::internal { //----- Network Network::forMainnet() { - Network network; - network.setNetwork(NodeAddressBook::fromFile("mainnet.pb")); - return network; + return getNetworkForLedgerId(LedgerId::MAINNET); } //----- Network Network::forTestnet() { - Network network; - network.setNetwork(NodeAddressBook::fromFile("testnet.pb")); - return network; + return getNetworkForLedgerId(LedgerId::TESTNET); } //----- Network Network::forPreviewnet() { - Network network; - network.setNetwork(NodeAddressBook::fromFile("previewnet.pb")); - return network; + return getNetworkForLedgerId(LedgerId::PREVIEWNET); } //----- Network Network::forNetwork(const std::unordered_map& networkMap) { - Network network; - network.setNetwork(networkMap); - return network; + return Network(networkMap); } //----- -std::vector> Network::getNodesWithAccountIds(const std::vector& accountIds) const +Network& Network::setLedgerId(const LedgerId& ledgerId) { - if (accountIds.empty()) - { - return mNodes; - } + return setLedgerIdInternal(ledgerId, getAddressBookForLedgerId(ledgerId)); +} + +//----- +Network& Network::setVerifyCertificates(bool verify) +{ + mVerifyCertificates = verify; - std::vector> nodesWithCorrectAccountIds; - for (const auto& node : mNodes) + // Set the new certificate verification policy for all Nodes on this Network. + std::for_each(getNodes().cbegin(), + getNodes().cend(), + [&verify](const std::shared_ptr& node) { node->setVerifyCertificates(verify); }); + + return *this; +} + +//----- +Network& Network::setMaxNodesPerRequest(unsigned int max) +{ + mMaxNodesPerRequest = max; + return *this; +} + +//----- +Network& Network::setTransportSecurity(TLSBehavior tls) +{ + if (isTransportSecurity() != tls) { - for (const auto& id : accountIds) + for (const std::shared_ptr& node : getNodes()) { - if (node->getAccountId() == id) + switch (tls) { - nodesWithCorrectAccountIds.push_back(node); + case TLSBehavior::REQUIRE: + { + node->toSecure(); + break; + } + case TLSBehavior::DISABLE: + { + node->toInsecure(); + break; + } + default: + { + // Unimplemented other TLSBehaviors. Do nothing for now. + } } } + + BaseNetwork::setTransportSecurityInternal(tls); } - return nodesWithCorrectAccountIds; + return *this; } //----- -void Network::close() const +std::vector Network::getNodeAccountIdsForExecute() { - for (const auto& node : mNodes) + std::vector accountIds; + for (const std::shared_ptr& node : getNumberOfMostHealthyNodes( + mMaxNodesPerRequest > 0U ? std::min(mMaxNodesPerRequest, static_cast(getNodes().size())) + : static_cast(std::ceil(static_cast(getNodes().size()) / 3.0)))) { - node->shutdown(); + accountIds.push_back(node->getAccountId()); } + + return accountIds; } -void Network::setTLSBehavior(TLSBehavior desiredBehavior) const +//----- +std::unordered_map Network::getNetwork() const { - for (const auto& node : mNodes) + std::unordered_map network; + for (const std::shared_ptr& node : getNodes()) { - node->setTLSBehavior(desiredBehavior); + network[node->getAddress().toString()] = node->getAccountId(); } + + return network; +} + +//----- +Network::Network(const std::unordered_map& network) +{ + setNetwork(network); } //----- -void Network::setNetwork(const NodeAddressBook& nodeAddressBook, TLSBehavior tls) +Network Network::getNetworkForLedgerId(const LedgerId& ledgerId) { - for (const auto& [accountId, nodeAddress] : nodeAddressBook.getAddressMap()) + const std::unordered_map addressBook = getAddressBookForLedgerId(ledgerId); + std::unordered_map network; + for (const auto& [accountId, nodeAddress] : addressBook) { - mNodes.push_back(std::make_shared(nodeAddress, tls)); + for (const auto& endpoint : nodeAddress.getEndpoints()) + { + if (endpoint.getPort() == BaseNodeAddress::PORT_NODE_PLAIN) + { + network[endpoint.toString()] = accountId; + } + } } + + return Network(network).setLedgerIdInternal(ledgerId, addressBook); } //----- -void Network::setNetwork(const std::unordered_map& networkMap, TLSBehavior tls) +std::unordered_map Network::getAddressBookForLedgerId(const LedgerId& ledgerId) { - std::unordered_map> addressMap; - - for (auto it = networkMap.cbegin(); it != networkMap.cend(); ++it) + // The address book can only be fetched for known Hedera networks. + if (!ledgerId.isKnownNetwork()) { - const std::string& nodeAddressAsString = it->first; - const AccountId& accountId = it->second; + return {}; + } + + std::ifstream infile(ledgerId.toString() + ".pb", std::ios_base::binary); + const NodeAddressBook addressBook = + NodeAddressBook::fromBytes({ std::istreambuf_iterator(infile), std::istreambuf_iterator() }); - NodeAddress nodeAddress = NodeAddress::fromString(nodeAddressAsString); - std::shared_ptr nodeAddressPtr = std::make_shared(nodeAddress); - nodeAddressPtr->setNodeAccountId(accountId); - addressMap.insert(std::pair>(accountId, nodeAddressPtr)); + std::unordered_map addresses; + for (const auto& nodeAddress : addressBook.getNodeAddresses()) + { + addresses[nodeAddress.getAccountId()] = nodeAddress; } - setNetwork(NodeAddressBook::fromAddressMap(addressMap), tls); + return addresses; +} + +//----- +std::shared_ptr Network::createNodeFromNetworkEntry(std::string_view address, const AccountId& key) const +{ + auto node = std::make_shared(key, address); + node->setVerifyCertificates(mVerifyCertificates); + return node; +} + +//----- +Network& Network::setLedgerIdInternal(const LedgerId& ledgerId, + const std::unordered_map& addressBook) +{ + // Set the ledger ID. + BaseNetwork::setLedgerId(ledgerId); + + // Update each Node's address book entry with the new address book. + std::for_each(getNodes().cbegin(), + getNodes().cend(), + [&addressBook](const std::shared_ptr& node) + { + node->setNodeCertificateHash(addressBook.empty() + ? std::vector() + : addressBook.at(node->getAccountId()).getCertHash()); + }); + + return *this; } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/Node.cc b/sdk/main/src/impl/Node.cc index f9e844192..68ad0d627 100644 --- a/sdk/main/src/impl/Node.cc +++ b/sdk/main/src/impl/Node.cc @@ -19,99 +19,25 @@ */ #include "impl/Node.h" #include "exceptions/UninitializedException.h" +#include "impl/BaseNodeAddress.h" #include "impl/HederaCertificateVerifier.h" #include -#include #include namespace Hedera::internal { //----- -Node::Node(std::shared_ptr address, TLSBehavior tls) - : mAddress(std::move(address)) +Node::Node(AccountId accountId, const BaseNodeAddress& address) + : BaseNode(address) + , mAccountId(std::move(accountId)) { - // In order to use TLS, a node certificate chain must be provided - if (tls == TLSBehavior::REQUIRE && mAddress->getNodeCertHash().empty()) - { - throw UninitializedException("NodeAddress has empty certificate chain hash for TLS connection"); - } - - grpc::experimental::TlsChannelCredentialsOptions tlsChannelCredentialsOptions; - - // Custom verification using the node's certificate chain hash - tlsChannelCredentialsOptions.set_verify_server_certs(false); - tlsChannelCredentialsOptions.set_check_call_host(false); - tlsChannelCredentialsOptions.set_certificate_verifier( - grpc::experimental::ExternalCertificateVerifier::Create(mAddress->getNodeCertHash())); - - // Feed in the root CA's file manually for Windows (this is a bug in the gRPC implementation and says here - // https://deploy-preview-763--grpc-io.netlify.app/docs/guides/auth/#using-client-side-ssltls that this needs to be - // specified manually). -#ifdef _WIN32 - tlsChannelCredentialsOptions.set_certificate_provider( - std::make_shared("roots.pem", -1)); - tlsChannelCredentialsOptions.watch_root_certs(); -#endif - - mTlsChannelCredentials = grpc::experimental::TlsCredentials(tlsChannelCredentialsOptions); -} - -//----- -bool Node::connect(const std::chrono::system_clock::time_point& timeout) -{ - return mIsInitialized || initializeChannel(timeout); } //----- -void Node::shutdown() +Node::Node(const AccountId& accountId, std::string_view address) + : Node(accountId, BaseNodeAddress::fromString(address)) { - if (mConsensusStub) - { - mConsensusStub.reset(); - } - - if (mCryptoStub) - { - mCryptoStub.reset(); - } - - if (mFileStub) - { - mFileStub.reset(); - } - - if (mFreezeStub) - { - mFreezeStub.reset(); - } - - if (mNetworkStub) - { - mNetworkStub.reset(); - } - - if (mScheduleStub) - { - mScheduleStub.reset(); - } - - if (mSmartContractStub) - { - mSmartContractStub.reset(); - } - - if (mTokenStub) - { - mTokenStub.reset(); - } - - if (mChannel) - { - mChannel.reset(); - } - - mIsInitialized = false; } //----- @@ -120,11 +46,6 @@ grpc::Status Node::submitQuery(proto::Query::QueryCase funcEnum, const std::chrono::system_clock::time_point& deadline, proto::Response* response) { - if (!connect(deadline)) - { - return grpc::Status::CANCELLED; - } - grpc::ClientContext context; context.set_deadline(deadline); @@ -176,11 +97,6 @@ grpc::Status Node::submitTransaction(proto::TransactionBody::DataCase funcEnum, const std::chrono::system_clock::time_point& deadline, proto::TransactionResponse* response) { - if (!connect(deadline)) - { - return grpc::Status::CANCELLED; - } - grpc::ClientContext context; context.set_deadline(deadline); @@ -277,136 +193,89 @@ grpc::Status Node::submitTransaction(proto::TransactionBody::DataCase funcEnum, } //----- -void Node::setTLSBehavior(TLSBehavior desiredBehavior) +Node& Node::toInsecure() { - if (desiredBehavior == mTLSBehavior) - { - return; - } - - // In order to use TLS, a node certificate chain must be provided - if (desiredBehavior == TLSBehavior::REQUIRE && mAddress->getNodeCertHash().empty()) - { - throw UninitializedException("NodeAddress has empty certificate chain hash for TLS connection"); - } - - mTLSBehavior = desiredBehavior; - shutdown(); + return BaseNode::setAddress(getAddress().toInsecure()); } //----- -void Node::setMinBackoff(const std::chrono::duration& backoff) +Node& Node::toSecure() { - mMinBackoff = backoff; + return BaseNode::setAddress(getAddress().toSecure()); } //----- -void Node::setMaxBackoff(const std::chrono::duration& backoff) +Node& Node::setNodeCertificateHash(const std::vector& hash) { - mMaxBackoff = backoff; + mNodeCertificateHash = hash; + return *this; } //----- -bool Node::isHealthy() const +Node& Node::setVerifyCertificates(bool verify) { - return mReadmitTime < std::chrono::system_clock::now(); + mVerifyCertificates = verify; + return *this; } //----- -void Node::increaseBackoff() +Node::Node(const Node& node, const BaseNodeAddress& address) + : BaseNode(address) + , mAccountId(node.mAccountId) + , mNodeCertificateHash(node.mNodeCertificateHash) + , mVerifyCertificates(node.mVerifyCertificates) { - mReadmitTime = - std::chrono::system_clock::now() + std::chrono::duration_cast(mCurrentBackoff); - mCurrentBackoff = std::min(mCurrentBackoff * 2, mMaxBackoff); } //----- -void Node::decreaseBackoff() +std::shared_ptr Node::getTlsChannelCredentials() const { - mCurrentBackoff /= 2.0; - mCurrentBackoff = std::max(mCurrentBackoff / 2.0, mMinBackoff); + grpc::experimental::TlsChannelCredentialsOptions tlsChannelCredentialsOptions; + + // Custom verification using the node's certificate chain hash + tlsChannelCredentialsOptions.set_verify_server_certs(false); + tlsChannelCredentialsOptions.set_check_call_host(false); + tlsChannelCredentialsOptions.set_certificate_verifier( + grpc::experimental::ExternalCertificateVerifier::Create(mNodeCertificateHash)); + + // Feed in the root CA's file manually for Windows (this is a bug in the gRPC implementation and says here + // https://deploy-preview-763--grpc-io.netlify.app/docs/guides/auth/#using-client-side-ssltls that this needs to be + // specified manually). +#ifdef _WIN32 + tlsChannelCredentialsOptions.set_certificate_provider( + std::make_shared("roots.pem", -1)); + tlsChannelCredentialsOptions.watch_root_certs(); +#endif + + return grpc::experimental::TlsCredentials(tlsChannelCredentialsOptions); } //----- -std::chrono::duration Node::getRemainingTimeForBackoff() const +void Node::initializeStubs(const std::shared_ptr& channel) { - return mReadmitTime - std::chrono::system_clock::now(); + // clang-format off + if (!mConsensusStub) mConsensusStub = proto::ConsensusService::NewStub(channel); + if (!mCryptoStub) mCryptoStub = proto::CryptoService::NewStub(channel); + if (!mFileStub) mFileStub = proto::FileService::NewStub(channel); + if (!mFreezeStub) mFreezeStub = proto::FreezeService::NewStub(channel); + if (!mNetworkStub) mNetworkStub = proto::NetworkService::NewStub(channel); + if (!mScheduleStub) mScheduleStub = proto::ScheduleService::NewStub(channel); + if (!mSmartContractStub) mSmartContractStub = proto::SmartContractService::NewStub(channel); + if (!mTokenStub) mTokenStub = proto::TokenService::NewStub(channel); + // clang-format on } //----- -bool Node::initializeChannel(const std::chrono::system_clock::time_point& deadline) +void Node::closeStubs() { - const std::vector> endpoints = mAddress->getEndpoints(); - - std::shared_ptr channelCredentials = nullptr; - - grpc::ChannelArguments channelArguments; - channelArguments.SetInt(GRPC_ARG_ENABLE_RETRIES, 0); - - for (const auto& endpoint : endpoints) - { - switch (mTLSBehavior) - { - case TLSBehavior::REQUIRE: - { - if (NodeAddress::isTlsPort(endpoint->getPort())) - { - channelArguments.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000); - channelArguments.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); - channelCredentials = mTlsChannelCredentials; - } - - break; - } - - case TLSBehavior::DISABLE: - { - if (NodeAddress::isNonTlsPort(endpoint->getPort())) - { - channelCredentials = grpc::InsecureChannelCredentials(); - } - - break; - } - - default: - { - continue; - } - } - - if (channelCredentials) - { - shutdown(); - - mChannel = grpc::CreateCustomChannel(endpoint->toString(), channelCredentials, channelArguments); - - if (mChannel->WaitForConnected(deadline)) - { - mConsensusStub = proto::ConsensusService::NewStub(mChannel); - mCryptoStub = proto::CryptoService::NewStub(mChannel); - mFileStub = proto::FileService::NewStub(mChannel); - mFreezeStub = proto::FreezeService::NewStub(mChannel); - mNetworkStub = proto::NetworkService::NewStub(mChannel); - mScheduleStub = proto::ScheduleService::NewStub(mChannel); - mSmartContractStub = proto::SmartContractService::NewStub(mChannel); - mTokenStub = proto::TokenService::NewStub(mChannel); - mIsInitialized = true; - - return true; - } - else - { - mChannel = nullptr; - } - } - else - { - channelCredentials = nullptr; - } - } - - return false; + mConsensusStub = nullptr; + mCryptoStub = nullptr; + mFileStub = nullptr; + mFreezeStub = nullptr; + mNetworkStub = nullptr; + mScheduleStub = nullptr; + mSmartContractStub = nullptr; + mTokenStub = nullptr; } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/NodeAddress.cc b/sdk/main/src/impl/NodeAddress.cc index eca19aab3..3e70e4415 100644 --- a/sdk/main/src/impl/NodeAddress.cc +++ b/sdk/main/src/impl/NodeAddress.cc @@ -18,12 +18,10 @@ * */ #include "impl/NodeAddress.h" -#include "exceptions/IllegalStateException.h" #include "impl/HexConverter.h" #include "impl/IPv4Address.h" #include "impl/Utilities.h" -#include #include #include #include @@ -31,107 +29,42 @@ namespace Hedera::internal { -//----- -NodeAddress::NodeAddress(std::string_view ipAddressV4, int port) -{ - mEndpoints.push_back(std::make_shared(IPv4Address::fromString(ipAddressV4), port)); -} - //----- NodeAddress NodeAddress::fromProtobuf(const proto::NodeAddress& protoNodeAddress) { NodeAddress outputNodeAddress; + outputNodeAddress.mRSAPublicKey = protoNodeAddress.rsa_pubkey(); + outputNodeAddress.mNodeId = protoNodeAddress.nodeid(); + outputNodeAddress.mNodeAccountId = AccountId::fromProtobuf(protoNodeAddress.nodeaccountid()); + outputNodeAddress.mNodeCertHash = Utilities::stringToByteVector(protoNodeAddress.nodecerthash()); for (int i = 0; i < protoNodeAddress.serviceendpoint_size(); ++i) { - Endpoint endpoint = Endpoint::fromProtobuf(protoNodeAddress.serviceendpoint(i)); - outputNodeAddress.mEndpoints.push_back(std::make_shared(endpoint)); - } - - if (protoNodeAddress.ipaddress().length() != 0) - { - outputNodeAddress.mEndpoints.emplace_back( - std::make_shared(IPv4Address::fromString(protoNodeAddress.ipaddress()), protoNodeAddress.portno())); + outputNodeAddress.mEndpoints.push_back(Endpoint::fromProtobuf(protoNodeAddress.serviceendpoint(i))); } - outputNodeAddress.mRSAPublicKey = protoNodeAddress.rsa_pubkey(); - outputNodeAddress.mNodeId = protoNodeAddress.nodeid(); - outputNodeAddress.mNodeAccountId = AccountId::fromProtobuf(protoNodeAddress.nodeaccountid()); - outputNodeAddress.mNodeCertHash = Utilities::stringToByteVector(protoNodeAddress.nodecerthash()); outputNodeAddress.mDescription = protoNodeAddress.description(); - outputNodeAddress.mStake = protoNodeAddress.stake(); return outputNodeAddress; } //----- -NodeAddress NodeAddress::fromString(std::string_view nodeAddress) +std::unique_ptr NodeAddress::toProtobuf() const { - const size_t colonIndex = nodeAddress.find(':'); - if (colonIndex == std::string::npos) - { - throw std::invalid_argument("Input node address is malformed"); - } + auto protoNodeAddress = std::make_unique(); + protoNodeAddress->set_rsa_pubkey(mRSAPublicKey); + protoNodeAddress->set_nodeid(mNodeId); + protoNodeAddress->set_allocated_nodeaccountid(mNodeAccountId.toProtobuf().release()); + protoNodeAddress->set_nodecerthash(Utilities::byteVectorToString(mNodeCertHash)); - const std::string_view ipAddressV4 = nodeAddress.substr(0, colonIndex); - const std::string_view portStr = nodeAddress.substr(colonIndex + 1, nodeAddress.size() - colonIndex - 1); - int port; - if (const auto result = std::from_chars(portStr.data(), portStr.data() + portStr.size(), port); - result.ptr != portStr.data() + portStr.size() || result.ec != std::errc{}) + for (const auto& endpoint : mEndpoints) { - throw std::invalid_argument("Input node address is malformed"); + *protoNodeAddress->add_serviceendpoint() = *endpoint.toProtobuf(); } - return { ipAddressV4, port }; -} - -//----- -NodeAddress& NodeAddress::setRSAPublicKey(std::string_view publicKey) -{ - mRSAPublicKey = publicKey; - return *this; -} - -//----- -NodeAddress& NodeAddress::setNodeId(const int64_t& nodeId) -{ - mNodeId = nodeId; - return *this; -} - -//----- -NodeAddress& NodeAddress::setNodeAccountId(const AccountId& accountId) -{ - mNodeAccountId = accountId; - return *this; -} - -//----- -NodeAddress& NodeAddress::setNodeCertHash(std::string_view certHash) -{ - mNodeCertHash = Utilities::stringToByteVector(certHash); - return *this; -} - -//----- -NodeAddress& NodeAddress::setEndpoints(const std::vector>& endpoints) -{ - mEndpoints = endpoints; - return *this; -} - -//----- -NodeAddress& NodeAddress::setDescription(std::string_view description) -{ - mDescription = description; - return *this; -} + protoNodeAddress->set_description(mDescription); -//----- -NodeAddress& NodeAddress::setStake(const uint64_t& stake) -{ - mStake = stake; - return *this; + return protoNodeAddress; } //----- @@ -147,7 +80,6 @@ std::string NodeAddress::toString() const outputStream << std::setw(columnWidth) << std::right << "RSA Public Key: " << std::left << mRSAPublicKey << std::endl; outputStream << std::setw(columnWidth) << std::right << "Certificate Hash: " << std::left << HexConverter::bytesToHex(mNodeCertHash) << std::endl; - outputStream << std::setw(columnWidth) << std::right << "Stake: " << std::left << mStake << std::endl; outputStream << std::setw(columnWidth) << std::right << "Endpoints: "; if (size_t endpointCount = mEndpoints.size(); !endpointCount) @@ -161,11 +93,11 @@ std::string NodeAddress::toString() const { if (counter == 0) { - outputStream << endpoint->toString(); + outputStream << endpoint.toString(); } else { - outputStream << std::setw(columnWidth) << endpoint->toString(); + outputStream << std::setw(columnWidth) << endpoint.toString(); } ++counter; @@ -180,4 +112,53 @@ std::string NodeAddress::toString() const return outputStream.str(); } +//----- +NodeAddress& NodeAddress::setPublicKey(std::string_view publicKey) +{ + mRSAPublicKey = publicKey; + return *this; +} + +//----- +NodeAddress& NodeAddress::setNodeId(const int64_t& nodeId) +{ + mNodeId = nodeId; + return *this; +} + +//----- +NodeAddress& NodeAddress::setAccountId(const AccountId& accountId) +{ + mNodeAccountId = accountId; + return *this; +} + +//----- +NodeAddress& NodeAddress::setCertHash(std::string_view certHash) +{ + mNodeCertHash = Utilities::stringToByteVector(certHash); + return *this; +} + +//----- +NodeAddress& NodeAddress::setCertHash(std::vector certHash) +{ + mNodeCertHash = std::move(certHash); + return *this; +} + +//----- +NodeAddress& NodeAddress::setEndpoints(const std::vector& endpoints) +{ + mEndpoints = endpoints; + return *this; +} + +//----- +NodeAddress& NodeAddress::setDescription(std::string_view description) +{ + mDescription = description; + return *this; +} + } // namespace Hedera::internal diff --git a/sdk/main/src/impl/NodeAddressBook.cc b/sdk/main/src/impl/NodeAddressBook.cc index c6e87e1de..4f9150d21 100644 --- a/sdk/main/src/impl/NodeAddressBook.cc +++ b/sdk/main/src/impl/NodeAddressBook.cc @@ -18,20 +18,22 @@ * */ #include "impl/NodeAddressBook.h" +#include "impl/Utilities.h" -#include #include namespace Hedera::internal { //----- -NodeAddressBook NodeAddressBook::fromFile(std::string_view fileName) +NodeAddressBook NodeAddressBook::fromProtobuf(const proto::NodeAddressBook& proto) { - std::ifstream infile(fileName.data(), std::ios_base::binary); - - std::vector buffer((std::istreambuf_iterator(infile)), std::istreambuf_iterator()); + NodeAddressBook nodeAddressBook; + for (int i = 0; i < proto.nodeaddress_size(); ++i) + { + nodeAddressBook.mNodeAddresses.push_back(NodeAddress::fromProtobuf(proto.nodeaddress(i))); + } - return NodeAddressBook::fromBytes(buffer); + return nodeAddressBook; } //----- @@ -39,34 +41,32 @@ NodeAddressBook NodeAddressBook::fromBytes(const std::vector& bytes) { proto::NodeAddressBook addressBook; addressBook.ParseFromArray(bytes.data(), static_cast(bytes.size())); - return fromProtobuf(addressBook); } //----- -NodeAddressBook NodeAddressBook::fromProtobuf(const proto::NodeAddressBook& protoAddressBook) +std::unique_ptr NodeAddressBook::toProtobuf() const { - NodeAddressBook outputAddressBook; - - for (int i = 0; i < protoAddressBook.nodeaddress_size(); ++i) + auto proto = std::make_unique(); + for (const NodeAddress& address : mNodeAddresses) { - const proto::NodeAddress& protoNodeAddress = protoAddressBook.nodeaddress(i); - - outputAddressBook.mAddressMap.try_emplace( - AccountId::fromProtobuf(protoNodeAddress.nodeaccountid()), - std::make_shared(NodeAddress::fromProtobuf(protoNodeAddress))); + *proto->add_nodeaddress() = *address.toProtobuf(); } - return outputAddressBook; + return proto; +} + +//----- +std::vector NodeAddressBook::toBytes() const +{ + return Utilities::stringToByteVector(toProtobuf()->SerializeAsString()); } //----- -NodeAddressBook NodeAddressBook::fromAddressMap( - const std::unordered_map>& addressMap) +NodeAddressBook& NodeAddressBook::setNodeAddresses(const std::vector& addresses) { - NodeAddressBook outputAddressBook; - outputAddressBook.mAddressMap = addressMap; - return outputAddressBook; + mNodeAddresses = addresses; + return *this; } } // namespace Hedera::internal diff --git a/sdk/main/src/impl/Utilities.cc b/sdk/main/src/impl/Utilities.cc index c0e409dd7..138215226 100644 --- a/sdk/main/src/impl/Utilities.cc +++ b/sdk/main/src/impl/Utilities.cc @@ -22,6 +22,7 @@ #include #include #include +#include namespace Hedera::internal::Utilities { @@ -92,4 +93,14 @@ std::string byteVectorToString(const std::vector& bytes) return str; } +//----- +unsigned int getRandomNumber(unsigned int lowerBound, unsigned int upperBound) +{ + static std::random_device rand; + static std::mt19937 eng(rand()); + + std::uniform_int_distribution dis(lowerBound, upperBound); + return dis(eng); +} + } // namespace Hedera::internal::Utilities diff --git a/sdk/tests/integration/ContractNonceInfoIntegrationTest.cc b/sdk/tests/integration/ContractNonceInfoIntegrationTest.cc index b56485260..6d730af3f 100644 --- a/sdk/tests/integration/ContractNonceInfoIntegrationTest.cc +++ b/sdk/tests/integration/ContractNonceInfoIntegrationTest.cc @@ -23,7 +23,6 @@ #include "ContractDeleteTransaction.h" #include "ContractFunctionResult.h" #include "ContractId.h" -#include "ContractInfo.h" #include "ED25519PrivateKey.h" #include "FileCreateTransaction.h" #include "FileDeleteTransaction.h" @@ -35,7 +34,6 @@ #include "exceptions/ReceiptStatusException.h" #include "impl/Utilities.h" -#include #include using namespace Hedera; @@ -64,7 +62,6 @@ TEST_F(ContractNonceInfoIntegrationTest, ContractADeploysContractBInConstructor) const std::unique_ptr operatorKey = ED25519PrivateKey::fromString( "302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137"); const std::string memo = "[e2e::ContractADeploysContractBInConstructor]"; - const std::chrono::duration autoRenewPeriod = std::chrono::hours(2016); FileId fileId; ASSERT_NO_THROW(fileId = FileCreateTransaction() @@ -88,12 +85,11 @@ TEST_F(ContractNonceInfoIntegrationTest, ContractADeploysContractBInConstructor) ContractId contractA = contractFunctionResult.mContractId; std::vector contractNonces; - for (auto it = contractFunctionResult.mContractNonces.begin(); it != contractFunctionResult.mContractNonces.end(); - ++it) + for (const auto& mContractNonce : contractFunctionResult.mContractNonces) { - if (!((*it).mContractId == contractA)) + if (!(mContractNonce.mContractId == contractA)) { - contractNonces.push_back(*it); + contractNonces.push_back(mContractNonce); } } @@ -102,16 +98,15 @@ TEST_F(ContractNonceInfoIntegrationTest, ContractADeploysContractBInConstructor) ContractNonceInfo contractANonceInfo; ContractNonceInfo contractBNonceInfo; - for (auto it = contractFunctionResult.mContractNonces.begin(); it != contractFunctionResult.mContractNonces.end(); - ++it) + for (const auto& mContractNonce : contractFunctionResult.mContractNonces) { - if ((*it).mContractId == contractA) + if (mContractNonce.mContractId == contractA) { - contractANonceInfo = *it; + contractANonceInfo = mContractNonce; } - else if ((*it).mContractId == contractB) + else if (mContractNonce.mContractId == contractB) { - contractBNonceInfo = *it; + contractBNonceInfo = mContractNonce; } } diff --git a/sdk/tests/integration/FileAppendTransactionIntegrationTests.cc b/sdk/tests/integration/FileAppendTransactionIntegrationTests.cc index a6eed7801..1de8cd9cb 100644 --- a/sdk/tests/integration/FileAppendTransactionIntegrationTests.cc +++ b/sdk/tests/integration/FileAppendTransactionIntegrationTests.cc @@ -239,11 +239,6 @@ TEST_F(FileAppendTransactionIntegrationTest, CanAppendLargeContents) txResponses = FileAppendTransaction().setFileId(fileId).setContents(appendedContents).executeAll(getTestClient())); // Then - for (const auto& response : txResponses) - { - EXPECT_NO_THROW(const TransactionReceipt txReceipt = response.getReceipt(getTestClient())); - } - FileContents fileContents; ASSERT_NO_THROW(fileContents = FileContentsQuery().setFileId(fileId).execute(getTestClient())); EXPECT_EQ(fileContents, internal::Utilities::concatenateVectors({ origContents, appendedContents })); diff --git a/sdk/tests/integration/TopicMessageSubmitTransactionIntegrationTests.cc b/sdk/tests/integration/TopicMessageSubmitTransactionIntegrationTests.cc index 092ee9f59..e76e12d19 100644 --- a/sdk/tests/integration/TopicMessageSubmitTransactionIntegrationTests.cc +++ b/sdk/tests/integration/TopicMessageSubmitTransactionIntegrationTests.cc @@ -325,7 +325,7 @@ TEST_F(TopicMessageSubmitTransactionIntegrationTests, CannotSubmitTopicMessageWi for (const auto& resp : txResponses) { EXPECT_EQ(resp.getValidateStatus(), true); - EXPECT_THROW(resp.getReceipt(getTestClient()).mStatus == Status::INVALID_TOPIC_ID, ReceiptStatusException); + EXPECT_THROW(const TransactionReceipt txReceipt = resp.getReceipt(getTestClient()), ReceiptStatusException); } TopicInfo topicInfo2; diff --git a/sdk/tests/unit/AccountAllowanceApproveTransactionTest.cc b/sdk/tests/unit/AccountAllowanceApproveTransactionTest.cc index 5538bc129..898089633 100644 --- a/sdk/tests/unit/AccountAllowanceApproveTransactionTest.cc +++ b/sdk/tests/unit/AccountAllowanceApproveTransactionTest.cc @@ -36,9 +36,6 @@ using namespace Hedera; class AccountAllowanceApproveTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(1ULL), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestOwnerAccountId() const { return mOwnerAccountId; } [[nodiscard]] inline const AccountId& getTestSpenderAccountId() const { return mSpenderAccountId; } [[nodiscard]] inline const Hbar& getTestAmountHbar() const { return mAmountHbar; } @@ -51,7 +48,6 @@ class AccountAllowanceApproveTransactionTest : public ::testing::Test } private: - Client mClient; const AccountId mOwnerAccountId = AccountId(2ULL); const AccountId mSpenderAccountId = AccountId(3ULL); const Hbar mAmountHbar = Hbar(4LL); @@ -153,8 +149,10 @@ TEST_F(AccountAllowanceApproveTransactionTest, ApproveHbarAllowance) TEST_F(AccountAllowanceApproveTransactionTest, ApproveHbarAllowanceFrozen) { // Given - AccountAllowanceApproveTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountAllowanceApproveTransaction transaction = AccountAllowanceApproveTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW( @@ -196,8 +194,10 @@ TEST_F(AccountAllowanceApproveTransactionTest, ApproveTokenAllowance) TEST_F(AccountAllowanceApproveTransactionTest, ApproveTokenAllowanceFrozen) { // Given - AccountAllowanceApproveTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountAllowanceApproveTransaction transaction = AccountAllowanceApproveTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW( @@ -247,8 +247,10 @@ TEST_F(AccountAllowanceApproveTransactionTest, ApproveNftAllowance) TEST_F(AccountAllowanceApproveTransactionTest, ApproveNftAllowanceFrozen) { // Given - AccountAllowanceApproveTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountAllowanceApproveTransaction transaction = AccountAllowanceApproveTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.approveTokenNftAllowance( @@ -281,8 +283,10 @@ TEST_F(AccountAllowanceApproveTransactionTest, ApproveNftAllowanceAllSerials) TEST_F(AccountAllowanceApproveTransactionTest, ApproveNftAllowanceAllSerialsFrozen) { // Given - AccountAllowanceApproveTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountAllowanceApproveTransaction transaction = AccountAllowanceApproveTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW( @@ -315,8 +319,10 @@ TEST_F(AccountAllowanceApproveTransactionTest, DeleteNftAllowanceAllSerials) TEST_F(AccountAllowanceApproveTransactionTest, DeleteNftAllowanceAllSerialsFrozen) { // Given - AccountAllowanceApproveTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountAllowanceApproveTransaction transaction = AccountAllowanceApproveTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW( diff --git a/sdk/tests/unit/AccountAllowanceDeleteTransactionTest.cc b/sdk/tests/unit/AccountAllowanceDeleteTransactionTest.cc index bb1bca914..a67be4704 100644 --- a/sdk/tests/unit/AccountAllowanceDeleteTransactionTest.cc +++ b/sdk/tests/unit/AccountAllowanceDeleteTransactionTest.cc @@ -35,15 +35,11 @@ using namespace Hedera; class AccountAllowanceDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(1ULL), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTokenId; } [[nodiscard]] inline const AccountId& getTestOwnerAccountId() const { return mOwnerAccountId; } [[nodiscard]] inline const std::vector& getTestSerialNumbers() const { return mSerialNumbers; } private: - Client mClient; const AccountId mOwnerAccountId = AccountId(2ULL); const TokenId mTokenId = TokenId(3ULL); const std::vector mSerialNumbers = { 4ULL, 5ULL, 6ULL }; @@ -145,8 +141,10 @@ TEST_F(AccountAllowanceDeleteTransactionTest, DeleteNftAllowancesDifferentTokenI TEST_F(AccountAllowanceDeleteTransactionTest, DeleteNftAllowancesFrozen) { // Given - AccountAllowanceDeleteTransaction transaction; - transaction.freezeWith(&getTestClient()); + AccountAllowanceDeleteTransaction transaction = AccountAllowanceDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.deleteAllTokenNftAllowances(NftId(getTestTokenId(), 10ULL), getTestOwnerAccountId()), diff --git a/sdk/tests/unit/AccountCreateTransactionTest.cc b/sdk/tests/unit/AccountCreateTransactionTest.cc index 8be7acfab..2f4cee03a 100644 --- a/sdk/tests/unit/AccountCreateTransactionTest.cc +++ b/sdk/tests/unit/AccountCreateTransactionTest.cc @@ -36,12 +36,6 @@ using namespace Hedera; class AccountCreateTransactionTest : public ::testing::Test { protected: - void SetUp() override - { - mClient.setOperator(getTestAccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); - } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const std::shared_ptr& getTestPublicKey() const { return mPublicKey; } [[nodiscard]] inline const Hbar& getTestInitialBalance() const { return mInitialBalance; } [[nodiscard]] inline bool getTestReceiverSignatureRequired() const { return mReceiverSignatureRequired; } @@ -54,7 +48,6 @@ class AccountCreateTransactionTest : public ::testing::Test [[nodiscard]] inline const EvmAddress& getTestEvmAddress() const { return mEvmAddress; } private: - Client mClient; const std::shared_ptr mPublicKey = ED25519PrivateKey::generatePrivateKey()->getPublicKey(); const Hbar mInitialBalance = Hbar(1LL); const bool mReceiverSignatureRequired = true; @@ -153,8 +146,10 @@ TEST_F(AccountCreateTransactionTest, SetKey) TEST_F(AccountCreateTransactionTest, SetKeyFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKey(getTestPublicKey().get()), IllegalStateException); @@ -177,8 +172,10 @@ TEST_F(AccountCreateTransactionTest, SetInitialBalance) TEST_F(AccountCreateTransactionTest, SetInitialBalanceFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setInitialBalance(getTestInitialBalance()), IllegalStateException); @@ -201,8 +198,10 @@ TEST_F(AccountCreateTransactionTest, SetReceiverSignatureRequired) TEST_F(AccountCreateTransactionTest, SetReceiverSignatureRequiredFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setReceiverSignatureRequired(getTestReceiverSignatureRequired()), IllegalStateException); @@ -225,8 +224,10 @@ TEST_F(AccountCreateTransactionTest, SetAutoRenewPeriod) TEST_F(AccountCreateTransactionTest, SetAutoRenewPeriodFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -259,8 +260,10 @@ TEST_F(AccountCreateTransactionTest, SetAccountMemoTooLarge) TEST_F(AccountCreateTransactionTest, SetAccountMemoFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountMemo(getTestAccountMemo()), IllegalStateException); @@ -293,8 +296,10 @@ TEST_F(AccountCreateTransactionTest, SetMaxAutomaticTokenAssociationsTooMany) TEST_F(AccountCreateTransactionTest, SetMaxAutomaticTokenAssociationsFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxAutomaticTokenAssociations(getTestMaximumTokenAssociations()), IllegalStateException); @@ -317,8 +322,10 @@ TEST_F(AccountCreateTransactionTest, SetStakedAccountId) TEST_F(AccountCreateTransactionTest, SetStakedAccountIdFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedAccountId(getTestAccountId()), IllegalStateException); @@ -341,8 +348,10 @@ TEST_F(AccountCreateTransactionTest, SetStakedNodeId) TEST_F(AccountCreateTransactionTest, SetStakedNodeIdFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedNodeId(getTestNodeId()), IllegalStateException); @@ -365,8 +374,10 @@ TEST_F(AccountCreateTransactionTest, SetStakingRewardPolicy) TEST_F(AccountCreateTransactionTest, SetStakingRewardPolicyFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDeclineStakingReward(getTestDeclineStakingReward()), IllegalStateException); @@ -384,17 +395,16 @@ TEST_F(AccountCreateTransactionTest, SetAlias) // Then ASSERT_TRUE(transaction.getAlias().has_value()); EXPECT_EQ(transaction.getAlias()->toBytes(), getTestEvmAddress().toBytes()); - - transaction.freezeWith(&getTestClient()); - EXPECT_THROW(transaction.setAlias(getTestEvmAddress()), IllegalStateException); } //----- TEST_F(AccountCreateTransactionTest, SetAliasFrozen) { // Given - AccountCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountCreateTransaction transaction = AccountCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When EXPECT_THROW(transaction.setAlias(getTestEvmAddress()), IllegalStateException); diff --git a/sdk/tests/unit/AccountDeleteTransactionTest.cc b/sdk/tests/unit/AccountDeleteTransactionTest.cc index 35ed929f1..eeb9f68ce 100644 --- a/sdk/tests/unit/AccountDeleteTransactionTest.cc +++ b/sdk/tests/unit/AccountDeleteTransactionTest.cc @@ -30,14 +30,10 @@ using namespace Hedera; class AccountDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestDeleteAccountId() const { return mDeleteAccountId; } [[nodiscard]] inline const AccountId& getTestTransferAccountId() const { return mTransferAccountId; } private: - Client mClient; const AccountId mDeleteAccountId = AccountId(1ULL); const AccountId mTransferAccountId = AccountId(2ULL); }; @@ -89,8 +85,10 @@ TEST_F(AccountDeleteTransactionTest, SetDeleteAccountId) TEST_F(AccountDeleteTransactionTest, SetDeleteAccountIdFrozen) { // Given - AccountDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountDeleteTransaction transaction = AccountDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDeleteAccountId(getTestDeleteAccountId()), IllegalStateException); @@ -113,8 +111,10 @@ TEST_F(AccountDeleteTransactionTest, SetTransferAccountId) TEST_F(AccountDeleteTransactionTest, SetTransferAccountIdFrozen) { // Given - AccountDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountDeleteTransaction transaction = AccountDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTransferAccountId(getTestTransferAccountId()), IllegalStateException); diff --git a/sdk/tests/unit/AccountUpdateTransactionTest.cc b/sdk/tests/unit/AccountUpdateTransactionTest.cc index c4e6a0910..8547a9fd5 100644 --- a/sdk/tests/unit/AccountUpdateTransactionTest.cc +++ b/sdk/tests/unit/AccountUpdateTransactionTest.cc @@ -34,12 +34,6 @@ using namespace Hedera; class AccountUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override - { - mClient.setOperator(getTestAccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); - } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mAccountId; } [[nodiscard]] inline const std::shared_ptr& getTestPublicKey() const { return mPublicKey; } [[nodiscard]] inline bool getTestReceiverSignatureRequired() const { return mReceiverSignatureRequired; } @@ -55,7 +49,6 @@ class AccountUpdateTransactionTest : public ::testing::Test [[nodiscard]] inline bool getTestDeclineStakingReward() const { return mDeclineStakingReward; } private: - Client mClient; const AccountId mAccountId = AccountId(1ULL); const std::shared_ptr mPublicKey = ECDSAsecp256k1PrivateKey::generatePrivateKey()->getPublicKey(); const bool mReceiverSignatureRequired = true; @@ -158,8 +151,10 @@ TEST_F(AccountUpdateTransactionTest, SetAccountId) TEST_F(AccountUpdateTransactionTest, SetAccountIdFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -182,8 +177,10 @@ TEST_F(AccountUpdateTransactionTest, SetKey) TEST_F(AccountUpdateTransactionTest, SetKeyFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKey(getTestPublicKey().get()), IllegalStateException); @@ -206,8 +203,10 @@ TEST_F(AccountUpdateTransactionTest, SetReceiverSignatureRequired) TEST_F(AccountUpdateTransactionTest, SetReceiverSignatureRequiredFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setReceiverSignatureRequired(getTestReceiverSignatureRequired()), IllegalStateException); @@ -230,8 +229,10 @@ TEST_F(AccountUpdateTransactionTest, SetAutoRenewPeriod) TEST_F(AccountUpdateTransactionTest, SetAutoRenewPeriodFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -254,8 +255,10 @@ TEST_F(AccountUpdateTransactionTest, SetExpirationTime) TEST_F(AccountUpdateTransactionTest, SetExpirationTimeFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -288,8 +291,10 @@ TEST_F(AccountUpdateTransactionTest, SetAccountMemoTooLarge) TEST_F(AccountUpdateTransactionTest, SetAccountMemoFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountMemo(getTestAccountMemo()), IllegalStateException); @@ -322,8 +327,10 @@ TEST_F(AccountUpdateTransactionTest, SetMaxAutomaticTokenAssociationsTooMany) TEST_F(AccountUpdateTransactionTest, SetMaxAutomaticTokenAssociationsFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxAutomaticTokenAssociations(getTestMaximumTokenAssociations()), IllegalStateException); @@ -346,8 +353,10 @@ TEST_F(AccountUpdateTransactionTest, SetStakedAccountId) TEST_F(AccountUpdateTransactionTest, SetStakedAccountIdFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedAccountId(getTestStakedAccountId()), IllegalStateException); @@ -370,8 +379,10 @@ TEST_F(AccountUpdateTransactionTest, SetStakedNodeId) TEST_F(AccountUpdateTransactionTest, SetStakedNodeIdFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedNodeId(getTestStakedNodeId()), IllegalStateException); @@ -394,8 +405,10 @@ TEST_F(AccountUpdateTransactionTest, SetStakingRewardPolicy) TEST_F(AccountUpdateTransactionTest, SetStakingRewardPolicyFrozen) { // Given - AccountUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + AccountUpdateTransaction transaction = AccountUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDeclineStakingReward(getTestDeclineStakingReward()), IllegalStateException); diff --git a/sdk/tests/unit/ChunkedTransactionTest.cc b/sdk/tests/unit/ChunkedTransactionTest.cc index dd9ec327c..769026ddb 100644 --- a/sdk/tests/unit/ChunkedTransactionTest.cc +++ b/sdk/tests/unit/ChunkedTransactionTest.cc @@ -32,14 +32,10 @@ using namespace Hedera; class ChunkedTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline unsigned int getTestMaxChunks() const { return mTestMaxChunks; } [[nodiscard]] inline unsigned int getTestChunkSize() const { return mTestChunkSize; } private: - Client mClient; const unsigned int mTestMaxChunks = 1U; const unsigned int mTestChunkSize = 2U; }; @@ -61,8 +57,10 @@ TEST_F(ChunkedTransactionTest, GetSetMaxChunks) TEST_F(ChunkedTransactionTest, GetSetMaxChunksFrozen) { // Given - FileAppendTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileAppendTransaction transaction = FileAppendTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxChunks(getTestMaxChunks()), IllegalStateException); @@ -85,8 +83,10 @@ TEST_F(ChunkedTransactionTest, GetSetChunkSize) TEST_F(ChunkedTransactionTest, GetSetChunkSizeFrozen) { // Given - FileAppendTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileAppendTransaction transaction = FileAppendTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setChunkSize(getTestChunkSize()), IllegalStateException); diff --git a/sdk/tests/unit/ClientTest.cc b/sdk/tests/unit/ClientTest.cc index bbccd4404..b32181267 100644 --- a/sdk/tests/unit/ClientTest.cc +++ b/sdk/tests/unit/ClientTest.cc @@ -79,25 +79,6 @@ TEST_F(ClientTest, SetOperator) EXPECT_FALSE(client.getOperatorPublicKey()->toStringDer().empty()); } -//----- -TEST_F(ClientTest, SignWithOperator) -{ - const std::vector bytesToSign = { std::byte(0x1), std::byte(0x2), std::byte(0x3) }; - - Client client; - EXPECT_THROW(auto bytes = client.sign(bytesToSign), UninitializedException); - - client.setOperator(getTestAccountId(), getTestPrivateKey().get()); - EXPECT_TRUE(getTestPrivateKey()->getPublicKey()->verifySignature(client.sign(bytesToSign), bytesToSign)); -} - -//----- -TEST_F(ClientTest, GetNodes) -{ - Client client; - EXPECT_THROW(auto nodes = client.getNodesWithAccountIds({ getTestAccountId() }), UninitializedException); -} - //----- TEST_F(ClientTest, SetDefaultMaxTransactionFee) { diff --git a/sdk/tests/unit/ContractCreateTransactionTest.cc b/sdk/tests/unit/ContractCreateTransactionTest.cc index 1ff865754..8a38eb3a3 100644 --- a/sdk/tests/unit/ContractCreateTransactionTest.cc +++ b/sdk/tests/unit/ContractCreateTransactionTest.cc @@ -37,9 +37,6 @@ using namespace Hedera; class ContractCreateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const std::vector& getTestBytecode() const { return mTestBytecode; } [[nodiscard]] inline const std::shared_ptr& getTestAdminKey() const { return mTestAdminKey; } @@ -61,7 +58,6 @@ class ContractCreateTransactionTest : public ::testing::Test [[nodiscard]] inline bool getTestDeclineStakingReward() const { return mTestDeclineStakingReward; } private: - Client mClient; const FileId mTestFileId = FileId(1ULL); const std::vector mTestBytecode = { std::byte(0x02), std::byte(0x03), std::byte(0x04) }; const std::shared_ptr mTestAdminKey = PublicKey::fromStringDer( @@ -138,8 +134,10 @@ TEST_F(ContractCreateTransactionTest, GetSetFileId) TEST_F(ContractCreateTransactionTest, GetSetFileIdFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setBytecodeFileId(getTestFileId()), IllegalStateException); @@ -162,8 +160,10 @@ TEST_F(ContractCreateTransactionTest, GetSetInitCode) TEST_F(ContractCreateTransactionTest, GetSetInitCodeFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setBytecode(getTestBytecode()), IllegalStateException); @@ -186,8 +186,10 @@ TEST_F(ContractCreateTransactionTest, GetSetAdminKey) TEST_F(ContractCreateTransactionTest, GetSetAdminKeyFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey().get()), IllegalStateException); @@ -210,8 +212,10 @@ TEST_F(ContractCreateTransactionTest, GetSetGas) TEST_F(ContractCreateTransactionTest, GetSetGasFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setGas(getTestGas()), IllegalStateException); @@ -234,8 +238,10 @@ TEST_F(ContractCreateTransactionTest, GetSetInitialBalance) TEST_F(ContractCreateTransactionTest, GetSetInitialBalanceFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setInitialBalance(getTestInitialBalance()), IllegalStateException); @@ -258,8 +264,10 @@ TEST_F(ContractCreateTransactionTest, GetSetAutoRenewPeriod) TEST_F(ContractCreateTransactionTest, GetSetAutoRenewPeriodFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -282,8 +290,10 @@ TEST_F(ContractCreateTransactionTest, GetSetConstructorParameters) TEST_F(ContractCreateTransactionTest, GetSetConstructorParametersFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setConstructorParameters(getTestConstructorParameters()), IllegalStateException); @@ -306,8 +316,10 @@ TEST_F(ContractCreateTransactionTest, GetSetMemo) TEST_F(ContractCreateTransactionTest, GetSetMemoFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMemo(getTestMemo()), IllegalStateException); @@ -330,8 +342,10 @@ TEST_F(ContractCreateTransactionTest, GetSetMaxAutomaticTokenAssociations) TEST_F(ContractCreateTransactionTest, GetSetMaxAutomaticTokenAssociationsFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxAutomaticTokenAssociations(getTestMaximumTokenAssociations()), IllegalStateException); @@ -354,8 +368,10 @@ TEST_F(ContractCreateTransactionTest, GetSetAutoRenewAccountId) TEST_F(ContractCreateTransactionTest, GetSetAutoRenewAccountIdFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); @@ -378,8 +394,10 @@ TEST_F(ContractCreateTransactionTest, GetSetStakedAccountId) TEST_F(ContractCreateTransactionTest, GetSetStakedAccountIdFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedAccountId(getTestStakedAccountId()), IllegalStateException); @@ -402,8 +420,10 @@ TEST_F(ContractCreateTransactionTest, GetSetStakedNodeId) TEST_F(ContractCreateTransactionTest, GetSetStakedNodeIdFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedNodeId(getTestStakedNodeId()), IllegalStateException); @@ -426,8 +446,10 @@ TEST_F(ContractCreateTransactionTest, GetSetDeclineReward) TEST_F(ContractCreateTransactionTest, GetSetDeclineRewardFrozen) { // Given - ContractCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractCreateTransaction transaction = ContractCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDeclineStakingReward(getTestDeclineStakingReward()), IllegalStateException); diff --git a/sdk/tests/unit/ContractDeleteTransactionTest.cc b/sdk/tests/unit/ContractDeleteTransactionTest.cc index 796b510b6..f4abbb820 100644 --- a/sdk/tests/unit/ContractDeleteTransactionTest.cc +++ b/sdk/tests/unit/ContractDeleteTransactionTest.cc @@ -34,15 +34,11 @@ using namespace Hedera; class ContractDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const ContractId& getTestContractId() const { return mTestContractId; } [[nodiscard]] inline const AccountId& getTestTransferAccountId() const { return mTestTransferAccountId; } [[nodiscard]] inline const ContractId& getTestTransferContractId() const { return mTestTransferContractId; } private: - Client mClient; const ContractId mTestContractId = ContractId(1ULL); const AccountId mTestTransferAccountId = AccountId(2ULL); const ContractId mTestTransferContractId = ContractId(3ULL); @@ -99,8 +95,10 @@ TEST_F(ContractDeleteTransactionTest, GetSetContractId) TEST_F(ContractDeleteTransactionTest, GetSetContractIdFrozen) { // Given - ContractDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractDeleteTransaction transaction = ContractDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractId(getTestContractId()), IllegalStateException); @@ -123,8 +121,10 @@ TEST_F(ContractDeleteTransactionTest, GetSetTransferAccountId) TEST_F(ContractDeleteTransactionTest, GetSetTransferAccountIdFrozen) { // Given - ContractDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractDeleteTransaction transaction = ContractDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTransferAccountId(getTestTransferAccountId()), IllegalStateException); @@ -147,8 +147,10 @@ TEST_F(ContractDeleteTransactionTest, GetSetTransferContractId) TEST_F(ContractDeleteTransactionTest, GetSetTransferContractIdFrozen) { // Given - ContractDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractDeleteTransaction transaction = ContractDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTransferContractId(getTestTransferContractId()), IllegalStateException); diff --git a/sdk/tests/unit/ContractExecuteTransactionTest.cc b/sdk/tests/unit/ContractExecuteTransactionTest.cc index d1ce2ff07..825fe5979 100644 --- a/sdk/tests/unit/ContractExecuteTransactionTest.cc +++ b/sdk/tests/unit/ContractExecuteTransactionTest.cc @@ -36,9 +36,6 @@ using namespace Hedera; class ContractExecuteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const ContractId& getTestContractId() const { return mTestContractId; } [[nodiscard]] inline const uint64_t& getTestGas() const { return mTestGas; } [[nodiscard]] inline const Hbar& getTestPayableAmount() const { return mTestPayableAmount; } @@ -48,7 +45,6 @@ class ContractExecuteTransactionTest : public ::testing::Test } private: - Client mClient; const ContractId mTestContractId = ContractId(1ULL); const uint64_t mTestGas = 2ULL; const Hbar mTestPayableAmount = Hbar(3LL); @@ -95,8 +91,10 @@ TEST_F(ContractExecuteTransactionTest, GetSetContractId) TEST_F(ContractExecuteTransactionTest, GetSetContractIdFrozen) { // Given - ContractExecuteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractExecuteTransaction transaction = ContractExecuteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractId(getTestContractId()), IllegalStateException); @@ -119,8 +117,10 @@ TEST_F(ContractExecuteTransactionTest, GetSetGas) TEST_F(ContractExecuteTransactionTest, GetSetGasFrozen) { // Given - ContractExecuteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractExecuteTransaction transaction = ContractExecuteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setGas(getTestGas()), IllegalStateException); @@ -143,8 +143,10 @@ TEST_F(ContractExecuteTransactionTest, GetSetPayableAmount) TEST_F(ContractExecuteTransactionTest, GetSetPayableAmountFrozen) { // Given - ContractExecuteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractExecuteTransaction transaction = ContractExecuteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setPayableAmount(getTestPayableAmount()), IllegalStateException); @@ -167,8 +169,10 @@ TEST_F(ContractExecuteTransactionTest, GetSetFunctionParameters) TEST_F(ContractExecuteTransactionTest, GetSetFunctionParametersFrozen) { // Given - ContractExecuteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractExecuteTransaction transaction = ContractExecuteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFunctionParameters(getTestFunctionParameters()), IllegalStateException); @@ -191,8 +195,10 @@ TEST_F(ContractExecuteTransactionTest, GetSetFunctionName) TEST_F(ContractExecuteTransactionTest, GetSetFunctionNameFrozen) { // Given - ContractExecuteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractExecuteTransaction transaction = ContractExecuteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFunction("functionName"), IllegalStateException); diff --git a/sdk/tests/unit/ContractUpdateTransactionTest.cc b/sdk/tests/unit/ContractUpdateTransactionTest.cc index 56d8e5225..82118b72f 100644 --- a/sdk/tests/unit/ContractUpdateTransactionTest.cc +++ b/sdk/tests/unit/ContractUpdateTransactionTest.cc @@ -35,9 +35,6 @@ using namespace Hedera; class ContractUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const ContractId& getTestContractId() const { return mTestContractId; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestExpirationTime() const { @@ -59,7 +56,6 @@ class ContractUpdateTransactionTest : public ::testing::Test [[nodiscard]] inline bool getTestDeclineStakingReward() const { return mTestDeclineStakingReward; } private: - Client mClient; const ContractId mTestContractId = ContractId(1ULL); const std::chrono::system_clock::time_point mTestExpirationTime = std::chrono::system_clock::now(); const std::shared_ptr mTestAdminKey = ECDSAsecp256k1PrivateKey::generatePrivateKey()->getPublicKey(); @@ -140,8 +136,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetContractId) TEST_F(ContractUpdateTransactionTest, SetContractIdFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractId(getTestContractId()), IllegalStateException); @@ -164,8 +162,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetExpirationTime) TEST_F(ContractUpdateTransactionTest, SetExpirationTimeFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -188,8 +188,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetAdminKey) TEST_F(ContractUpdateTransactionTest, SetAdminKeyFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey().get()), IllegalStateException); @@ -212,8 +214,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetAutoRenewPeriod) TEST_F(ContractUpdateTransactionTest, SetAutoRenewPeriodFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -246,8 +250,10 @@ TEST_F(ContractUpdateTransactionTest, SetContractMemoTooLarge) TEST_F(ContractUpdateTransactionTest, SetContractMemoFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractMemo(getTestContractMemo()), IllegalStateException); @@ -280,8 +286,10 @@ TEST_F(ContractUpdateTransactionTest, SetMaxAutomaticTokenAssociationsTooMany) TEST_F(ContractUpdateTransactionTest, GetSetMaxAutomaticTokenAssociationsFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxAutomaticTokenAssociations(getTestMaximumAutomaticTokenAssociations()), @@ -305,8 +313,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetAutoRenewAccountId) TEST_F(ContractUpdateTransactionTest, SetAutoRenewAccountIdFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); @@ -329,8 +339,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetStakedAccountId) TEST_F(ContractUpdateTransactionTest, SetStakedAccountIdFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedAccountId(getTestStakedAccountId()), IllegalStateException); @@ -353,8 +365,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetStakedNodeId) TEST_F(ContractUpdateTransactionTest, SetStakedNodeIdFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStakedNodeId(getTestStakedNodeId()), IllegalStateException); @@ -377,8 +391,10 @@ TEST_F(ContractUpdateTransactionTest, GetSetStakingRewardPolicy) TEST_F(ContractUpdateTransactionTest, SetStakingRewardPolicyFrozen) { // Given - ContractUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ContractUpdateTransaction transaction = ContractUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDeclineStakingReward(getTestDeclineStakingReward()), IllegalStateException); diff --git a/sdk/tests/unit/EthereumTransactionTest.cc b/sdk/tests/unit/EthereumTransactionTest.cc index bcf9d6353..1c9383837 100644 --- a/sdk/tests/unit/EthereumTransactionTest.cc +++ b/sdk/tests/unit/EthereumTransactionTest.cc @@ -37,15 +37,11 @@ using namespace Hedera; class EthereumTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const std::vector& getTestEthereumData() const { return mTestEthereumData; } [[nodiscard]] inline const FileId& getTestCallDataFileId() const { return mTestCallDataFileId; } [[nodiscard]] inline const Hbar& getTestMaxGasAllowance() const { return mTestMaxGasAllowance; } private: - Client mClient; const std::vector mTestEthereumData = { std::byte(0x01), std::byte(0x02), std::byte(0x03) }; const FileId mTestCallDataFileId = FileId(4ULL); const Hbar mTestMaxGasAllowance = Hbar(5LL); @@ -90,8 +86,10 @@ TEST_F(EthereumTransactionTest, GetSetEthereumData) TEST_F(EthereumTransactionTest, GetSetEthereumDataFrozen) { // Given - EthereumTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + EthereumTransaction transaction = EthereumTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setEthereumData(getTestEthereumData()), IllegalStateException); @@ -114,8 +112,10 @@ TEST_F(EthereumTransactionTest, GetSetCallDataFileId) TEST_F(EthereumTransactionTest, GetSetCallDataFileIdFrozen) { // Given - EthereumTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + EthereumTransaction transaction = EthereumTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setCallDataFileId(getTestCallDataFileId()), IllegalStateException); @@ -138,8 +138,10 @@ TEST_F(EthereumTransactionTest, GetSetMaxGasAllowance) TEST_F(EthereumTransactionTest, GetSetMaxGasAllowanceFrozen) { // Given - EthereumTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + EthereumTransaction transaction = EthereumTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxGasAllowance(getTestMaxGasAllowance()), IllegalStateException); diff --git a/sdk/tests/unit/FileAppendTransactionTest.cc b/sdk/tests/unit/FileAppendTransactionTest.cc index 845bed8f8..952fbdb96 100644 --- a/sdk/tests/unit/FileAppendTransactionTest.cc +++ b/sdk/tests/unit/FileAppendTransactionTest.cc @@ -37,15 +37,10 @@ using namespace Hedera; class FileAppendTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const std::vector& getTestContents() const { return mTestContents; } private: - Client mClient; - const FileId mTestFileId = FileId(1ULL); const std::vector mTestContents = { std::byte(0x02), std::byte(0x03), std::byte(0x04) }; }; @@ -86,8 +81,10 @@ TEST_F(FileAppendTransactionTest, GetSetFileId) TEST_F(FileAppendTransactionTest, GetSetFileIdFrozen) { // Given - FileAppendTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileAppendTransaction transaction = FileAppendTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); @@ -113,8 +110,10 @@ TEST_F(FileAppendTransactionTest, GetSetContents) TEST_F(FileAppendTransactionTest, GetSetContentsFrozen) { // Given - FileAppendTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileAppendTransaction transaction = FileAppendTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContents(getTestContents()), IllegalStateException); diff --git a/sdk/tests/unit/FileCreateTransactionTest.cc b/sdk/tests/unit/FileCreateTransactionTest.cc index 8fcda8452..c95bfb525 100644 --- a/sdk/tests/unit/FileCreateTransactionTest.cc +++ b/sdk/tests/unit/FileCreateTransactionTest.cc @@ -39,9 +39,6 @@ using namespace Hedera; class FileCreateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestExpirationTime() const { return mTestExpirationTime; @@ -52,7 +49,6 @@ class FileCreateTransactionTest : public ::testing::Test [[nodiscard]] inline const std::string& getTestMemo() const { return mTestMemo; } private: - Client mClient; const std::unique_ptr mPrivateKey1 = ED25519PrivateKey::fromString( "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10"); const std::unique_ptr mPrivateKey2 = ED25519PrivateKey::fromString( @@ -107,8 +103,10 @@ TEST_F(FileCreateTransactionTest, GetSetExpirationTime) TEST_F(FileCreateTransactionTest, GetSetExpirationTimeFrozen) { // Given - FileCreateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileCreateTransaction transaction = FileCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -135,8 +133,10 @@ TEST_F(FileCreateTransactionTest, GetSetKeys) TEST_F(FileCreateTransactionTest, GetSetKeysFrozen) { // Given - FileCreateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileCreateTransaction transaction = FileCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKeys(getTestKeyList()), IllegalStateException); @@ -160,8 +160,10 @@ TEST_F(FileCreateTransactionTest, GetSetContents) TEST_F(FileCreateTransactionTest, GetSetContentsFrozen) { // Given - FileCreateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileCreateTransaction transaction = FileCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContents(getTestContents()), IllegalStateException); @@ -184,8 +186,10 @@ TEST_F(FileCreateTransactionTest, GetSetMemo) TEST_F(FileCreateTransactionTest, GetSetMemoFrozen) { // Given - FileCreateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileCreateTransaction transaction = FileCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileMemo(getTestMemo()), IllegalStateException); diff --git a/sdk/tests/unit/FileDeleteTransactionTest.cc b/sdk/tests/unit/FileDeleteTransactionTest.cc index 2a3431b0f..231718538 100644 --- a/sdk/tests/unit/FileDeleteTransactionTest.cc +++ b/sdk/tests/unit/FileDeleteTransactionTest.cc @@ -31,13 +31,9 @@ using namespace Hedera; class FileDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } private: - Client mClient; const FileId mTestFileId = FileId(1ULL); }; @@ -75,8 +71,10 @@ TEST_F(FileDeleteTransactionTest, GetSetFileId) TEST_F(FileDeleteTransactionTest, GetSetFileIdFrozen) { // Given - FileDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + FileDeleteTransaction transaction = FileDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); diff --git a/sdk/tests/unit/FileUpdateTransactionTest.cc b/sdk/tests/unit/FileUpdateTransactionTest.cc index 3d840f86f..71da8d651 100644 --- a/sdk/tests/unit/FileUpdateTransactionTest.cc +++ b/sdk/tests/unit/FileUpdateTransactionTest.cc @@ -39,9 +39,6 @@ using namespace Hedera; class FileUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestExpirationTime() const { @@ -53,7 +50,6 @@ class FileUpdateTransactionTest : public ::testing::Test [[nodiscard]] inline const std::string& getTestMemo() const { return mTestMemo; } private: - Client mClient; const std::unique_ptr mPrivateKey1 = ED25519PrivateKey::fromString( "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10"); const std::unique_ptr mPrivateKey2 = ED25519PrivateKey::fromString( @@ -118,8 +114,10 @@ TEST_F(FileUpdateTransactionTest, GetSetFileId) TEST_F(FileUpdateTransactionTest, GetSetFileIdFrozen) { // Given - FileUpdateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileUpdateTransaction transaction = FileUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); @@ -143,8 +141,10 @@ TEST_F(FileUpdateTransactionTest, GetSetExpirationTime) TEST_F(FileUpdateTransactionTest, GetSetExpirationTimeFrozen) { // Given - FileUpdateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileUpdateTransaction transaction = FileUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -174,8 +174,10 @@ TEST_F(FileUpdateTransactionTest, GetSetKeys) TEST_F(FileUpdateTransactionTest, GetSetKeysFrozen) { // Given - FileUpdateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileUpdateTransaction transaction = FileUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKeys(getTestKeyList()), IllegalStateException); @@ -204,8 +206,10 @@ TEST_F(FileUpdateTransactionTest, GetSetContents) TEST_F(FileUpdateTransactionTest, GetSetContentsFrozen) { // Given - FileUpdateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileUpdateTransaction transaction = FileUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContents(getTestContents()), IllegalStateException); @@ -231,8 +235,10 @@ TEST_F(FileUpdateTransactionTest, GetSetMemo) TEST_F(FileUpdateTransactionTest, GetSetMemoFrozen) { // Given - FileUpdateTransaction transaction; - transaction.freezeWith(&getTestClient()); + FileUpdateTransaction transaction = FileUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileMemo(getTestMemo()), IllegalStateException); diff --git a/sdk/tests/unit/FreezeTransactionUnitTests.cc b/sdk/tests/unit/FreezeTransactionUnitTests.cc index 77006a18f..694cda0ab 100644 --- a/sdk/tests/unit/FreezeTransactionUnitTests.cc +++ b/sdk/tests/unit/FreezeTransactionUnitTests.cc @@ -39,17 +39,12 @@ using namespace Hedera; class FreezeTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ED25519PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const std::vector& getTestFileHash() const { return mTestFileHash; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestStartTime() const { return mTestStartTime; } [[nodiscard]] inline const FreezeType& getTestFreezeType() const { return mTestFreezeType; } private: - Client mClient; - const FileId mTestFileId = FileId(1ULL, 2ULL, 3ULL); const std::vector mTestFileHash = { std::byte(0x04), std::byte(0x05), std::byte(0x06) }; const std::chrono::system_clock::time_point mTestStartTime = std::chrono::system_clock::now(); @@ -99,8 +94,10 @@ TEST_F(FreezeTransactionTest, GetSetFileId) TEST_F(FreezeTransactionTest, GetSetFileIdFrozen) { // Given - FreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + FreezeTransaction transaction = FreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); @@ -123,8 +120,10 @@ TEST_F(FreezeTransactionTest, GetSetFileHash) TEST_F(FreezeTransactionTest, GetSetFileHashFrozen) { // Given - FreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + FreezeTransaction transaction = FreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileHash(getTestFileHash()), IllegalStateException); @@ -148,8 +147,10 @@ TEST_F(FreezeTransactionTest, GetSetStartTime) TEST_F(FreezeTransactionTest, GetSetStartTimeFrozen) { // Given - FreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + FreezeTransaction transaction = FreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setStartTime(getTestStartTime()), IllegalStateException); @@ -172,8 +173,10 @@ TEST_F(FreezeTransactionTest, GetSetFreezeType) TEST_F(FreezeTransactionTest, GetSetFreezeTypeFrozen) { // Given - FreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + FreezeTransaction transaction = FreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFreezeType(getTestFreezeType()), IllegalStateException); diff --git a/sdk/tests/unit/NodeAddressTest.cc b/sdk/tests/unit/NodeAddressTest.cc index 1ab7b39d4..012817cb7 100644 --- a/sdk/tests/unit/NodeAddressTest.cc +++ b/sdk/tests/unit/NodeAddressTest.cc @@ -18,6 +18,7 @@ * */ #include "impl/NodeAddress.h" +#include "AccountId.h" #include "impl/Endpoint.h" #include "impl/IPv4Address.h" #include "impl/Utilities.h" @@ -27,170 +28,164 @@ #include #include +using namespace Hedera; using namespace Hedera::internal; class NodeAddressTest : public ::testing::Test { protected: - [[nodiscard]] inline const int64_t& getTestNodeId() const { return mTestNodeId; } - [[nodiscard]] inline const int& getTestPortTLS() const { return mTestPortTLS; } - [[nodiscard]] inline const int& getTestPortPlain() const { return mTestPortPlain; } - [[nodiscard]] inline const std::string& getTestRSAPublicKey() const { return mTestRSAPublicKey; } - [[nodiscard]] inline const std::string& getTestIpAddress() const { return mTestIpAddress; } + [[nodiscard]] inline const std::vector& getTestEndpoints() const { return mTestEndpoints; } + [[nodiscard]] inline const std::string& getTestPublicKey() const { return mTestPublicKey; } + [[nodiscard]] inline int64_t getTestNodeId() const { return mTestNodeId; } + [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestNodeAccountId; } + [[nodiscard]] inline const std::vector& getTestCertHash() const { return mTestCertHash; } [[nodiscard]] inline const std::string& getTestDescription() const { return mTestDescription; } - [[nodiscard]] inline const std::string& getTestNodeCertHash() const { return mTestNodeCertHash; } - [[nodiscard]] inline const std::string& getTestNodeAddress() const { return mTestNodeAddress; } - - void SetUp() override - { - const int testPortTLS = getTestPortTLS(); - std::stringstream outputStream; - outputStream << getTestIpAddress() << ":" << std::to_string(testPortTLS); - mTestNodeAddress = outputStream.str(); - } private: - const int64_t mTestNodeId = 9; - const int mTestPortTLS = 50212; - const int mTestPortPlain = 50211; - const std::string mTestRSAPublicKey = "TestPublicKey"; - const std::string mTestIpAddress = "35.237.200.180"; + const std::vector mTestEndpoints = { + Endpoint() + .setAddress(IPv4Address::fromBytes({ std::byte(0x00), std::byte(0x01), std::byte(0x02), std::byte(0x03) })) + .setPort(4U) + }; + const std::string mTestPublicKey = "TestPublicKey"; + const int64_t mTestNodeId = 5LL; + const AccountId mTestNodeAccountId = AccountId(6ULL, 7ULL, 8ULL); + const std::vector mTestCertHash = { std::byte(0x09), std::byte(0x0A), std::byte(0x0B) }; const std::string mTestDescription = "Test Description"; - const std::string mTestNodeCertHash = "Certificate Hash Value"; - std::string mTestNodeAddress; }; -// Test creation of NodeAddress instance using the default constructor. -TEST_F(NodeAddressTest, DefaultConstructNodeAddress) +//----- +TEST_F(NodeAddressTest, FromProtobuf) +{ + // Given + proto::NodeAddress protoNodeAddress; + + for (const auto& endpoint : getTestEndpoints()) + { + *protoNodeAddress.add_serviceendpoint() = *endpoint.toProtobuf(); + } + + protoNodeAddress.set_rsa_pubkey(getTestPublicKey()); + protoNodeAddress.set_nodeid(getTestNodeId()); + protoNodeAddress.set_allocated_nodeaccountid(getTestAccountId().toProtobuf().release()); + protoNodeAddress.set_nodecerthash(Utilities::byteVectorToString(getTestCertHash())); + protoNodeAddress.set_description(getTestDescription()); + + // When + const NodeAddress nodeAddress = NodeAddress::fromProtobuf(protoNodeAddress); + + // Then + EXPECT_EQ(nodeAddress.getEndpoints().size(), getTestEndpoints().size()); + EXPECT_EQ(nodeAddress.getPublicKey(), getTestPublicKey()); + EXPECT_EQ(nodeAddress.getNodeId(), getTestNodeId()); + EXPECT_EQ(nodeAddress.getAccountId(), getTestAccountId()); + EXPECT_EQ(nodeAddress.getCertHash(), getTestCertHash()); + EXPECT_EQ(nodeAddress.getDescription(), getTestDescription()); +} + +//----- +TEST_F(NodeAddressTest, ToProtobuf) +{ + // Given + NodeAddress nodeAddress; + nodeAddress.setEndpoints(getTestEndpoints()); + nodeAddress.setPublicKey(getTestPublicKey()); + nodeAddress.setNodeId(getTestNodeId()); + nodeAddress.setAccountId(getTestAccountId()); + nodeAddress.setCertHash(Utilities::byteVectorToString(getTestCertHash())); + nodeAddress.setDescription(getTestDescription()); + + // When + const std::unique_ptr protoNodeAddress = nodeAddress.toProtobuf(); + + // Then + EXPECT_EQ(protoNodeAddress->serviceendpoint_size(), getTestEndpoints().size()); + EXPECT_EQ(protoNodeAddress->rsa_pubkey(), getTestPublicKey()); + EXPECT_EQ(protoNodeAddress->nodeid(), getTestNodeId()); + EXPECT_EQ(protoNodeAddress->nodeaccountid().shardnum(), getTestAccountId().mShardNum); + EXPECT_EQ(protoNodeAddress->nodeaccountid().realmnum(), getTestAccountId().mRealmNum); + EXPECT_EQ(protoNodeAddress->nodeaccountid().accountnum(), getTestAccountId().mAccountNum.value()); + EXPECT_EQ(protoNodeAddress->nodecerthash(), Utilities::byteVectorToString(getTestCertHash())); + EXPECT_EQ(protoNodeAddress->description(), getTestDescription()); +} + +//----- +TEST_F(NodeAddressTest, GetSetPublicKey) { // Given - const int testPortTLS = getTestPortTLS(); + NodeAddress nodeAddress; // When - const NodeAddress nodeAddress; + nodeAddress.setPublicKey(getTestPublicKey()); // Then - EXPECT_TRUE(nodeAddress.isTlsPort(testPortTLS)); - EXPECT_FALSE(nodeAddress.isNonTlsPort(testPortTLS)); - EXPECT_EQ(nodeAddress.getNodeId(), -1); - EXPECT_EQ(nodeAddress.getNodeAccountId().mShardNum, 0ULL); - EXPECT_EQ(nodeAddress.getNodeAccountId().mRealmNum, 0ULL); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mAccountNum.has_value()); - EXPECT_EQ(nodeAddress.getNodeAccountId().mPublicKeyAlias, nullptr); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mEvmAddressAlias.has_value()); - EXPECT_TRUE(nodeAddress.getNodeCertHash().empty()); - EXPECT_TRUE(nodeAddress.getDescription().empty()); - EXPECT_TRUE(nodeAddress.getEndpoints().empty()); + EXPECT_EQ(nodeAddress.getPublicKey(), getTestPublicKey()); } -// Test setters & getters of NodeAddress. -TEST_F(NodeAddressTest, GettersAndSettersNodeAddress) +//----- +TEST_F(NodeAddressTest, GetSetNodeId) { // Given - NodeAddress testNodeAddress; - const int64_t testNodeId = getTestNodeId(); - const int testPortTLS = getTestPortTLS(); - const std::string& testRSAPublicKey = getTestRSAPublicKey(); - const std::string& testStringForIpAddressV4_1 = getTestIpAddress(); - const std::string& testStringForIpAddressV4_2 = "127.0.0.1"; - const IPv4Address& testIpAddressV4_1 = IPv4Address::fromString(testStringForIpAddressV4_1); - const IPv4Address& testIpAddressV4_2 = IPv4Address::fromString(testStringForIpAddressV4_2); - const std::string& testDescription = getTestDescription(); - const std::string& testNodeCertHash = getTestNodeCertHash(); - const std::vector nodeCertHashVec = Utilities::stringToByteVector(testNodeCertHash); - const auto testEndpointPtr_1 = std::make_shared(testIpAddressV4_1, testPortTLS); - const auto testEndpointPtr_2 = std::make_shared(testIpAddressV4_2, testPortTLS); - std::vector> testEndpoints; - testEndpoints.push_back(testEndpointPtr_1); - testEndpoints.push_back(testEndpointPtr_2); - const std::vector> testConstEndpoints(testEndpoints); + NodeAddress nodeAddress; // When - testNodeAddress.setNodeId(testNodeId); - testNodeAddress.setRSAPublicKey(testRSAPublicKey); - testNodeAddress.setDescription(testDescription); - testNodeAddress.setNodeCertHash(testNodeCertHash); - testNodeAddress.setEndpoints(testConstEndpoints); + nodeAddress.setNodeId(getTestNodeId()); // Then - EXPECT_EQ(testNodeAddress.getNodeId(), testNodeId); - EXPECT_EQ(testNodeAddress.getPublicKey(), testRSAPublicKey); - EXPECT_EQ(testNodeAddress.getDescription(), testDescription); - EXPECT_EQ(testNodeAddress.getNodeCertHash(), nodeCertHashVec); - EXPECT_EQ(testNodeAddress.getDefaultIpAddress().toString(), testStringForIpAddressV4_1); - EXPECT_EQ(testNodeAddress.getDefaultPort(), testPortTLS); + EXPECT_EQ(nodeAddress.getNodeId(), getTestNodeId()); } -// Test creation of NodeAddress instance using a protobuf object. -TEST_F(NodeAddressTest, ConstructFromProtobuf) +//----- +TEST_F(NodeAddressTest, GetSetAccountId) { // Given - const int testPortPlain = getTestPortPlain(); - const int64_t testNodeId = getTestNodeId(); - const std::string& testRSAPublicKey = getTestRSAPublicKey(); - const std::string& testIpAddressV4 = getTestIpAddress(); - const std::string& testDescription = getTestDescription(); - auto testProtoNodeAddress = proto::NodeAddress(); - testProtoNodeAddress.set_nodeid(testNodeId); - testProtoNodeAddress.set_description(testDescription); - testProtoNodeAddress.set_rsa_pubkey(testRSAPublicKey); - proto::ServiceEndpoint* serviceEndpoint = testProtoNodeAddress.add_serviceendpoint(); - serviceEndpoint->set_ipaddressv4(testIpAddressV4); - serviceEndpoint->set_port(testPortPlain); + NodeAddress nodeAddress; // When - const NodeAddress nodeAddress = NodeAddress::fromProtobuf(testProtoNodeAddress); + nodeAddress.setAccountId(getTestAccountId()); // Then - EXPECT_EQ(nodeAddress.getDefaultIpAddress().toString(), testIpAddressV4); - EXPECT_EQ(nodeAddress.getDefaultPort(), getTestPortTLS()); - EXPECT_EQ(nodeAddress.getNodeId(), testNodeId); - EXPECT_EQ(nodeAddress.getPublicKey(), testRSAPublicKey); - EXPECT_EQ(nodeAddress.getNodeAccountId().mShardNum, 0ULL); - EXPECT_EQ(nodeAddress.getNodeAccountId().mRealmNum, 0ULL); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mAccountNum.has_value()); - EXPECT_EQ(nodeAddress.getNodeAccountId().mPublicKeyAlias, nullptr); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mEvmAddressAlias.has_value()); - EXPECT_TRUE(nodeAddress.getNodeCertHash().empty()); - EXPECT_FALSE(nodeAddress.getDescription().empty()); - EXPECT_EQ(nodeAddress.getDescription(), testDescription); - EXPECT_FALSE(nodeAddress.getEndpoints().empty()); + EXPECT_EQ(nodeAddress.getAccountId(), getTestAccountId()); } -// Test creation of NodeAddress instance using a node address represented as a string. -TEST_F(NodeAddressTest, ConstructFromString) +//----- +TEST_F(NodeAddressTest, GetSetCertHash) { // Given - const int testPort = getTestPortTLS(); - const std::string& testIpAddressV4 = getTestIpAddress(); - const std::string testNodeAddress = getTestNodeAddress(); + NodeAddress nodeAddressWithStr; + NodeAddress nodeAddressWithBytes; // When - const NodeAddress nodeAddress = NodeAddress::fromString(testNodeAddress); + nodeAddressWithStr.setCertHash(Utilities::byteVectorToString(getTestCertHash())); + nodeAddressWithBytes.setCertHash(getTestCertHash()); // Then - EXPECT_EQ(nodeAddress.getDefaultIpAddress().toString(), testIpAddressV4); - EXPECT_EQ(nodeAddress.getDefaultPort(), testPort); - EXPECT_EQ(nodeAddress.getNodeId(), -1); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mEvmAddressAlias.has_value()); - EXPECT_EQ(nodeAddress.getNodeAccountId().mShardNum, 0ULL); - EXPECT_EQ(nodeAddress.getNodeAccountId().mRealmNum, 0ULL); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mAccountNum.has_value()); - EXPECT_EQ(nodeAddress.getNodeAccountId().mPublicKeyAlias, nullptr); - EXPECT_FALSE(nodeAddress.getNodeAccountId().mEvmAddressAlias.has_value()); - EXPECT_TRUE(nodeAddress.getNodeCertHash().empty()); - EXPECT_TRUE(nodeAddress.getDescription().empty()); - EXPECT_FALSE(nodeAddress.getEndpoints().empty()); + EXPECT_EQ(nodeAddressWithStr.getCertHash(), getTestCertHash()); + EXPECT_EQ(nodeAddressWithBytes.getCertHash(), getTestCertHash()); } -// Test throwing an exception when trying to create a NodeAddress from malformed string. -TEST_F(NodeAddressTest, ConstructFromMalformedStringAndThrowException) +//----- +TEST_F(NodeAddressTest, GetSetEndpoints) { // Given - const std::string testNodeAddress_1 = "1"; - const std::string testNodeAddress_2 = "aaa.bbb.ccc.ddd"; + NodeAddress nodeAddress; + + // When + nodeAddress.setEndpoints(getTestEndpoints()); - // When & Then - EXPECT_THROW(auto nodeAddress = NodeAddress::fromString(testNodeAddress_1), std::invalid_argument); - EXPECT_THROW(auto nodeAddress = NodeAddress::fromString(testNodeAddress_2), std::invalid_argument); + // Then + EXPECT_EQ(nodeAddress.getEndpoints().size(), getTestEndpoints().size()); +} + +//----- +TEST_F(NodeAddressTest, GetSetDescription) +{ + // Given + NodeAddress nodeAddress; + + // When + nodeAddress.setDescription(getTestDescription()); + + // Then + EXPECT_EQ(nodeAddress.getDescription(), getTestDescription()); } diff --git a/sdk/tests/unit/ScheduleCreateTransactionUnitTests.cc b/sdk/tests/unit/ScheduleCreateTransactionUnitTests.cc index 71393b3e1..e1458e1fd 100644 --- a/sdk/tests/unit/ScheduleCreateTransactionUnitTests.cc +++ b/sdk/tests/unit/ScheduleCreateTransactionUnitTests.cc @@ -35,15 +35,12 @@ class ScheduleCreateTransactionTests : public ::testing::Test protected: void SetUp() override { - mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); - mTestSchedulableTransactionBody.set_memo("test memo"); mTestSchedulableTransactionBody.set_transactionfee(1ULL); mTestSchedulableTransactionBody.set_allocated_cryptoapproveallowance( new proto::CryptoApproveAllowanceTransactionBody); } - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const proto::SchedulableTransactionBody& getTestSchedulableTransactionBody() const { return mTestSchedulableTransactionBody; @@ -58,7 +55,6 @@ class ScheduleCreateTransactionTests : public ::testing::Test [[nodiscard]] inline bool getTestWaitForExpiry() const { return mTestWaitForExpiry; } private: - Client mClient; proto::SchedulableTransactionBody mTestSchedulableTransactionBody; const std::string mTestMemo = "my test memo"; const std::shared_ptr mTestAdminKey = ECDSAsecp256k1PrivateKey::generatePrivateKey()->getPublicKey(); @@ -113,8 +109,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetScheduledTransaction) TEST_F(ScheduleCreateTransactionTests, GetSetScheduledTransactionFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setScheduledTransaction(WrappedTransaction(AccountAllowanceApproveTransaction())), @@ -138,8 +136,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetMemo) TEST_F(ScheduleCreateTransactionTests, GetSetMemoFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setScheduleMemo(getTestMemo()), IllegalStateException); @@ -162,8 +162,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetAdminKey) TEST_F(ScheduleCreateTransactionTests, GetSetAdminKeyFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey()), IllegalStateException); @@ -186,8 +188,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetPayerAccountId) TEST_F(ScheduleCreateTransactionTests, GetSetPayerAccountIdFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setPayerAccountId(getTestPayerAccountId()), IllegalStateException); @@ -210,8 +214,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetExpirationTime) TEST_F(ScheduleCreateTransactionTests, GetSetExpirationTimeFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -234,8 +240,10 @@ TEST_F(ScheduleCreateTransactionTests, GetSetWaitForExpiry) TEST_F(ScheduleCreateTransactionTests, GetSetWaitForExpiryFrozen) { // Given - ScheduleCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleCreateTransaction transaction = ScheduleCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setWaitForExpiry(getTestWaitForExpiry()), IllegalStateException); diff --git a/sdk/tests/unit/ScheduleDeleteTransactionUnitTests.cc b/sdk/tests/unit/ScheduleDeleteTransactionUnitTests.cc index 403dbc9ce..5ac3ee3c8 100644 --- a/sdk/tests/unit/ScheduleDeleteTransactionUnitTests.cc +++ b/sdk/tests/unit/ScheduleDeleteTransactionUnitTests.cc @@ -30,13 +30,9 @@ using namespace Hedera; class ScheduleDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const ScheduleId& getTestScheduleId() const { return mTestScheduleId; } private: - Client mClient; const ScheduleId mTestScheduleId = ScheduleId(1ULL); }; @@ -84,8 +80,10 @@ TEST_F(ScheduleDeleteTransactionTest, GetSetScheduleId) TEST_F(ScheduleDeleteTransactionTest, GetSetScheduleIdFrozen) { // Given - ScheduleDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleDeleteTransaction transaction = ScheduleDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setScheduleId(getTestScheduleId()), IllegalStateException); diff --git a/sdk/tests/unit/ScheduleSignTransactionUnitTests.cc b/sdk/tests/unit/ScheduleSignTransactionUnitTests.cc index 733a14cee..328ad05e4 100644 --- a/sdk/tests/unit/ScheduleSignTransactionUnitTests.cc +++ b/sdk/tests/unit/ScheduleSignTransactionUnitTests.cc @@ -30,13 +30,9 @@ using namespace Hedera; class ScheduleSignTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const ScheduleId& getTestScheduleId() const { return mTestScheduleId; } private: - Client mClient; const ScheduleId mTestScheduleId = ScheduleId(1ULL); }; @@ -84,8 +80,10 @@ TEST_F(ScheduleSignTransactionTest, GetSetScheduleId) TEST_F(ScheduleSignTransactionTest, GetSetScheduleIdFrozen) { // Given - ScheduleSignTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleSignTransaction transaction = ScheduleSignTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setScheduleId(getTestScheduleId()), IllegalStateException); @@ -109,8 +107,10 @@ TEST_F(ScheduleSignTransactionTest, ClearScheduleId) TEST_F(ScheduleSignTransactionTest, ClearScheduleIdFrozen) { // Given - ScheduleSignTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + ScheduleSignTransaction transaction = ScheduleSignTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.clearScheduleId(), IllegalStateException); diff --git a/sdk/tests/unit/SystemDeleteTransactionUnitTests.cc b/sdk/tests/unit/SystemDeleteTransactionUnitTests.cc index f128d5234..fb4aaac13 100644 --- a/sdk/tests/unit/SystemDeleteTransactionUnitTests.cc +++ b/sdk/tests/unit/SystemDeleteTransactionUnitTests.cc @@ -31,9 +31,6 @@ using namespace Hedera; class SystemDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const ContractId& getTestContractId() const { return mTestContractId; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestExpirationTime() const @@ -42,7 +39,6 @@ class SystemDeleteTransactionTest : public ::testing::Test } private: - Client mClient; const FileId mTestFileId = FileId(1ULL, 2ULL, 3ULL); const ContractId mTestContractId = ContractId(4ULL, 5ULL, 6ULL); const std::chrono::system_clock::time_point mTestExpirationTime = std::chrono::system_clock::now(); @@ -102,8 +98,10 @@ TEST_F(SystemDeleteTransactionTest, GetSetFileId) TEST_F(SystemDeleteTransactionTest, GetSetFileIdFrozen) { // Given - SystemDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + SystemDeleteTransaction transaction = SystemDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); @@ -127,8 +125,10 @@ TEST_F(SystemDeleteTransactionTest, GetSetContractId) TEST_F(SystemDeleteTransactionTest, GetSetContractIdFrozen) { // Given - SystemDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + SystemDeleteTransaction transaction = SystemDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractId(getTestContractId()), IllegalStateException); @@ -151,8 +151,10 @@ TEST_F(SystemDeleteTransactionTest, GetSetExpirationTime) TEST_F(SystemDeleteTransactionTest, GetSetExpirationTimeFrozen) { // Given - SystemDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + SystemDeleteTransaction transaction = SystemDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); diff --git a/sdk/tests/unit/SystemUndeleteTransactionUnitTests.cc b/sdk/tests/unit/SystemUndeleteTransactionUnitTests.cc index 5b3375a1f..f35a473b2 100644 --- a/sdk/tests/unit/SystemUndeleteTransactionUnitTests.cc +++ b/sdk/tests/unit/SystemUndeleteTransactionUnitTests.cc @@ -30,14 +30,10 @@ using namespace Hedera; class SystemUndeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const FileId& getTestFileId() const { return mTestFileId; } [[nodiscard]] inline const ContractId& getTestContractId() const { return mTestContractId; } private: - Client mClient; const FileId mTestFileId = FileId(1ULL, 2ULL, 3ULL); const ContractId mTestContractId = ContractId(4ULL, 5ULL, 6ULL); }; @@ -90,8 +86,10 @@ TEST_F(SystemUndeleteTransactionTest, GetSetFileId) TEST_F(SystemUndeleteTransactionTest, GetSetFileIdFrozen) { // Given - SystemUndeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + SystemUndeleteTransaction transaction = SystemUndeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFileId(getTestFileId()), IllegalStateException); @@ -115,8 +113,10 @@ TEST_F(SystemUndeleteTransactionTest, GetSetContractId) TEST_F(SystemUndeleteTransactionTest, GetSetContractIdFrozen) { // Given - SystemUndeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + SystemUndeleteTransaction transaction = SystemUndeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setContractId(getTestContractId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenAssociateTransactionUnitTests.cc b/sdk/tests/unit/TokenAssociateTransactionUnitTests.cc index 764946af3..1cff8dba7 100644 --- a/sdk/tests/unit/TokenAssociateTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenAssociateTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenAssociateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const std::vector& getTestTokenIds() const { return mTestTokenIds; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const std::vector mTestTokenIds = { TokenId(4ULL, 5ULL, 6ULL), TokenId(7ULL, 8ULL, 9ULL), @@ -85,8 +81,10 @@ TEST_F(TokenAssociateTransactionTest, GetSetAccountId) TEST_F(TokenAssociateTransactionTest, GetSetAccountIdFrozen) { // Given - TokenAssociateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenAssociateTransaction transaction = TokenAssociateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -109,8 +107,10 @@ TEST_F(TokenAssociateTransactionTest, GetSetTokenIds) TEST_F(TokenAssociateTransactionTest, GetSetTokenIdFrozen) { // Given - TokenAssociateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenAssociateTransaction transaction = TokenAssociateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenIds(getTestTokenIds()), IllegalStateException); diff --git a/sdk/tests/unit/TokenBurnTransactionUnitTests.cc b/sdk/tests/unit/TokenBurnTransactionUnitTests.cc index 75b894e25..4d9d7fbf2 100644 --- a/sdk/tests/unit/TokenBurnTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenBurnTransactionUnitTests.cc @@ -30,15 +30,11 @@ using namespace Hedera; class TokenBurnTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } [[nodiscard]] inline const uint64_t& getTestAmount() const { return mTestAmount; } [[nodiscard]] inline const std::vector& getTestSerialNumbers() const { return mTestSerialNumbers; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL, 2ULL, 3ULL); const uint64_t mTestAmount = 4ULL; const std::vector mTestSerialNumbers = { 5ULL, 6ULL, 7ULL }; @@ -86,8 +82,10 @@ TEST_F(TokenBurnTransactionTest, GetSetTokenId) TEST_F(TokenBurnTransactionTest, GetSetTokenIdFrozen) { // Given - TokenBurnTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenBurnTransaction transaction = TokenBurnTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); @@ -110,8 +108,10 @@ TEST_F(TokenBurnTransactionTest, GetSetAmount) TEST_F(TokenBurnTransactionTest, GetSetAmountFrozen) { // Given - TokenBurnTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenBurnTransaction transaction = TokenBurnTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAmount(getTestAmount()), IllegalStateException); @@ -134,8 +134,10 @@ TEST_F(TokenBurnTransactionTest, GetSetSerialNumbers) TEST_F(TokenBurnTransactionTest, GetSetSerialNumbersFrozen) { // Given - TokenBurnTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenBurnTransaction transaction = TokenBurnTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSerialNumbers(getTestSerialNumbers()), IllegalStateException); diff --git a/sdk/tests/unit/TokenCreateTransactionTest.cc b/sdk/tests/unit/TokenCreateTransactionTest.cc index 90d1eefc9..85dc1d918 100644 --- a/sdk/tests/unit/TokenCreateTransactionTest.cc +++ b/sdk/tests/unit/TokenCreateTransactionTest.cc @@ -44,9 +44,6 @@ using namespace Hedera; class TokenCreateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const std::string& getTestTokenName() const { return mTestTokenName; } [[nodiscard]] inline const std::string& getTestTokenSymbol() const { return mTestTokenSymbol; } [[nodiscard]] inline uint32_t getTestDecimals() const { return mTestDecimals; } @@ -79,7 +76,6 @@ class TokenCreateTransactionTest : public ::testing::Test [[nodiscard]] inline const std::shared_ptr& getTestPauseKey() const { return mTestPauseKey; } private: - Client mClient; const std::string mTestTokenName = "test name"; const std::string mTestTokenSymbol = "test symbol"; const uint32_t mTestDecimals = 1U; @@ -196,8 +192,10 @@ TEST_F(TokenCreateTransactionTest, GetSetName) TEST_F(TokenCreateTransactionTest, GetSetNameFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenName(getTestTokenName()), IllegalStateException); @@ -220,8 +218,10 @@ TEST_F(TokenCreateTransactionTest, GetSetSymbol) TEST_F(TokenCreateTransactionTest, GetSetSymbolFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenSymbol(getTestTokenSymbol()), IllegalStateException); @@ -244,8 +244,10 @@ TEST_F(TokenCreateTransactionTest, GetSetDecimals) TEST_F(TokenCreateTransactionTest, GetSetDecimalsFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setDecimals(getTestDecimals()), IllegalStateException); @@ -268,8 +270,10 @@ TEST_F(TokenCreateTransactionTest, GetSetInitialSupply) TEST_F(TokenCreateTransactionTest, GetSetInitialSupplyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setInitialSupply(getTestInitialSupply()), IllegalStateException); @@ -292,8 +296,10 @@ TEST_F(TokenCreateTransactionTest, GetSetTreasuryAccountId) TEST_F(TokenCreateTransactionTest, GetSetTreasuryAccountIdFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTreasuryAccountId(getTestTreasuryAccountId()), IllegalStateException); @@ -316,8 +322,10 @@ TEST_F(TokenCreateTransactionTest, GetSetAdminKey) TEST_F(TokenCreateTransactionTest, GetSetAdminKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey()), IllegalStateException); @@ -340,8 +348,10 @@ TEST_F(TokenCreateTransactionTest, GetSetKycKey) TEST_F(TokenCreateTransactionTest, GetSetKycKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKycKey(getTestKycKey()), IllegalStateException); @@ -364,8 +374,10 @@ TEST_F(TokenCreateTransactionTest, GetSetFreezeKey) TEST_F(TokenCreateTransactionTest, GetSetFreezeKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFreezeKey(getTestFreezeKey()), IllegalStateException); @@ -388,8 +400,10 @@ TEST_F(TokenCreateTransactionTest, GetSetWipeKey) TEST_F(TokenCreateTransactionTest, GetSetWipeKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setWipeKey(getTestWipeKey()), IllegalStateException); @@ -412,8 +426,10 @@ TEST_F(TokenCreateTransactionTest, GetSetSupplyKey) TEST_F(TokenCreateTransactionTest, GetSetSupplyKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSupplyKey(getTestSupplyKey()), IllegalStateException); @@ -436,8 +452,10 @@ TEST_F(TokenCreateTransactionTest, GetSetFreezeDefault) TEST_F(TokenCreateTransactionTest, GetSetFreezeDefaultFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFreezeDefault(getTestFreezeDefault()), IllegalStateException); @@ -460,8 +478,10 @@ TEST_F(TokenCreateTransactionTest, GetSetExpirationTime) TEST_F(TokenCreateTransactionTest, GetSetExpirationTimeFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -484,8 +504,10 @@ TEST_F(TokenCreateTransactionTest, GetSetAutoRenewAccountId) TEST_F(TokenCreateTransactionTest, GetSetAutoRenewAccountIdFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); @@ -508,8 +530,10 @@ TEST_F(TokenCreateTransactionTest, GetSetAutoRenewPeriod) TEST_F(TokenCreateTransactionTest, GetSetAutoRenewPeriodFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -532,8 +556,10 @@ TEST_F(TokenCreateTransactionTest, GetSetMemo) TEST_F(TokenCreateTransactionTest, GetSetMemoFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenMemo(getTestTokenMemo()), IllegalStateException); @@ -556,8 +582,10 @@ TEST_F(TokenCreateTransactionTest, GetSetTokenType) TEST_F(TokenCreateTransactionTest, GetSetTokenTypeFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenType(getTestTokenType()), IllegalStateException); @@ -580,8 +608,10 @@ TEST_F(TokenCreateTransactionTest, GetSetSupplyType) TEST_F(TokenCreateTransactionTest, GetSetSupplyTypeFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSupplyType(getTestTokenSupplyType()), IllegalStateException); @@ -604,8 +634,10 @@ TEST_F(TokenCreateTransactionTest, GetSetMaxSupply) TEST_F(TokenCreateTransactionTest, GetSetMaxSupplyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMaxSupply(getTestMaxSupply()), IllegalStateException); @@ -628,8 +660,10 @@ TEST_F(TokenCreateTransactionTest, GetSetFeeScheduleKey) TEST_F(TokenCreateTransactionTest, GetSetFeeScheduleKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFeeScheduleKey(getTestFeeScheduleKey()), IllegalStateException); @@ -652,8 +686,10 @@ TEST_F(TokenCreateTransactionTest, GetSetCustomFees) TEST_F(TokenCreateTransactionTest, GetSetCustomFeesFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setCustomFees(getTestCustomFees()), IllegalStateException); @@ -676,8 +712,10 @@ TEST_F(TokenCreateTransactionTest, GetSetPauseKey) TEST_F(TokenCreateTransactionTest, GetSetPauseKeyFrozen) { // Given - TokenCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenCreateTransaction transaction = TokenCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setPauseKey(getTestPauseKey()), IllegalStateException); diff --git a/sdk/tests/unit/TokenDeleteTransactionTest.cc b/sdk/tests/unit/TokenDeleteTransactionTest.cc index 3d86d84ec..1774e07bb 100644 --- a/sdk/tests/unit/TokenDeleteTransactionTest.cc +++ b/sdk/tests/unit/TokenDeleteTransactionTest.cc @@ -30,13 +30,9 @@ using namespace Hedera; class TokenDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL); }; @@ -84,8 +80,10 @@ TEST_F(TokenDeleteTransactionTest, GetSetTokenId) TEST_F(TokenDeleteTransactionTest, GetSetTokenIdFrozen) { // Given - TokenDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenDeleteTransaction transaction = TokenDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenDissociateTransactionUnitTests.cc b/sdk/tests/unit/TokenDissociateTransactionUnitTests.cc index df29b0117..39c7f6d0b 100644 --- a/sdk/tests/unit/TokenDissociateTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenDissociateTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenDissociateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const std::vector& getTestTokenIds() const { return mTestTokenIds; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const std::vector mTestTokenIds = { TokenId(4ULL, 5ULL, 6ULL), TokenId(7ULL, 8ULL, 9ULL), @@ -85,8 +81,10 @@ TEST_F(TokenDissociateTransactionTest, GetSetAccountId) TEST_F(TokenDissociateTransactionTest, GetSetAccountIdFrozen) { // Given - TokenDissociateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenDissociateTransaction transaction = TokenDissociateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -109,8 +107,10 @@ TEST_F(TokenDissociateTransactionTest, GetSetTokenIds) TEST_F(TokenDissociateTransactionTest, GetSetTokenIdFrozen) { // Given - TokenDissociateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenDissociateTransaction transaction = TokenDissociateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenIds(getTestTokenIds()), IllegalStateException); diff --git a/sdk/tests/unit/TokenFeeScheduleUpdateTransactionUnitTests.cc b/sdk/tests/unit/TokenFeeScheduleUpdateTransactionUnitTests.cc index e6921c11b..719d16ed0 100644 --- a/sdk/tests/unit/TokenFeeScheduleUpdateTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenFeeScheduleUpdateTransactionUnitTests.cc @@ -34,9 +34,6 @@ using namespace Hedera; class TokenFeeScheduleUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } [[nodiscard]] inline const std::vector>& getTestCustomFees() const { @@ -44,7 +41,6 @@ class TokenFeeScheduleUpdateTransactionTest : public ::testing::Test } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL); const std::vector> mTestCustomFees = { std::make_shared(), std::make_shared(), @@ -91,8 +87,10 @@ TEST_F(TokenFeeScheduleUpdateTransactionTest, GetSetTokenId) TEST_F(TokenFeeScheduleUpdateTransactionTest, GetSetTokenIdFrozen) { // Given - TokenFeeScheduleUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenFeeScheduleUpdateTransaction transaction = TokenFeeScheduleUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); @@ -115,8 +113,10 @@ TEST_F(TokenFeeScheduleUpdateTransactionTest, GetSetCustomFees) TEST_F(TokenFeeScheduleUpdateTransactionTest, GetSetCustomFeesFrozen) { // Given - TokenFeeScheduleUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenFeeScheduleUpdateTransaction transaction = TokenFeeScheduleUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setCustomFees(getTestCustomFees()), IllegalStateException); diff --git a/sdk/tests/unit/TokenFreezeTransactionUnitTests.cc b/sdk/tests/unit/TokenFreezeTransactionUnitTests.cc index 7807c563f..80d7ec976 100644 --- a/sdk/tests/unit/TokenFreezeTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenFreezeTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenFreezeTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const TokenId mTestTokenId = TokenId(4ULL, 5ULL, 6ULL); }; @@ -79,8 +75,10 @@ TEST_F(TokenFreezeTransactionTest, GetSetAccountId) TEST_F(TokenFreezeTransactionTest, GetSetAccountIdFrozen) { // Given - TokenFreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenFreezeTransaction transaction = TokenFreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -103,8 +101,10 @@ TEST_F(TokenFreezeTransactionTest, GetSetTokenId) TEST_F(TokenFreezeTransactionTest, GetSetTokenIdFrozen) { // Given - TokenFreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenFreezeTransaction transaction = TokenFreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenGrantKycTransactionUnitTests.cc b/sdk/tests/unit/TokenGrantKycTransactionUnitTests.cc index 2d20269f5..b30c52f4b 100644 --- a/sdk/tests/unit/TokenGrantKycTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenGrantKycTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenGrantKycTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const TokenId mTestTokenId = TokenId(4ULL, 5ULL, 6ULL); }; @@ -79,8 +75,10 @@ TEST_F(TokenGrantKycTransactionTest, GetSetAccountId) TEST_F(TokenGrantKycTransactionTest, GetSetAccountIdFrozen) { // Given - TokenGrantKycTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenGrantKycTransaction transaction = TokenGrantKycTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -103,8 +101,10 @@ TEST_F(TokenGrantKycTransactionTest, GetSetTokenId) TEST_F(TokenGrantKycTransactionTest, GetSetTokenIdFrozen) { // Given - TokenGrantKycTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenGrantKycTransaction transaction = TokenGrantKycTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenMintTransactionUnitTests.cc b/sdk/tests/unit/TokenMintTransactionUnitTests.cc index 598eb2dd9..3d43515f3 100644 --- a/sdk/tests/unit/TokenMintTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenMintTransactionUnitTests.cc @@ -34,9 +34,6 @@ using namespace Hedera; class TokenMintTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } [[nodiscard]] inline const uint64_t& getTestAmount() const { return mTestAmount; } [[nodiscard]] inline const std::vector>& getTestMetadataList() const @@ -45,7 +42,6 @@ class TokenMintTransactionTest : public ::testing::Test } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL, 2ULL, 3ULL); const uint64_t mTestAmount = 4ULL; const std::vector> mTestMetadataList = { @@ -97,8 +93,10 @@ TEST_F(TokenMintTransactionTest, GetSetTokenId) TEST_F(TokenMintTransactionTest, GetSetTokenIdFrozen) { // Given - TokenMintTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenMintTransaction transaction = TokenMintTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); @@ -121,8 +119,10 @@ TEST_F(TokenMintTransactionTest, GetSetAmount) TEST_F(TokenMintTransactionTest, GetSetAmountFrozen) { // Given - TokenMintTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenMintTransaction transaction = TokenMintTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAmount(getTestAmount()), IllegalStateException); @@ -145,8 +145,10 @@ TEST_F(TokenMintTransactionTest, GetSetMetadata) TEST_F(TokenMintTransactionTest, GetSetMetadataFrozen) { // Given - TokenMintTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenMintTransaction transaction = TokenMintTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMetadata(getTestMetadataList()), IllegalStateException); @@ -165,3 +167,17 @@ TEST_F(TokenMintTransactionTest, AddMetadata) // Then EXPECT_EQ(tokenMintTransaction.getMetadata(), std::vector>{ metadata }); } + +//----- +TEST_F(TokenMintTransactionTest, AddMetadataFrozen) +{ + // Given + TokenMintTransaction transaction = TokenMintTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + const std::vector metadata = { std::byte(0x0E), std::byte(0x0F) }; + ASSERT_NO_THROW(transaction.freeze()); + + // When / Then + EXPECT_THROW(transaction.addMetadata(metadata), IllegalStateException); +} diff --git a/sdk/tests/unit/TokenPauseTransactionUnitTests.cc b/sdk/tests/unit/TokenPauseTransactionUnitTests.cc index f85d21e0f..7343591ba 100644 --- a/sdk/tests/unit/TokenPauseTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenPauseTransactionUnitTests.cc @@ -30,13 +30,9 @@ using namespace Hedera; class TokenPauseTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL); }; @@ -74,8 +70,10 @@ TEST_F(TokenPauseTransactionTest, GetSetTokenId) TEST_F(TokenPauseTransactionTest, GetSetTokenIdFrozen) { // Given - TokenPauseTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenPauseTransaction transaction = TokenPauseTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenRevokeKycTransactionUnitTests.cc b/sdk/tests/unit/TokenRevokeKycTransactionUnitTests.cc index b881d70f0..dc3b322dd 100644 --- a/sdk/tests/unit/TokenRevokeKycTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenRevokeKycTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenRevokeKycTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const TokenId mTestTokenId = TokenId(4ULL, 5ULL, 6ULL); }; @@ -79,8 +75,10 @@ TEST_F(TokenRevokeKycTransactionTest, GetSetAccountId) TEST_F(TokenRevokeKycTransactionTest, GetSetAccountIdFrozen) { // Given - TokenRevokeKycTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenRevokeKycTransaction transaction = TokenRevokeKycTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -103,8 +101,10 @@ TEST_F(TokenRevokeKycTransactionTest, GetSetTokenId) TEST_F(TokenRevokeKycTransactionTest, GetSetTokenIdFrozen) { // Given - TokenRevokeKycTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenRevokeKycTransaction transaction = TokenRevokeKycTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenUnfreezeTransactionUnitTests.cc b/sdk/tests/unit/TokenUnfreezeTransactionUnitTests.cc index a70318939..dc6211e89 100644 --- a/sdk/tests/unit/TokenUnfreezeTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenUnfreezeTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TokenUnfreezeTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const AccountId mTestAccountId = AccountId(1ULL, 2ULL, 3ULL); const TokenId mTestTokenId = TokenId(4ULL, 5ULL, 6ULL); }; @@ -79,8 +75,10 @@ TEST_F(TokenUnfreezeTransactionTest, GetSetAccountId) TEST_F(TokenUnfreezeTransactionTest, GetSetAccountIdFrozen) { // Given - TokenUnfreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUnfreezeTransaction transaction = TokenUnfreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -103,8 +101,10 @@ TEST_F(TokenUnfreezeTransactionTest, GetSetTokenId) TEST_F(TokenUnfreezeTransactionTest, GetSetTokenIdFrozen) { // Given - TokenUnfreezeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUnfreezeTransaction transaction = TokenUnfreezeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenUnpauseTransactionUnitTests.cc b/sdk/tests/unit/TokenUnpauseTransactionUnitTests.cc index 974fb214e..ab8c4dec3 100644 --- a/sdk/tests/unit/TokenUnpauseTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenUnpauseTransactionUnitTests.cc @@ -30,13 +30,9 @@ using namespace Hedera; class TokenUnpauseTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL); }; @@ -74,8 +70,10 @@ TEST_F(TokenUnpauseTransactionTest, GetSetTokenId) TEST_F(TokenUnpauseTransactionTest, GetSetTokenIdFrozen) { // Given - TokenUnpauseTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUnpauseTransaction transaction = TokenUnpauseTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); diff --git a/sdk/tests/unit/TokenUpdateTransactionUnitTests.cc b/sdk/tests/unit/TokenUpdateTransactionUnitTests.cc index d364794a7..eed282652 100644 --- a/sdk/tests/unit/TokenUpdateTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenUpdateTransactionUnitTests.cc @@ -42,9 +42,6 @@ using namespace Hedera; class TokenUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } [[nodiscard]] inline const std::string& getTestTokenName() const { return mTestTokenName; } [[nodiscard]] inline const std::string& getTestTokenSymbol() const { return mTestTokenSymbol; } @@ -68,7 +65,6 @@ class TokenUpdateTransactionTest : public ::testing::Test [[nodiscard]] inline const std::shared_ptr& getTestPauseKey() const { return mTestPauseKey; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL, 2ULL, 3ULL); const std::string mTestTokenName = "test name"; const std::string mTestTokenSymbol = "test symbol"; @@ -160,8 +156,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetTokenId) TEST_F(TokenUpdateTransactionTest, GetSetTokenIdFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); @@ -184,8 +182,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetName) TEST_F(TokenUpdateTransactionTest, GetSetNameFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenName(getTestTokenName()), IllegalStateException); @@ -208,8 +208,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetSymbol) TEST_F(TokenUpdateTransactionTest, GetSetSymbolFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenSymbol(getTestTokenSymbol()), IllegalStateException); @@ -232,8 +234,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetTreasuryAccountId) TEST_F(TokenUpdateTransactionTest, GetSetTreasuryAccountIdFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTreasuryAccountId(getTestTreasuryAccountId()), IllegalStateException); @@ -256,8 +260,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetAdminKey) TEST_F(TokenUpdateTransactionTest, GetSetAdminKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey()), IllegalStateException); @@ -280,8 +286,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetKycKey) TEST_F(TokenUpdateTransactionTest, GetSetKycKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setKycKey(getTestKycKey()), IllegalStateException); @@ -304,8 +312,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetFreezeKey) TEST_F(TokenUpdateTransactionTest, GetSetFreezeKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFreezeKey(getTestFreezeKey()), IllegalStateException); @@ -328,8 +338,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetWipeKey) TEST_F(TokenUpdateTransactionTest, GetSetWipeKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setWipeKey(getTestWipeKey()), IllegalStateException); @@ -352,8 +364,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetSupplyKey) TEST_F(TokenUpdateTransactionTest, GetSetSupplyKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSupplyKey(getTestSupplyKey()), IllegalStateException); @@ -376,8 +390,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetAutoRenewAccountId) TEST_F(TokenUpdateTransactionTest, GetSetAutoRenewAccountIdFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); @@ -400,8 +416,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetAutoRenewPeriod) TEST_F(TokenUpdateTransactionTest, GetSetAutoRenewPeriodFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -424,8 +442,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetExpirationTime) TEST_F(TokenUpdateTransactionTest, GetSetExpirationTimeFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -448,8 +468,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetMemo) TEST_F(TokenUpdateTransactionTest, GetSetMemoFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenMemo(getTestTokenMemo()), IllegalStateException); @@ -472,8 +494,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetFeeScheduleKey) TEST_F(TokenUpdateTransactionTest, GetSetFeeScheduleKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setFeeScheduleKey(getTestFeeScheduleKey()), IllegalStateException); @@ -496,8 +520,10 @@ TEST_F(TokenUpdateTransactionTest, GetSetPauseKey) TEST_F(TokenUpdateTransactionTest, GetSetPauseKeyFrozen) { // Given - TokenUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenUpdateTransaction transaction = TokenUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setPauseKey(getTestPauseKey()), IllegalStateException); diff --git a/sdk/tests/unit/TokenWipeTransactionUnitTests.cc b/sdk/tests/unit/TokenWipeTransactionUnitTests.cc index bbb597de6..2e6eb6c12 100644 --- a/sdk/tests/unit/TokenWipeTransactionUnitTests.cc +++ b/sdk/tests/unit/TokenWipeTransactionUnitTests.cc @@ -30,16 +30,12 @@ using namespace Hedera; class TokenWipeTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTestTokenId; } [[nodiscard]] inline const AccountId& getTestAccountId() const { return mTestAccountId; } [[nodiscard]] inline const uint64_t& getTestAmount() const { return mTestAmount; } [[nodiscard]] inline const std::vector& getTestSerialNumbers() const { return mTestSerialNumbers; } private: - Client mClient; const TokenId mTestTokenId = TokenId(1ULL, 2ULL, 3ULL); const AccountId mTestAccountId = AccountId(4ULL, 5ULL, 6ULL); const uint64_t mTestAmount = 7ULL; @@ -90,8 +86,10 @@ TEST_F(TokenWipeTransactionTest, GetSetTokenId) TEST_F(TokenWipeTransactionTest, GetSetTokenIdFrozen) { // Given - TokenWipeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenWipeTransaction transaction = TokenWipeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTokenId(getTestTokenId()), IllegalStateException); @@ -114,8 +112,10 @@ TEST_F(TokenWipeTransactionTest, GetSetAccountId) TEST_F(TokenWipeTransactionTest, GetSetAccountIdFrozen) { // Given - TokenWipeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenWipeTransaction transaction = TokenWipeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAccountId(getTestAccountId()), IllegalStateException); @@ -138,8 +138,10 @@ TEST_F(TokenWipeTransactionTest, GetSetAmount) TEST_F(TokenWipeTransactionTest, GetSetAmountFrozen) { // Given - TokenWipeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenWipeTransaction transaction = TokenWipeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAmount(getTestAmount()), IllegalStateException); @@ -162,8 +164,10 @@ TEST_F(TokenWipeTransactionTest, GetSetSerialNumbers) TEST_F(TokenWipeTransactionTest, GetSetSerialNumbersFrozen) { // Given - TokenWipeTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TokenWipeTransaction transaction = TokenWipeTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSerialNumbers(getTestSerialNumbers()), IllegalStateException); diff --git a/sdk/tests/unit/TopicCreateTransactionUnitTests.cc b/sdk/tests/unit/TopicCreateTransactionUnitTests.cc index 3bf079d48..36afbfdb3 100644 --- a/sdk/tests/unit/TopicCreateTransactionUnitTests.cc +++ b/sdk/tests/unit/TopicCreateTransactionUnitTests.cc @@ -33,9 +33,6 @@ using namespace Hedera; class TopicCreateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const std::string& getTestTopicMemo() const { return mTestTopicMemo; } [[nodiscard]] inline const std::shared_ptr& getTestAdminKey() const { return mTestAdminKey; } [[nodiscard]] inline const std::shared_ptr& getTestSubmitKey() const { return mTestSubmitKey; } @@ -46,7 +43,6 @@ class TopicCreateTransactionTest : public ::testing::Test [[nodiscard]] inline const AccountId& getTestAutoRenewAccountId() const { return mTestAutoRenewAccountId; } private: - Client mClient; const std::string mTestTopicMemo = "test topic memo"; const std::shared_ptr mTestAdminKey = ED25519PrivateKey::generatePrivateKey(); const std::shared_ptr mTestSubmitKey = ED25519PrivateKey::generatePrivateKey(); @@ -108,8 +104,10 @@ TEST_F(TopicCreateTransactionTest, GetSetMemo) TEST_F(TopicCreateTransactionTest, GetSetMemoFrozen) { // Given - TopicCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicCreateTransaction transaction = TopicCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMemo(getTestTopicMemo()), IllegalStateException); @@ -132,8 +130,10 @@ TEST_F(TopicCreateTransactionTest, GetSetAdminKey) TEST_F(TopicCreateTransactionTest, GetSetAdminKeyFrozen) { // Given - TopicCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicCreateTransaction transaction = TopicCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey()), IllegalStateException); @@ -156,8 +156,10 @@ TEST_F(TopicCreateTransactionTest, GetSetSubmitKey) TEST_F(TopicCreateTransactionTest, GetSetSubmitKeyFrozen) { // Given - TopicCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicCreateTransaction transaction = TopicCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSubmitKey(getTestSubmitKey()), IllegalStateException); @@ -180,8 +182,10 @@ TEST_F(TopicCreateTransactionTest, GetSetAutoRenewPeriod) TEST_F(TopicCreateTransactionTest, GetSetAutoRenewPeriodFrozen) { // Given - TopicCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicCreateTransaction transaction = TopicCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -204,8 +208,10 @@ TEST_F(TopicCreateTransactionTest, GetSetAutoRenewAccountId) TEST_F(TopicCreateTransactionTest, GetSetAutoRenewAccountIdFrozen) { // Given - TopicCreateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicCreateTransaction transaction = TopicCreateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); diff --git a/sdk/tests/unit/TopicDeleteTransactionUnitTests.cc b/sdk/tests/unit/TopicDeleteTransactionUnitTests.cc index 755de41f6..512af6b37 100644 --- a/sdk/tests/unit/TopicDeleteTransactionUnitTests.cc +++ b/sdk/tests/unit/TopicDeleteTransactionUnitTests.cc @@ -30,13 +30,9 @@ using namespace Hedera; class TopicDeleteTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TopicId& getTestTopicId() const { return mTestTopicId; } private: - Client mClient; const TopicId mTestTopicId = TopicId(1ULL); }; @@ -84,8 +80,10 @@ TEST_F(TopicDeleteTransactionTest, GetSetTopicId) TEST_F(TopicDeleteTransactionTest, GetSetTopicIdFrozen) { // Given - TopicDeleteTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicDeleteTransaction transaction = TopicDeleteTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTopicId(getTestTopicId()), IllegalStateException); diff --git a/sdk/tests/unit/TopicMessageSubmitTransactionUnitTests.cc b/sdk/tests/unit/TopicMessageSubmitTransactionUnitTests.cc index 4e9e98a36..e869880db 100644 --- a/sdk/tests/unit/TopicMessageSubmitTransactionUnitTests.cc +++ b/sdk/tests/unit/TopicMessageSubmitTransactionUnitTests.cc @@ -31,14 +31,10 @@ using namespace Hedera; class TopicMessageSubmitTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TopicId& getTestTopicId() const { return mTestTopicId; } [[nodiscard]] inline const std::vector& getTestMessage() const { return mTestMessage; } private: - Client mClient; const TopicId mTestTopicId = TopicId(1ULL, 2ULL, 3ULL); const std::vector mTestMessage = { std::byte(0x04), std::byte(0x05), std::byte(0x06) }; }; @@ -78,8 +74,10 @@ TEST_F(TopicMessageSubmitTransactionTest, GetSetTopicId) TEST_F(TopicMessageSubmitTransactionTest, GetSetTopicIdFrozen) { // Given - TopicMessageSubmitTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicMessageSubmitTransaction transaction = TopicMessageSubmitTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTopicId(getTestTopicId()), IllegalStateException); @@ -105,10 +103,14 @@ TEST_F(TopicMessageSubmitTransactionTest, GetSetMessage) TEST_F(TopicMessageSubmitTransactionTest, GetSetMessageFrozen) { // Given - TopicMessageSubmitTransaction transactionWithBytes; - TopicMessageSubmitTransaction transactionWithStr; - ASSERT_NO_THROW(transactionWithBytes.freezeWith(&getTestClient())); - ASSERT_NO_THROW(transactionWithStr.freezeWith(&getTestClient())); + TopicMessageSubmitTransaction transactionWithBytes = TopicMessageSubmitTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + TopicMessageSubmitTransaction transactionWithStr = TopicMessageSubmitTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transactionWithBytes.freeze()); + ASSERT_NO_THROW(transactionWithStr.freeze()); // When / Then EXPECT_THROW(transactionWithBytes.setMessage(getTestMessage()), IllegalStateException); diff --git a/sdk/tests/unit/TopicUpdateTransactionUnitTests.cc b/sdk/tests/unit/TopicUpdateTransactionUnitTests.cc index df05a008e..7fa550c04 100644 --- a/sdk/tests/unit/TopicUpdateTransactionUnitTests.cc +++ b/sdk/tests/unit/TopicUpdateTransactionUnitTests.cc @@ -34,9 +34,6 @@ using namespace Hedera; class TopicUpdateTransactionTest : public ::testing::Test { protected: - void SetUp() override { mClient.setOperator(AccountId(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const TopicId& getTestTopicId() const { return mTestTopicId; } [[nodiscard]] inline const std::string& getTestTopicMemo() const { return mTestTopicMemo; } [[nodiscard]] inline const std::chrono::system_clock::time_point& getTestExpirationTime() const @@ -52,7 +49,6 @@ class TopicUpdateTransactionTest : public ::testing::Test [[nodiscard]] inline const AccountId& getTestAutoRenewAccountId() const { return mTestAutoRenewAccountId; } private: - Client mClient; const TopicId mTestTopicId = TopicId(1ULL, 2ULL, 3ULL); const std::string mTestTopicMemo = "test topic memo"; const std::chrono::system_clock::time_point mTestExpirationTime = std::chrono::system_clock::now(); @@ -120,8 +116,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetTopicId) TEST_F(TopicUpdateTransactionTest, GetSetTopicIdFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setTopicId(getTestTopicId()), IllegalStateException); @@ -144,8 +142,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetMemo) TEST_F(TopicUpdateTransactionTest, GetSetMemoFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setMemo(getTestTopicMemo()), IllegalStateException); @@ -169,8 +169,10 @@ TEST_F(TopicUpdateTransactionTest, ClearMemo) TEST_F(TopicUpdateTransactionTest, ClearMemoFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.clearTopicMemo(), IllegalStateException); @@ -193,8 +195,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetExpirationTime) TEST_F(TopicUpdateTransactionTest, GetSetExpirationTimeFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setExpirationTime(getTestExpirationTime()), IllegalStateException); @@ -217,8 +221,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetAdminKey) TEST_F(TopicUpdateTransactionTest, GetSetAdminKeyFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAdminKey(getTestAdminKey()), IllegalStateException); @@ -241,8 +247,10 @@ TEST_F(TopicUpdateTransactionTest, ClearAdminKey) TEST_F(TopicUpdateTransactionTest, ClearAdminKeyFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.clearAdminKey(), IllegalStateException); @@ -265,8 +273,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetSubmitKey) TEST_F(TopicUpdateTransactionTest, GetSetSubmitKeyFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setSubmitKey(getTestSubmitKey()), IllegalStateException); @@ -289,8 +299,10 @@ TEST_F(TopicUpdateTransactionTest, ClearSubmitKey) TEST_F(TopicUpdateTransactionTest, ClearSubmitKeyFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.clearAdminKey(), IllegalStateException); @@ -313,8 +325,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetAutoRenewPeriod) TEST_F(TopicUpdateTransactionTest, GetSetAutoRenewPeriodFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewPeriod(getTestAutoRenewPeriod()), IllegalStateException); @@ -337,8 +351,10 @@ TEST_F(TopicUpdateTransactionTest, GetSetAutoRenewAccountId) TEST_F(TopicUpdateTransactionTest, GetSetAutoRenewAccountIdFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.setAutoRenewAccountId(getTestAutoRenewAccountId()), IllegalStateException); @@ -362,8 +378,10 @@ TEST_F(TopicUpdateTransactionTest, ClearAutoRenewAccountId) TEST_F(TopicUpdateTransactionTest, ClearAutoRenewAccountIdFrozen) { // Given - TopicUpdateTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TopicUpdateTransaction transaction = TopicUpdateTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.clearAutoRenewAccountId(), IllegalStateException); diff --git a/sdk/tests/unit/TransactionTest.cc b/sdk/tests/unit/TransactionTest.cc index 7b090cccc..508c40f54 100644 --- a/sdk/tests/unit/TransactionTest.cc +++ b/sdk/tests/unit/TransactionTest.cc @@ -66,6 +66,7 @@ #include #include #include +#include using namespace Hedera; @@ -90,7 +91,7 @@ TEST_F(TransactionTest, AccountApproveAllowanceFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, AccountApproveAllowanceFromSignedTransactionBytes) +TEST_F(TransactionTest, AccountApproveAllowanceFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -100,9 +101,12 @@ TEST_F(TransactionTest, AccountApproveAllowanceFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_ALLOWANCE_APPROVE_TRANSACTION); @@ -110,7 +114,7 @@ TEST_F(TransactionTest, AccountApproveAllowanceFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, AccountApproveAllowanceFromTransactionBytes) +TEST_F(TransactionTest, AccountApproveAllowanceFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -123,9 +127,12 @@ TEST_F(TransactionTest, AccountApproveAllowanceFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(tx.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_ALLOWANCE_APPROVE_TRANSACTION); @@ -149,7 +156,7 @@ TEST_F(TransactionTest, AccountDeleteAllowanceFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, AccountDeleteAllowanceFromSignedTransactionBytes) +TEST_F(TransactionTest, AccountDeleteAllowanceFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -159,9 +166,12 @@ TEST_F(TransactionTest, AccountDeleteAllowanceFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_ALLOWANCE_DELETE_TRANSACTION); @@ -169,7 +179,7 @@ TEST_F(TransactionTest, AccountDeleteAllowanceFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, AccountDeleteAllowanceFromTransactionBytes) +TEST_F(TransactionTest, AccountDeleteAllowanceFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -182,9 +192,12 @@ TEST_F(TransactionTest, AccountDeleteAllowanceFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(tx.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_ALLOWANCE_DELETE_TRANSACTION); @@ -208,7 +221,7 @@ TEST_F(TransactionTest, AccountCreateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, AccountCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, AccountCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -218,9 +231,12 @@ TEST_F(TransactionTest, AccountCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_CREATE_TRANSACTION); @@ -228,7 +244,7 @@ TEST_F(TransactionTest, AccountCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, AccountCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, AccountCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -241,9 +257,12 @@ TEST_F(TransactionTest, AccountCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_CREATE_TRANSACTION); @@ -267,7 +286,7 @@ TEST_F(TransactionTest, AccountDeleteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, AccountDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, AccountDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -277,9 +296,12 @@ TEST_F(TransactionTest, AccountDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_DELETE_TRANSACTION); @@ -287,7 +309,7 @@ TEST_F(TransactionTest, AccountDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, AccountDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, AccountDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -300,9 +322,12 @@ TEST_F(TransactionTest, AccountDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_DELETE_TRANSACTION); @@ -326,7 +351,7 @@ TEST_F(TransactionTest, AccountUpdateTransactionFromTransactionBodyByte) } //----- -TEST_F(TransactionTest, AccountUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, AccountUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -336,9 +361,12 @@ TEST_F(TransactionTest, AccountUpdateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_UPDATE_TRANSACTION); @@ -346,7 +374,7 @@ TEST_F(TransactionTest, AccountUpdateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, AccountUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, AccountUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -359,9 +387,12 @@ TEST_F(TransactionTest, AccountUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ACCOUNT_UPDATE_TRANSACTION); @@ -385,7 +416,7 @@ TEST_F(TransactionTest, ContractCreateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, ContractCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ContractCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -395,9 +426,12 @@ TEST_F(TransactionTest, ContractCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_CREATE_TRANSACTION); @@ -405,7 +439,7 @@ TEST_F(TransactionTest, ContractCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ContractCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, ContractCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -418,9 +452,12 @@ TEST_F(TransactionTest, ContractCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_CREATE_TRANSACTION); @@ -444,7 +481,7 @@ TEST_F(TransactionTest, ContractDeleteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, ContractDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ContractDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -454,9 +491,12 @@ TEST_F(TransactionTest, ContractDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_DELETE_TRANSACTION); @@ -464,7 +504,7 @@ TEST_F(TransactionTest, ContractDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ContractDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, ContractDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -477,9 +517,12 @@ TEST_F(TransactionTest, ContractDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_DELETE_TRANSACTION); @@ -503,7 +546,7 @@ TEST_F(TransactionTest, ContractExecuteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, ContractExecuteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ContractExecuteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -513,9 +556,12 @@ TEST_F(TransactionTest, ContractExecuteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_EXECUTE_TRANSACTION); @@ -523,7 +569,7 @@ TEST_F(TransactionTest, ContractExecuteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ContractExecuteTransactionFromTransactionBytes) +TEST_F(TransactionTest, ContractExecuteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -536,9 +582,12 @@ TEST_F(TransactionTest, ContractExecuteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_EXECUTE_TRANSACTION); @@ -562,7 +611,7 @@ TEST_F(TransactionTest, ContractUpdateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, ContractUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ContractUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -572,9 +621,12 @@ TEST_F(TransactionTest, ContractUpdateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_UPDATE_TRANSACTION); @@ -582,7 +634,7 @@ TEST_F(TransactionTest, ContractUpdateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ContractUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, ContractUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -595,9 +647,12 @@ TEST_F(TransactionTest, ContractUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::CONTRACT_UPDATE_TRANSACTION); @@ -621,7 +676,7 @@ TEST_F(TransactionTest, EthereumTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, EthereumTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, EthereumTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -631,9 +686,12 @@ TEST_F(TransactionTest, EthereumTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ETHEREUM_TRANSACTION); @@ -641,7 +699,7 @@ TEST_F(TransactionTest, EthereumTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, EthereumTransactionFromTransactionBytes) +TEST_F(TransactionTest, EthereumTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -654,9 +712,12 @@ TEST_F(TransactionTest, EthereumTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::ETHEREUM_TRANSACTION); @@ -679,7 +740,7 @@ TEST_F(TransactionTest, FileAppendTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, FileAppendTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, FileAppendTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -689,6 +750,9 @@ TEST_F(TransactionTest, FileAppendTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -699,7 +763,7 @@ TEST_F(TransactionTest, FileAppendTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, FileAppendTransactionFromTransactionBytes) +TEST_F(TransactionTest, FileAppendTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -712,9 +776,12 @@ TEST_F(TransactionTest, FileAppendTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_APPEND_TRANSACTION); @@ -738,7 +805,7 @@ TEST_F(TransactionTest, FileCreateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, FileCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, FileCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -748,9 +815,12 @@ TEST_F(TransactionTest, FileCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_CREATE_TRANSACTION); @@ -758,7 +828,7 @@ TEST_F(TransactionTest, FileCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, FileCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, FileCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -771,9 +841,12 @@ TEST_F(TransactionTest, FileCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_CREATE_TRANSACTION); @@ -797,7 +870,7 @@ TEST_F(TransactionTest, FileDeleteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, FileDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, FileDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -807,9 +880,12 @@ TEST_F(TransactionTest, FileDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_DELETE_TRANSACTION); @@ -817,7 +893,7 @@ TEST_F(TransactionTest, FileDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, FileDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, FileDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -830,9 +906,12 @@ TEST_F(TransactionTest, FileDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_DELETE_TRANSACTION); @@ -856,7 +935,7 @@ TEST_F(TransactionTest, FileUpdateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, FileUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, FileUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -866,6 +945,9 @@ TEST_F(TransactionTest, FileUpdateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -876,7 +958,7 @@ TEST_F(TransactionTest, FileUpdateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, FileUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, FileUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -889,9 +971,12 @@ TEST_F(TransactionTest, FileUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FILE_UPDATE_TRANSACTION); @@ -915,7 +1000,7 @@ TEST_F(TransactionTest, FreezeTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, FreezeTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, FreezeTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -925,6 +1010,9 @@ TEST_F(TransactionTest, FreezeTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -935,7 +1023,7 @@ TEST_F(TransactionTest, FreezeTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, FreezeTransactionFromTransactionBytes) +TEST_F(TransactionTest, FreezeTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -948,9 +1036,12 @@ TEST_F(TransactionTest, FreezeTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::FREEZE_TRANSACTION); @@ -974,7 +1065,7 @@ TEST_F(TransactionTest, ScheduleCreateTransactionTransactionFromTransactionBodyB } //----- -TEST_F(TransactionTest, ScheduleCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ScheduleCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -984,9 +1075,12 @@ TEST_F(TransactionTest, ScheduleCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_CREATE_TRANSACTION); @@ -994,7 +1088,7 @@ TEST_F(TransactionTest, ScheduleCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ScheduleCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, ScheduleCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1007,9 +1101,12 @@ TEST_F(TransactionTest, ScheduleCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_CREATE_TRANSACTION); @@ -1033,7 +1130,7 @@ TEST_F(TransactionTest, ScheduleDeleteTransactionTransactionFromTransactionBodyB } //----- -TEST_F(TransactionTest, ScheduleDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ScheduleDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1043,9 +1140,12 @@ TEST_F(TransactionTest, ScheduleDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_DELETE_TRANSACTION); @@ -1053,7 +1153,7 @@ TEST_F(TransactionTest, ScheduleDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ScheduleDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, ScheduleDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1066,9 +1166,12 @@ TEST_F(TransactionTest, ScheduleDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_DELETE_TRANSACTION); @@ -1092,7 +1195,7 @@ TEST_F(TransactionTest, ScheduleSignTransactionTransactionFromTransactionBodyByt } //----- -TEST_F(TransactionTest, ScheduleSignTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, ScheduleSignTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1102,9 +1205,12 @@ TEST_F(TransactionTest, ScheduleSignTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_SIGN_TRANSACTION); @@ -1112,7 +1218,7 @@ TEST_F(TransactionTest, ScheduleSignTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, ScheduleSignTransactionFromTransactionBytes) +TEST_F(TransactionTest, ScheduleSignTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1125,9 +1231,12 @@ TEST_F(TransactionTest, ScheduleSignTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SCHEDULE_SIGN_TRANSACTION); @@ -1151,7 +1260,7 @@ TEST_F(TransactionTest, SystemDeleteTransactionTransactionFromTransactionBodyByt } //----- -TEST_F(TransactionTest, SystemDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, SystemDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1161,9 +1270,12 @@ TEST_F(TransactionTest, SystemDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SYSTEM_DELETE_TRANSACTION); @@ -1171,7 +1283,7 @@ TEST_F(TransactionTest, SystemDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, SystemDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, SystemDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1184,9 +1296,12 @@ TEST_F(TransactionTest, SystemDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SYSTEM_DELETE_TRANSACTION); @@ -1210,7 +1325,7 @@ TEST_F(TransactionTest, SystemUndeleteTransactionTransactionFromTransactionBodyB } //----- -TEST_F(TransactionTest, SystemUndeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, SystemUndeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1220,9 +1335,12 @@ TEST_F(TransactionTest, SystemUndeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SYSTEM_UNDELETE_TRANSACTION); @@ -1230,7 +1348,7 @@ TEST_F(TransactionTest, SystemUndeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, SystemUndeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, SystemUndeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1243,9 +1361,12 @@ TEST_F(TransactionTest, SystemUndeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When - const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + const WrappedTransaction wrappedTx = Transaction::fromBytes( + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::SYSTEM_UNDELETE_TRANSACTION); @@ -1269,7 +1390,7 @@ TEST_F(TransactionTest, TokenAssociateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenAssociateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenAssociateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1279,6 +1400,9 @@ TEST_F(TransactionTest, TokenAssociateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1289,7 +1413,7 @@ TEST_F(TransactionTest, TokenAssociateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenAssociateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenAssociateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1302,9 +1426,12 @@ TEST_F(TransactionTest, TokenAssociateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_ASSOCIATE_TRANSACTION); @@ -1328,7 +1455,7 @@ TEST_F(TransactionTest, TokenBurnTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenBurnTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenBurnTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1338,6 +1465,9 @@ TEST_F(TransactionTest, TokenBurnTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1348,7 +1478,7 @@ TEST_F(TransactionTest, TokenBurnTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenBurnTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenBurnTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1361,9 +1491,12 @@ TEST_F(TransactionTest, TokenBurnTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_BURN_TRANSACTION); @@ -1387,7 +1520,7 @@ TEST_F(TransactionTest, TokenCreateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1397,6 +1530,9 @@ TEST_F(TransactionTest, TokenCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1407,7 +1543,7 @@ TEST_F(TransactionTest, TokenCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1420,9 +1556,12 @@ TEST_F(TransactionTest, TokenCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_CREATE_TRANSACTION); @@ -1446,7 +1585,7 @@ TEST_F(TransactionTest, TokenDeleteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1456,6 +1595,9 @@ TEST_F(TransactionTest, TokenDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1466,7 +1608,7 @@ TEST_F(TransactionTest, TokenDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1479,9 +1621,12 @@ TEST_F(TransactionTest, TokenDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_DELETE_TRANSACTION); @@ -1505,7 +1650,7 @@ TEST_F(TransactionTest, TokenDissociateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenDissociateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenDissociateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1515,6 +1660,9 @@ TEST_F(TransactionTest, TokenDissociateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1525,7 +1673,7 @@ TEST_F(TransactionTest, TokenDissociateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenDissociateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenDissociateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1538,9 +1686,12 @@ TEST_F(TransactionTest, TokenDissociateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_DISSOCIATE_TRANSACTION); @@ -1564,7 +1715,7 @@ TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromTransactionBodyByte } //----- -TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1574,6 +1725,9 @@ TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromSignedTransactionBy signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1584,7 +1738,7 @@ TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromSignedTransactionBy } //----- -TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1597,9 +1751,12 @@ TEST_F(TransactionTest, TokenFeeScheduleUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_FEE_SCHEDULE_UPDATE_TRANSACTION); @@ -1623,7 +1780,7 @@ TEST_F(TransactionTest, TokenFreezeTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenFreezeTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenFreezeTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1633,6 +1790,9 @@ TEST_F(TransactionTest, TokenFreezeTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1643,7 +1803,7 @@ TEST_F(TransactionTest, TokenFreezeTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenFreezeTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenFreezeTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1656,9 +1816,12 @@ TEST_F(TransactionTest, TokenFreezeTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_FREEZE_TRANSACTION); @@ -1682,7 +1845,7 @@ TEST_F(TransactionTest, TokenGrantKycTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenGrantKycTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenGrantKycTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1692,6 +1855,9 @@ TEST_F(TransactionTest, TokenGrantKycTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1702,7 +1868,7 @@ TEST_F(TransactionTest, TokenGrantKycTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenGrantKycTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenGrantKycTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1715,9 +1881,12 @@ TEST_F(TransactionTest, TokenGrantKycTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_GRANT_KYC_TRANSACTION); @@ -1741,7 +1910,7 @@ TEST_F(TransactionTest, TokenMintTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenMintTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenMintTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1751,6 +1920,9 @@ TEST_F(TransactionTest, TokenMintTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1761,7 +1933,7 @@ TEST_F(TransactionTest, TokenMintTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenMintTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenMintTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1774,9 +1946,12 @@ TEST_F(TransactionTest, TokenMintTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_MINT_TRANSACTION); @@ -1800,7 +1975,7 @@ TEST_F(TransactionTest, TokenPauseTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenPauseTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenPauseTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1810,6 +1985,9 @@ TEST_F(TransactionTest, TokenPauseTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1820,7 +1998,7 @@ TEST_F(TransactionTest, TokenPauseTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenPauseTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenPauseTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1833,9 +2011,12 @@ TEST_F(TransactionTest, TokenPauseTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_PAUSE_TRANSACTION); @@ -1859,7 +2040,7 @@ TEST_F(TransactionTest, TokenRevokeKycTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenRevokeKycTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenRevokeKycTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1869,6 +2050,9 @@ TEST_F(TransactionTest, TokenRevokeKycTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1879,7 +2063,7 @@ TEST_F(TransactionTest, TokenRevokeKycTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenRevokeKycTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenRevokeKycTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1892,9 +2076,12 @@ TEST_F(TransactionTest, TokenRevokeKycTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_REVOKE_KYC_TRANSACTION); @@ -1918,7 +2105,7 @@ TEST_F(TransactionTest, TokenUnfreezeTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenUnfreezeTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenUnfreezeTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1928,6 +2115,9 @@ TEST_F(TransactionTest, TokenUnfreezeTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1938,7 +2128,7 @@ TEST_F(TransactionTest, TokenUnfreezeTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenUnfreezeTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenUnfreezeTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -1951,9 +2141,12 @@ TEST_F(TransactionTest, TokenUnfreezeTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_UNFREEZE_TRANSACTION); @@ -1977,7 +2170,7 @@ TEST_F(TransactionTest, TokenUnpauseTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenUnpauseTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenUnpauseTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -1987,6 +2180,9 @@ TEST_F(TransactionTest, TokenUnpauseTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -1997,7 +2193,7 @@ TEST_F(TransactionTest, TokenUnpauseTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenUnpauseTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenUnpauseTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2010,9 +2206,12 @@ TEST_F(TransactionTest, TokenUnpauseTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_UNPAUSE_TRANSACTION); @@ -2036,7 +2235,7 @@ TEST_F(TransactionTest, TokenUpdateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2046,6 +2245,9 @@ TEST_F(TransactionTest, TokenUpdateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -2056,7 +2258,7 @@ TEST_F(TransactionTest, TokenUpdateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2069,9 +2271,12 @@ TEST_F(TransactionTest, TokenUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_UPDATE_TRANSACTION); @@ -2095,7 +2300,7 @@ TEST_F(TransactionTest, TokenWipeTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TokenWipeTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TokenWipeTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2105,6 +2310,9 @@ TEST_F(TransactionTest, TokenWipeTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -2115,7 +2323,7 @@ TEST_F(TransactionTest, TokenWipeTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TokenWipeTransactionFromTransactionBytes) +TEST_F(TransactionTest, TokenWipeTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2128,9 +2336,12 @@ TEST_F(TransactionTest, TokenWipeTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOKEN_WIPE_TRANSACTION); @@ -2154,7 +2365,7 @@ TEST_F(TransactionTest, TopicCreateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TopicCreateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TopicCreateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2164,6 +2375,9 @@ TEST_F(TransactionTest, TopicCreateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -2174,7 +2388,7 @@ TEST_F(TransactionTest, TopicCreateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TopicCreateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TopicCreateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2187,9 +2401,12 @@ TEST_F(TransactionTest, TopicCreateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_CREATE_TRANSACTION); @@ -2213,7 +2430,7 @@ TEST_F(TransactionTest, TopicDeleteTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TopicDeleteTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TopicDeleteTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2223,6 +2440,9 @@ TEST_F(TransactionTest, TopicDeleteTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); @@ -2233,7 +2453,7 @@ TEST_F(TransactionTest, TopicDeleteTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TopicDeleteTransactionFromTransactionBytes) +TEST_F(TransactionTest, TopicDeleteTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2246,9 +2466,12 @@ TEST_F(TransactionTest, TopicDeleteTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(txBody.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_DELETE_TRANSACTION); @@ -2272,7 +2495,7 @@ TEST_F(TransactionTest, TopicMessageSubmitTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TopicMessageSubmitTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TopicMessageSubmitTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2282,9 +2505,12 @@ TEST_F(TransactionTest, TopicMessageSubmitTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_MESSAGE_SUBMIT_TRANSACTION); @@ -2292,7 +2518,7 @@ TEST_F(TransactionTest, TopicMessageSubmitTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TopicMessageSubmitTransactionFromTransactionBytes) +TEST_F(TransactionTest, TopicMessageSubmitTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2305,9 +2531,12 @@ TEST_F(TransactionTest, TopicMessageSubmitTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(tx.SerializeAsString())); + internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_MESSAGE_SUBMIT_TRANSACTION); @@ -2331,7 +2560,7 @@ TEST_F(TransactionTest, TopicUpdateTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TopicUpdateTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TopicUpdateTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2341,9 +2570,12 @@ TEST_F(TransactionTest, TopicUpdateTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When - const WrappedTransaction wrappedTx = Transaction::fromBytes( - internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + const WrappedTransaction wrappedTx = + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_UPDATE_TRANSACTION); @@ -2351,7 +2583,7 @@ TEST_F(TransactionTest, TopicUpdateTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TopicUpdateTransactionFromTransactionBytes) +TEST_F(TransactionTest, TopicUpdateTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2364,9 +2596,12 @@ TEST_F(TransactionTest, TopicUpdateTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TOPIC_UPDATE_TRANSACTION); @@ -2390,7 +2625,7 @@ TEST_F(TransactionTest, TransferTransactionFromTransactionBodyBytes) } //----- -TEST_F(TransactionTest, TransferTransactionFromSignedTransactionBytes) +TEST_F(TransactionTest, TransferTransactionFromTransactionBytes) { // Given proto::TransactionBody txBody; @@ -2400,9 +2635,12 @@ TEST_F(TransactionTest, TransferTransactionFromSignedTransactionBytes) signedTx.set_bodybytes(txBody.SerializeAsString()); // SignatureMap not required + proto::Transaction tx; + tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(signedTx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TRANSFER_TRANSACTION); @@ -2410,7 +2648,7 @@ TEST_F(TransactionTest, TransferTransactionFromSignedTransactionBytes) } //----- -TEST_F(TransactionTest, TransferTransactionFromTransactionBytes) +TEST_F(TransactionTest, TransferTransactionFromTransactionListBytes) { // Given proto::TransactionBody txBody; @@ -2423,9 +2661,12 @@ TEST_F(TransactionTest, TransferTransactionFromTransactionBytes) proto::Transaction tx; tx.set_signedtransactionbytes(signedTx.SerializeAsString()); + proto::TransactionList txList; + *txList.add_transaction_list() = tx; + // When const WrappedTransaction wrappedTx = - Transaction::fromBytes(internal::Utilities::stringToByteVector(tx.SerializeAsString())); + Transaction::fromBytes(internal::Utilities::stringToByteVector(txList.SerializeAsString())); // Then ASSERT_EQ(wrappedTx.getTransactionType(), TransactionType::TRANSFER_TRANSACTION); diff --git a/sdk/tests/unit/TransferTransactionTest.cc b/sdk/tests/unit/TransferTransactionTest.cc index d638f3beb..411a058d1 100644 --- a/sdk/tests/unit/TransferTransactionTest.cc +++ b/sdk/tests/unit/TransferTransactionTest.cc @@ -33,12 +33,6 @@ using namespace Hedera; class TransferTransactionTest : public ::testing::Test { protected: - void SetUp() override - { - mClient.setOperator(getTestAccountId1(), ECDSAsecp256k1PrivateKey::generatePrivateKey().get()); - } - - [[nodiscard]] inline const Client& getTestClient() const { return mClient; } [[nodiscard]] inline const AccountId& getTestAccountId1() const { return mAccountId1; } [[nodiscard]] inline const AccountId& getTestAccountId2() const { return mAccountId2; } [[nodiscard]] inline const TokenId& getTestTokenId() const { return mTokenId; } @@ -48,7 +42,6 @@ class TransferTransactionTest : public ::testing::Test [[nodiscard]] inline bool getTestApproval() const { return mApproval; } private: - Client mClient; const AccountId mAccountId1 = AccountId(10ULL); const AccountId mAccountId2 = AccountId(20ULL); const TokenId mTokenId = TokenId(30ULL); @@ -150,8 +143,10 @@ TEST_F(TransferTransactionTest, AddHbarTransfer) TEST_F(TransferTransactionTest, AddHbarTransferFrozen) { // Given - TransferTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TransferTransaction transaction = TransferTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.addHbarTransfer(getTestAccountId1(), getTestAmount()), IllegalStateException); @@ -192,8 +187,10 @@ TEST_F(TransferTransactionTest, AddTokenTransfer) TEST_F(TransferTransactionTest, AddTokenTransferFrozen) { // Given - TransferTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TransferTransaction transaction = TransferTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.addTokenTransfer(getTestTokenId(), getTestAccountId1(), getTestAmount().toTinybars()), @@ -237,8 +234,10 @@ TEST_F(TransferTransactionTest, AddNftTransfer) TEST_F(TransferTransactionTest, AddNftTransferFrozen) { // Given - TransferTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TransferTransaction transaction = TransferTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.addNftTransfer(getTestNftId(), getTestAccountId1(), getTestAccountId2()), @@ -283,8 +282,10 @@ TEST_F(TransferTransactionTest, AddTokenTransferWithDecimals) TEST_F(TransferTransactionTest, AddTokenTransferWithDecimalsFrozen) { // Given - TransferTransaction transaction; - ASSERT_NO_THROW(transaction.freezeWith(&getTestClient())); + TransferTransaction transaction = TransferTransaction() + .setNodeAccountIds({ AccountId(1ULL) }) + .setTransactionId(TransactionId::generate(AccountId(1ULL))); + ASSERT_NO_THROW(transaction.freeze()); // When / Then EXPECT_THROW(transaction.addTokenTransferWithDecimals(getTestTokenId(),