Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: POC refactor for TokenRejectFlow #868

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
gsstoykov marked this conversation as resolved.
Show resolved Hide resolved

// 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
Loading