Skip to content

Commit

Permalink
feat: POC refactor for TokenRejectFlow (#868)
Browse files Browse the repository at this point in the history
Signed-off-by: gsstoykov <[email protected]>
  • Loading branch information
gsstoykov authored Jan 14, 2025
1 parent 13936a1 commit 52e6ae7
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 249 deletions.
158 changes: 17 additions & 141 deletions src/sdk/main/include/TokenRejectFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

#include "AccountId.h"
#include "NftId.h"
#include "TokenDissociateTransaction.h"
#include "TokenId.h"
#include "TokenRejectTransaction.h"
#include "TransactionResponse.h"

namespace Hiero
Expand All @@ -21,6 +23,16 @@ namespace Hiero
class TokenRejectFlow
{
public:
/**
* The transaction used to reject tokens.
*/
TokenRejectTransaction tokenRejectTransaction;

/**
* The transaction used to dissociate tokens.
*/
TokenDissociateTransaction tokenDissociateTransaction;

/**
* Execute the Transactions in this flow (TokenRejectTransaction and TokenDissociateTransaction).
*
Expand All @@ -45,153 +57,17 @@ class TokenRejectFlow
TransactionResponse execute(const Client& client, const std::chrono::system_clock::duration& timeout);

/**
* Freeze the TokenRejectTransaction 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.
*
* NOTE: Since Client's can't be copied, this TokenRejectFlow will store a pointer to the input Client. It is the
* responsibility of the user to make sure that the Client does not go out of scope or get destroyed until this
* TokenRejectFlow is done executing, otherwise this will crash upon execution.
*
* @param client The Client with which to freeze the TokenRejectTransaction.
* @return A reference to this TokenRejectFlow object with the newly-set freeze Client.
* @throws UninitializedException If Client operator has not been initialized.
*/
TokenRejectFlow& freezeWith(const Client* client);

/**
* Set the PrivateKey with which the TokenRejectTransaction will be signed.
*
* @param key The PrivateKey with which to sign the TokenRejectTransaction.
* @return A reference to this TokenRejectFlow object with the newly-set signing PrivateKey.
*/
TokenRejectFlow& sign(const std::shared_ptr<PrivateKey>& key);

/**
* Set the PublicKey and signer function with which the TokenRejectTransaction will be signed.
*
* @param key The PublicKey with which to sign the TokenRejectTransaction.
* @param signer The callback function to use to sign the TokenRejectTransaction.
* @return A reference to this TokenRejectFlow object with the newly-set public key and signer function.
*/
TokenRejectFlow& signWith(const std::shared_ptr<PublicKey>& key,
const std::function<std::vector<std::byte>(const std::vector<std::byte>&)>& signer);

/**
* Set the Client operator with which the TokenRejectTransaction will be signed.
* Set the PrivateKey to be used for signing the transactions.
*
* @param client The Client operator to sign the TokenRejectTransaction.
* @return A reference to this TokenRejectFlow object with the newly-set signing operator.
* @throws UninitializedException If the Client operator has not yet been set.
* @param privateKey A shared pointer to the `PrivateKey` object.
*/
TokenRejectFlow& signWithOperator(const Client& client);

/**
* Get the list of account IDs for nodes with which execution will be attempted.
*
* @return The list of account IDs of nodes this TokenRejectFlow would attempt request submission.
*/
[[nodiscard]] inline std::vector<AccountId> getNodeAccountIds() const { return mNodeAccountIds; }

/**
* Get the account holding tokens to be rejected.
*
* @return Optional containing the account Id of the owner.
*/
[[nodiscard]] std::optional<AccountId> getOwner() const { return mOwner; };

/**
* Get the list of fungible tokens to be rejected.
*
* @return A vector of TokenId objects.
*/
[[nodiscard]] const std::vector<TokenId>& getFts() const { return mFts; };

/**
* Get the list of non-fungible tokens to be rejected.
*
* @return A vector of NftId objects.
*/
[[nodiscard]] const std::vector<NftId>& getNfts() const { return mNfts; };

/**
* Set the desired account IDs of nodes to which this transaction will be submitted.
*
* @param nodeAccountIds The desired list of account IDs of nodes to submit this request.
* @return A reference to this TokenRejectFlow object with the newly-set node account IDs.
*/
TokenRejectFlow& setNodeAccountIds(const std::vector<AccountId>& nodeAccountIds);

/**
* Set a new account holding tokens to be rejected.
*
* @param owner Account Id of the account.
* @return A reference to this TokenRejectFlow with the newly-set owner.
*/
TokenRejectFlow& setOwner(const AccountId& owner);

/**
* Set a new fungible tokens list of tokens to be rejected.
*
* @param fts List of token ids.
* @return A reference to this TokenRejectFlow with the newly-set tokens list.
*/
TokenRejectFlow& setFts(const std::vector<TokenId>& fts);

/**
* Set a new non-fungible tokens list of tokens to be rejected.
*
* @param nfts List of nft ids.
* @return A reference to this TokenRejectFlow with the newly-set nfts list.
*/
TokenRejectFlow& setNfts(const std::vector<NftId>& nfts);
void setReceiverPrivateKey(const std::shared_ptr<PrivateKey>& privateKey) { mReceiverPrivateKey = privateKey; }

private:
/**
* The Client with which to freeze the TokenRejectTransaction.
*/
const Client* mFreezeWithClient = nullptr;

/**
* The PrivateKey with which to sign the TokenRejectTransaction.
*/
std::shared_ptr<PrivateKey> mPrivateKey = nullptr;

/**
* The PublicKey associated with the signer function to sign the TokenRejectTransaction.
*/
std::shared_ptr<PublicKey> mPublicKey = nullptr;

/**
* The signer function to use to sign the TokenRejectTransaction.
*/
std::optional<std::function<std::vector<std::byte>(const std::vector<std::byte>&)>> mSigner;

/**
* The list of account IDs of the nodes with which execution should be attempted.
*/
std::vector<AccountId> mNodeAccountIds;

/**
* An account holding the tokens to be rejected.
* If set, this account MUST sign this transaction.
* If not set, the payer for this transaction SHALL be the account rejecting tokens.
*/
std::optional<AccountId> mOwner;

/**
* On success each rejected token serial number or balance SHALL be transferred from
* the requesting account to the treasury account for that token type.
* After rejection the requesting account SHALL continue to be associated with the token.
* if dissociation is desired then a separate TokenDissociate transaction MUST be submitted to remove the association.
*
* A list of one or more fungible token rejections.
*/
std::vector<TokenId> mFts;

/**
* A list of one or more non-fungible token rejections.
* The PrivateKey with which to sign the transactions.
*/
std::vector<NftId> mNfts;
std::shared_ptr<PrivateKey> mReceiverPrivateKey = nullptr;
};

} // namespace Hiero
Expand Down
1 change: 1 addition & 0 deletions src/sdk/main/include/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class Transaction
* @param key The PrivateKey with which to sign this Transaction.
* @return A reference to this derived Transaction object with the signature.
* @throws IllegalStateException If this Transaction object is not frozen.
* @throws std::invalid_argument If the signing key is not set.
*/
SdkRequestType& sign(const std::shared_ptr<PrivateKey>& key);

