Skip to content

feat: token transfer operator == adition#1320

Open
Egbaiyelo wants to merge 5 commits intohiero-ledger:mainfrom
Egbaiyelo:feat/tokentransfer==
Open

feat: token transfer operator == adition#1320
Egbaiyelo wants to merge 5 commits intohiero-ledger:mainfrom
Egbaiyelo:feat/tokentransfer==

Conversation

@Egbaiyelo
Copy link
Copy Markdown
Contributor

@Egbaiyelo Egbaiyelo commented Apr 4, 2026

Description:

Implementing the TokenTransfer== operator

Related issue(s):

Fixes #1298

Notes for reviewer:

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.)

Signed-off-by: Egbaiyelo <moteniolaegbaiyelo@trentu.ca>
@Egbaiyelo Egbaiyelo requested review from a team as code owners April 4, 2026 17:01
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 4, 2026

Hey @Egbaiyelo 👋 thanks for the PR!
I'm your friendly PR Helper Bot 🤖 and I'll be riding shotgun on this one, keeping track of your PR's status to help you get it approved and merged.

This comment updates automatically as you push changes -- think of it as your PR's live scoreboard!
Here's the latest:


PR Checks

DCO Sign-off -- All commits have valid sign-offs. Nice work!


GPG Signature -- All commits have verified GPG signatures. Locked and loaded!


Merge Conflicts -- No merge conflicts detected. Smooth sailing!


Issue Link -- Linked to #1298 (assigned to you).


🎉 All checks passed! Your PR is ready for review. Great job!

@github-actions github-actions bot added the status: needs revision A pull request that requires changes before merge label Apr 4, 2026
@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Apr 4, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 5 complexity

Metric Results
Complexity 5

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

Signed-off-by: Egbaiyelo <moteniolaegbaiyelo@trentu.ca>
Copy link
Copy Markdown
Contributor

@rwalworth rwalworth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @Egbaiyelo! There are a few things to address before this can be merged:

Issue link fix: The PR description has Fixes # 1298 (space after #) - GitHub won't auto-link that, which is why the bot flagged it. Please update it to Fixes #1298 (no space).

I left a few comments below on the code changes. Let me know if you have any questions!

Comment on lines +100 to +106
/**
* Compare this TokenTransfer instance to another TokenTransfer instance and determine if they represent the same pending TokenTransfer.
*
* @param other The other TokenTransfer with which to compare this TokenTransfer.
* @return \c TRUE if this TokenTransfer is the same as the input TokenTransfer, otherwise \c FALSE.
*/
friend bool operator==(const TokenTransfer&, const TokenTransfer&);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): The operator== is declared twice - once inside the class as friend (without [[nodiscard]]) and once as a free function outside the class (with [[nodiscard]]). Neither form is quite right.

Since all members of TokenTransfer are public, friend isn't needed. The rest of the codebase uses a member function for operator== (see PendingAirdropId, NftId). Please use that pattern instead:

// In the header, inside the class:
[[nodiscard]] bool operator==(const TokenTransfer& other) const;