Expand Down
118 changes: 10 additions & 108 deletions src/sdk/main/src/TokenRejectFlow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,125 +20,27 @@ TransactionResponse TokenRejectFlow::execute(const Client& client)
//-----
TransactionResponse TokenRejectFlow::execute(const Client& client, const std::chrono::system_clock::duration& timeout)
{
TokenRejectTransaction tokenRejectTransaction;

if (mOwner.has_value())
{
tokenRejectTransaction.setOwner(mOwner.value());
}

tokenRejectTransaction.setFts(mFts).setNfts(mNfts);

if (!mNodeAccountIds.empty())
{
tokenRejectTransaction.setNodeAccountIds(mNodeAccountIds);
}

if (mFreezeWithClient != nullptr)
{
tokenRejectTransaction.freezeWith(mFreezeWithClient);
}

if (mPrivateKey)
{
tokenRejectTransaction.sign(mPrivateKey);
}
else if (mPublicKey && mSigner.has_value())
{
tokenRejectTransaction.signWith(mPublicKey, mSigner.value());
}

// Submit the TokenRejectTransaction.
TransactionResponse txResponse = tokenRejectTransaction.execute(client, timeout);
TransactionResponse txResponse =
tokenRejectTransaction.freezeWith(&client).sign(mReceiverPrivateKey).execute(client, timeout);

// Make sure the transaction reaches consensus.
TransactionReceipt txReceipt = txResponse.getReceipt(client, timeout);

TokenDissociateTransaction tokenDissociateTransaction;

if (mOwner.has_value())
{
tokenDissociateTransaction.setAccountId(mOwner.value());
}

// build dissociate vector from rejected nfts
std::vector<TokenId> toDissociate;
std::for_each(
mNfts.cbegin(), mNfts.cend(), [&toDissociate](const NftId& nftId) { toDissociate.push_back(nftId.mTokenId); });
std::for_each(tokenRejectTransaction.getNfts().cbegin(),
tokenRejectTransaction.getNfts().cend(),
[&toDissociate](const NftId& nftId) { toDissociate.push_back(nftId.mTokenId); });

// Make sure the transaction reaches consensus.
txReceipt = tokenDissociateTransaction.setTokenIds(toDissociate).execute(client, timeout).getReceipt(client, timeout);
txReceipt = tokenDissociateTransaction.setTokenIds(toDissociate)
.freezeWith(&client)
.sign(mReceiverPrivateKey)
.execute(client, timeout)
.getReceipt(client, timeout);

return txResponse;
}

//-----
TokenRejectFlow& TokenRejectFlow::freezeWith(const Client* client)
{
mFreezeWithClient = client;
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::sign(const std::shared_ptr<PrivateKey>& key)
{
mPrivateKey = key;
mPublicKey = nullptr;
mSigner.reset();
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::signWith(
const std::shared_ptr<PublicKey>& key,
const std::function<std::vector<std::byte>(const std::vector<std::byte>&)>& signer)
{
mPrivateKey = nullptr;
mPublicKey = key;
mSigner = signer;
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::signWithOperator(const Client& client)
{
if (!client.getOperatorPublicKey())
{
throw UninitializedException("Client operator has not yet been set");
}

mPrivateKey = nullptr;
mPublicKey = client.getOperatorPublicKey();
mSigner = client.getOperatorSigner();
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::setNodeAccountIds(const std::vector<AccountId>& nodeAccountIds)
{
mNodeAccountIds = nodeAccountIds;
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::setOwner(const AccountId& owner)
{
mOwner = owner;
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::setFts(const std::vector<TokenId>& fts)
{
mFts = fts;
return *this;
}

//-----
TokenRejectFlow& TokenRejectFlow::setNfts(const std::vector<NftId>& nfts)
{
mNfts = nfts;
return *this;
}

} // namespace Hiero
5 changes: 5 additions & 0 deletions src/sdk/main/src/Transaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ template<typename SdkRequestType>
SdkRequestType& Transaction<SdkRequestType>::sign(const std::shared_ptr<PrivateKey>& key)
{
// clang-format off
if (key == nullptr)
{
throw std::invalid_argument("Signing key must be set.");
}

return signInternal(key->getPublicKey(), [key](const std::vector<std::byte>& vec) { return key->sign(vec); }, key);
// clang-format on
}
Expand Down
Loading

0 comments on commit 52e6ae7

Please sign in to comment.