Remove the friend declaration inside the class and the entire block outside the class (the // Adding nodiscard... comment, the duplicate Doxygen block, and the [[nodiscard]] bool operator== line).

In TokenTransfer.cc, update the definition accordingly:

bool TokenTransfer::operator==(const TokenTransfer& other) const
{
  return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
         (mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
         (mExpectedDecimals == other.mExpectedDecimals);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad though it did say friend in the issue, it said add [[nodiscard]] friend and i saw it was never like that in the codebase and I couldn't even do it like that cause of lint #1298

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense - the issue description was a bit ambiguous there. Removing friend was the right call.

Two things still needed on the declaration:

  1. const qualifier — since this comparison doesn't modify *this, the method should be const:
    [[nodiscard]] bool operator==(const TokenTransfer& other) const;
  2. Parameter name - minor, but the codebase convention names the parameter in the declaration too (see PendingAirdropId.h).

Also, the implementation in TokenTransfer.cc still needs to be updated - I left a comment there with the details.

@github-actions github-actions bot added status: needs review The pull request is ready for maintainer review and removed status: needs revision A pull request that requires changes before merge labels Apr 5, 2026
@Egbaiyelo
Copy link
Copy Markdown
Contributor Author

I genuinely cant run the tests for some reason? something about hproto-populate?

Signed-off-by: Egbaiyelo <moteniolaegbaiyelo@trentu.ca>
@Egbaiyelo Egbaiyelo force-pushed the feat/tokentransfer== branch from 1d2345c to b79455b Compare April 5, 2026 01:19
Signed-off-by: Egbaiyelo <moteniolaegbaiyelo@trentu.ca>
@Egbaiyelo
Copy link
Copy Markdown
Contributor Author

@rwalworth So I am a bit confused with the test cases, i came back realising I might not have done the right thing, I think they cover everything now but I dont see the structure of what I did in the codebase

Copy link
Copy Markdown
Contributor

@rwalworth rwalworth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates @Egbaiyelo — good progress on the SPDX header fix and adding the //----- separator! There are still a couple of things to address before this can merge, the most critical being that the operator== implementation in TokenTransfer.cc is a free function rather than a member function, which means it won't compile. I've left the details in the comments below.

Comment on lines +81 to +86
//-----
bool operator==(const TokenTransfer& other) {
return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
(mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
(mExpectedDecimals == other.mExpectedDecimals);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking): The implementation is a free function, not a member function of TokenTransfer.

As written, bool operator==(const TokenTransfer& other) is a free function trying to access mTokenId, mAccountId, etc. directly - those are members of TokenTransfer, not variables in scope, so this won't compile.

Please use the member function form with the TokenTransfer:: scope qualifier and const at the end, matching the style of other functions in this file:

bool TokenTransfer::operator==(const TokenTransfer& other) const
{
  return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
         (mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
         (mExpectedDecimals == other.mExpectedDecimals);
}

Also note: the opening brace goes on its own line to match the file's style.

Copy link
Copy Markdown
Contributor Author

@Egbaiyelo Egbaiyelo Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noted, just realizing the free function thing.
Why is it a free function though? it's in the body of TokenTransfer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a .cc file, bool operator==(const TokenTransfer& other) without the TokenTransfer:: prefix IS a free function - even though it's typed inside the same file as the class definition, the .cc file has no class body, so there's no implicit class scope. The ClassName:: qualifier is what ties it to the class.

Looking at the latest commit, the definition now reads bool TokenTransfer::operator==(const TokenTransfer& other) const - that's the correct member function form. You got it!

Comment on lines +83 to +84
return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
(mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo (blocking): There is still trailing whitespace at the end of these two lines (a space before the line break after &&).

You can catch these with clang-format-17 -i src/sdk/main/src/TokenTransfer.cc, or most editors can highlight and trim trailing whitespace automatically.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ill add git hooks to my local repo to solve this white space thing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea! A pre-commit hook running clang-format-17 -i on staged files would catch this automatically. The latest commit looks clean - no trailing whitespace.

@rwalworth
Copy link
Copy Markdown
Contributor

@rwalworth So I am a bit confused with the test cases, i came back realising I might not have done the right thing, I think they cover everything now but I dont see the structure of what I did in the codebase

The tests look good - they cover all three cases required by the issue:

  1. Two default-constructed instances are equal ✓
  2. Two identically-constructed instances are equal ✓
  3. Instances differing in each field are not equal ✓

The structure (going straight from // Given to // Then without an explicit // When) is a bit different from some of the other tests in the file, but it's perfectly fine for equality assertions - the test name makes the intent clear.

One minor thing: in OperatorEqualsDiff, testTokenTransfer is constructed with the hardcoded value true for mIsApproval. Since getTestIsApproval() also returns true, they're equivalent - using getTestIsApproval() would be slightly more consistent with the rest of the test, but it's not a blocker.

The reason you can't run the tests right now is the compilation error in TokenTransfer.cc - the operator== is a free function that can't access the member variables. Once that's fixed (see the thread on that file), things should build and the tests should pass!

@rwalworth
Copy link
Copy Markdown
Contributor

I genuinely cant run the tests for some reason? something about hproto-populate?

Can you share the full error message? An error mentioning "hproto-populate" sounds like a build system or dependency issue unrelated to your changes - possibly a missing proto generation step or a stale build cache.

@rwalworth rwalworth added status: needs revision A pull request that requires changes before merge and removed status: needs review The pull request is ready for maintainer review labels Apr 5, 2026
TokenTransfer diffTestAccountId(getTestTokenId(), AccountId(12345ULL), getTestAmount(), getTestExpectedDecimals(), getTestIsApproval());
TokenTransfer diffTestAmount(getTestTokenId(), getTestAccountId(), 500LL, getTestExpectedDecimals(), getTestIsApproval());
TokenTransfer diffTestExpectedDecimals(getTestTokenId(), getTestAccountId(), getTestAmount(), 2U, getTestIsApproval());
TokenTransfer diffTestIsApproval(getTestTokenId(), getTestAccountId(), getTestAmount(), getTestExpectedDecimals(), false);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just hoping this is the appropriate way to space this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): The column-aligned variable declarations here (extra spaces padding variable names to align) and the space inside ( TokenId(...) won't survive clang-format-17. The .clang-format config has AlignConsecutiveDeclarations: None and SpacesInParentheses: false.

The lint check only runs on src/sdk/main/, so this won't fail CI - but it's worth running clang-format on the test file too to keep things consistent:

clang-format-17 -i src/sdk/tests/unit/TokenTransferUnitTests.cc

Not a blocker - but something to consider.

@Egbaiyelo
Copy link
Copy Markdown
Contributor Author

ill rebuild it actually

Signed-off-by: Egbaiyelo <moteniolaegbaiyelo@trentu.ca>
@github-actions github-actions bot added status: needs review The pull request is ready for maintainer review and removed status: needs revision A pull request that requires changes before merge labels Apr 5, 2026
Copy link
Copy Markdown
Contributor

@rwalworth rwalworth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sticking with this @Egbaiyelo - the implementation and test coverage are looking good now! The operator== logic is correct, the //----- separator is there, the member function form is right, and the SPDX header is clean. Just one small doc comment fix needed in the header before this can merge.

Comment on lines +100 to +107
/**
* Compare this TokenTransfer instance to another TokenTransfer instance and determine if they represent the same pending TokenTransfer.
*
* @param other The other TokenTransfer with which to compare this TokenTransfer.
* @return \c TRUE if this TokenTransfer is the same as the input TokenTransfer, otherwise \c FALSE.
*/
[[nodiscard]] bool operator==(const TokenTransfer& other) const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo (blocking): The doc comment says "determine if they represent the same pending TokenTransfer" - the word "pending" was carried over from PendingAirdropId's comment but doesn't apply here. TokenTransfer is not a "pending" transfer.

Please change it to:

/**
 * Compare this TokenTransfer to another TokenTransfer and determine if they represent the same TokenTransfer.
 *
 * @param other The other TokenTransfer with which to compare this TokenTransfer.
 * @return \c TRUE if this TokenTransfer is the same as the input TokenTransfer, otherwise \c FALSE.
 */

Also note: the comment line currently exceeds the 120-character column limit, so clang-format will reflow it - the shorter version above fits cleanly.

TokenTransfer diffTestAccountId(getTestTokenId(), AccountId(12345ULL), getTestAmount(), getTestExpectedDecimals(), getTestIsApproval());
TokenTransfer diffTestAmount(getTestTokenId(), getTestAccountId(), 500LL, getTestExpectedDecimals(), getTestIsApproval());
TokenTransfer diffTestExpectedDecimals(getTestTokenId(), getTestAccountId(), getTestAmount(), 2U, getTestIsApproval());
TokenTransfer diffTestIsApproval(getTestTokenId(), getTestAccountId(), getTestAmount(), getTestExpectedDecimals(), false);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): The column-aligned variable declarations here (extra spaces padding variable names to align) and the space inside ( TokenId(...) won't survive clang-format-17. The .clang-format config has AlignConsecutiveDeclarations: None and SpacesInParentheses: false.

The lint check only runs on src/sdk/main/, so this won't fail CI - but it's worth running clang-format on the test file too to keep things consistent:

clang-format-17 -i src/sdk/tests/unit/TokenTransferUnitTests.cc

Not a blocker - but something to consider.

Comment on lines +81 to +86
//-----
bool operator==(const TokenTransfer& other) {
return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
(mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
(mExpectedDecimals == other.mExpectedDecimals);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a .cc file, bool operator==(const TokenTransfer& other) without the TokenTransfer:: prefix IS a free function - even though it's typed inside the same file as the class definition, the .cc file has no class body, so there's no implicit class scope. The ClassName:: qualifier is what ties it to the class.

Looking at the latest commit, the definition now reads bool TokenTransfer::operator==(const TokenTransfer& other) const - that's the correct member function form. You got it!

Comment on lines +83 to +84
return (mTokenId == other.mTokenId) && (mAccountId == other.mAccountId) &&
(mAmount == other.mAmount) && (mIsApproval == other.mIsApproval) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great idea! A pre-commit hook running clang-format-17 -i on staged files would catch this automatically. The latest commit looks clean - no trailing whitespace.

@rwalworth rwalworth removed the status: needs review The pull request is ready for maintainer review label Apr 5, 2026
@rwalworth rwalworth added the status: needs revision A pull request that requires changes before merge label Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: needs revision A pull request that requires changes before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Beginner]: Add operator== to TokenTransfer

2 participants