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(wallet): Implemented show all networks assets #17615

Closed
wants to merge 1 commit into from

Conversation

Pavneet-Sing
Copy link

Resolves brave/brave-browser#27074
Resolves brave/brave-browser#27333
Resolves brave/brave-browser#28506
Resolves brave/brave-browser#28748
Resolves brave/brave-browser#28627
Resolves brave/brave-browser#28301
Resolves brave/brave-browser#27614

Submitter Checklist:

  • I confirm that no security/privacy review is needed, or that I have requested one
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run lint, npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

multi-chain.webm

Additional:

  • Not all network overlapping icons are show because they are unavailable: Add shared png icons of networks/chains brave-browser#28561 (comment)
  • Selected asset is preserved for long enough to work with incoming asset and single selection. Ideally will be showing no asset like desktop to avoid complication and extra calls to show the selected asset.

- Implementing multi chain show balance (#27333)
- Refactor network selector screen to show new "All network" (#27074)
- Implemented multi-chain price and asset data collection (#27333)
- Show overlapping network icon on Portfolio and Asset selection screens (#27333)
- Show asset graph data for different networks and assets (#28748)
- Fixed unwanted duplicate removal from list (#28506)
- Fix balance issue for incoming asset
- Reduce latency by separating P3A calls
- Fixed edit visible asset to select assets
- Fixed edit visible assets list for all network to show default assets in "edit visible assets" when all networks is selected (until all network is supported)
- Updated portfolio, edit, view assets list UI list to show asset and network details from "All network" view
- Fix AssetDetails activity to use passed network
- Fixed AccountDetails activity issue with network
- Tested and added available icons for networks/native assets, logged issue for missing assets (#28798)
- Fix account list on asset details on AssetDetails screen
- Fixed cached NFTs after unlock wallet (#28301)
- Fixing asset graph data when multiple assets are shown
- Fix nested network list is instantly closed after selection (click) and improve selection (#27614)
- ERC721 NFTs with different token identifiers may show incorrect balance (#28627)
- Implement All networks list sort order
- Fix Buy, Send, Swap flows for selected multi-chain view token
- Fix crash with test network with new flow
- Ux: Show full network name on click on Edit visible via click popup
- Clear balance with network switching
- Clean up and refactoring to reuse
@Pavneet-Sing Pavneet-Sing added CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-ios Do not run CI builds for iOS CI/skip-windows-x86 CI/skip-windows-x64 Do not run CI builds for Windows x64 unused-CI/skip-linux-x64 Do not run CI builds for Linux x64 labels Mar 15, 2023
@Pavneet-Sing Pavneet-Sing self-assigned this Mar 15, 2023
@SergeyZhukovsky
Copy link
Member

Please don't combine if possible a huge amount of issues in one PR in the future. It would be hard to fix something in case of failure of one of the issues when verifying it, as it could be dependent or the worse case if we need to revert the whole PR(in that case everything has to be reverted). Plus to the above it's harder for reviewers to catch up with all of the issues and trying to understand what is going on.

@simoarpe
Copy link
Collaborator

😱 Reviewing 1200 LOC PR is every developer's worst nightmare.
Try to break the work into smaller PRs when possible. If not, split it into multiple commits with a meaningful name and a description to help the reviewers.
I'm going to check out the branch and compile it locally.

@Pavneet-Sing
Copy link
Author

Pavneet-Sing commented Mar 15, 2023

Please don't combine if possible a huge amount of issues in one PR in the future. It would be hard to fix something in case of failure of one of the issues when verifying it, as it could be dependent or the worse case if we need to revert the whole PR(in that case everything has to be reverted). Plus to the above it's harder for reviewers to catch up with all of the issues and trying to understand what is going on.

scream Reviewing 1200 LOC PR is every developer's worst nightmare. Try to break the work into smaller PRs when possible. If not, split it into multiple commits with a meaningful name and a description to help the reviewers. I'm going to check out the branch and compile it locally.

Multi-chain is a feature and many things in the codebase had to be fixed to support this if you look thoroughly.

public void onDestroyView() {
super.onDestroyView();
if (mPortfolioModel != null) {
mPortfolioModel.clear();
}
}

@simoarpe

  • The issues were found and fixed back and forth and it's easier to use squash to review and fix, but as mentioned above, other than the NFT cache issue, everything is related and saves a lot of time than maintaining a commit history.
  • Probably, I can post and get help from other reviewers who are used to review large PR in brave and you can continue with other work if it gonna take considerable amount of time for you. Alternately, we split the files to review but don't think it is possible unless someone is used to it. LMK

Please feel free to discuss anything as I am using some new APIs with sophisticated flow so LMK if I can help with anything.

@SergeyZhukovsky
Copy link
Member

@Pavneet-Sing so there is no way to split it and it has all be in a single PR and in a single commit right?

@Pavneet-Sing
Copy link
Author

Pavneet-Sing commented Mar 15, 2023

@Pavneet-Sing so there is no way to split it and it has all be in a single PR and in a single commit right?

I can move brave/brave-browser#28748

var nonZeroBalanceAssetList =
mUserAssetsList.stream()
.filter(token -> {
var assetBalance = mPerTokenCryptoSum.get(Utils.tokenToString(token));
return assetBalance != null && assetBalance > 0;
})
.collect(Collectors.toList());

and brave/brave-browser#28627

public void onDestroyView() {
super.onDestroyView();
if (mPortfolioModel != null) {
mPortfolioModel.clear();
}
}

changes in a separate PR. These are not big changes (linked the changes above) but yes, can be separated into a different PR. LMK know if it will help to move these two in a separate PR.

Other than brave/brave-browser#27074 and brave/brave-browser#27333, rest of the changes are small. Selector issue was fixed automatically.

brave/brave-browser#28506 is related to moving code to TokenUtils:

callback.call(removeDuplicates(filteredTokens));

@bbondy
Copy link
Member

bbondy commented Mar 15, 2023

Sorry for the drive by comment, but this comment came off as lacking in courtesy and I had to comment...

Probably, I can post and get help from other reviewers who are used to review large PR in brave

It doesn't matter how great a reviewer is, if you have a very big commit that mixes several concerns, it will not be reviewed properly.

It is not a matter of reviewer experience.

It is up to the person creating pull requests to split up a pull request's concerns into multiple digestible commits. The author should create a story with their commits and have 1 concern per commit.

What's more is that when combining multiple things it makes them inseparable. Maybe 1 concern of many needs special attention and needs an uplift. It could be cherry-picked if it was split up correctly, but cannot if it is buried in a big set of other changes.

Some sources, but it's not hard to find more:

@simoarpe
Copy link
Collaborator

Probably, I can post and get help from other reviewers who are used to review large PR in brave

@Pavneet-Sing , there's no need. I'm always up for a challenge. Please don't take it the wrong way, small PRs should always be preferable, when I noticed the LOC were over a thousand it was natural for me expressing that as a candid observation.

At the end of the day, honest feedback is an invaluable tool that will make us better developers. I hope it didn't make you feel bad or anything, as your comment sounded a bit harsh. I just wanted to help.

I'm going to finish soon an initial review round 😀

* View <=> NetworkSelection state only with All Networks option.
* @param key as identifier to bind local state of NetworkSelection with the view. If null then
* use global/default network selection mode.
^ IMP: Should only be called if the wallet is setup and unlocked
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
^ IMP: Should only be called if the wallet is setup and unlocked
* IMP: Should only be called if the wallet is set up and unlocked.

@@ -212,22 +260,27 @@ public void refreshNetworks() {
init();
}

static void getAllNetworks(JsonRpcService jsonRpcService, List<Integer> supportedCoins,
Copy link
Collaborator

Choose a reason for hiding this comment

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

public? Or package private for a reason?

Copy link
Author

Choose a reason for hiding this comment

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

package accessible only, if there is no modifier then it is default


double thisPrice = Utils.getOrDefault(assetPrices,
mAsset.symbol.toLowerCase(
Locale.getDefault()),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: For the sake of consistency, let's switch to Locale.ENGLISH.

Copy link
Author

@Pavneet-Sing Pavneet-Sing Mar 15, 2023

Choose a reason for hiding this comment

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

These parts are just auto formatted and didn't touched though have used and updated for the other parts. will update

Copy link
Collaborator

Choose a reason for hiding this comment

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

These parts are just auto formatted and didn't touched

I'm well aware, I hope you don't mind if I suggest minor improvements; feel free to skip them if they become too much.
Thank you for making the codebase better, I'm a huge supported of the Boy Scout rule: https://biratkirat.medium.com/step-8-the-boy-scout-rule-robert-c-martin-uncle-bob-9ac839778385

for (AccountInfo accountInfo : accountInfos) {
final String accountAddressLower =
accountInfo.address.toLowerCase(
Locale.getDefault());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here,
for the sake of consistency, let's switch to Locale.ENGLISH.

Copy link
Author

Choose a reason for hiding this comment

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

});
});
final String fiatBalanceString = String.format(
Locale.getDefault(), "$%,.2f",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here,
for the sake of consistency, let's switch to Locale.ENGLISH.

Copy link
Author

Choose a reason for hiding this comment

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

@@ -102,23 +109,96 @@ public Double getMostRecentFiatSum() {
return Double.valueOf(mFiatHistory[mFiatHistory.length - 1].price);
}

public void fetchAllAssetsAndDetails(Callbacks.Callback1<PortfolioHelper> callback) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method is really hard to read. Is there anything that can be done to make it more maintainable and easier to follow?

Copy link
Author

Choose a reason for hiding this comment

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

cc @SergeyZhukovsky for thoughts, if we should split this and what's should be the ideal length of a method as this was mostly picked form the existing implementation.

resetResultData();
if (mActivity.get() == null || mSelectedNetworks.isEmpty()) return;
int totalNetworks = mSelectedNetworks.size();
AtomicInteger resCount = new AtomicInteger();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why the use of an atomic integer? Aren't the callbacks always in the main thread?

Copy link
Author

Choose a reason for hiding this comment

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

because cannot use local variable as it is being used within the callback and don't wanna use a global variable to avoid logical complexity so this is a decent solution.

* @return true if Fragment UI can be updated otherwise false
*/
public static boolean canUpdateFragmentUi(Fragment frag) {
return !(frag.isRemoving() || frag.getActivity() == null || frag.isDetached()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would switch isRemoving in favor of isRemovingParent, it's safer as it checks also for the parent ancestors.

Copy link
Author

Choose a reason for hiding this comment

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

It's only for fragment itself not for the container or parent.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Fine 👍 Better explains that in the Javadoc.

Copy link
Author

Choose a reason for hiding this comment

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

The function name itself explains what it does and I already added javadoc for you specially that should be enough. No need to add info about isRemovingParent as it is not related and needed. Would suggest to add minor or subjective review as nits because there are often many than the crucial ones.

Comment on lines +195 to +204
/**
* Create a network model to handle either default or local state (onscreen e.g. {@link
* org.chromium.chrome.browser.crypto_wallet.fragments.PortfolioFragment}). Local network
* selection can be used by many views so make sure to use the same key which acts as a contract
* between the view and the selection activity.
* @param key acts as a binding key between caller and selection activity.
* @param mode to handle network selection event globally or locally.
* @param lifecycle to auto remove network-selection objects.
* @return NetworkSelectorModel object.
*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

❤️

Comment on lines +95 to +103
StringBuilder builder = new StringBuilder();
for (int i = 0; i < items.length; i++) {
String item = items[i];
if (TextUtils.isEmpty(item)) continue;
builder.append(item).append(separator);
}
// Delete separator after the last value
builder.deleteCharAt(builder.length() - 1);
return builder.toString();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's make this more elegant using Java streams.
if (items == null) return ""; can remain, but the rest can be optimized into a single line:
return Arrays.stream(items).collect(Collectors.joining(Character.toString(separator)));

Copy link
Author

Choose a reason for hiding this comment

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

I wanna delete the separator at last, and your code doesn't check for nulls or empty.
BTW, the focus is not on refactoring things to streams. Probably just use it where it is more suitable but should not be enforced.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand your answer.
I didn't add a filter to the chain as I just wanted to suggest a more elegant way, and give you the idea. Not sure about you mention the focus on refactoring the code using streams.

Copy link
Author

@Pavneet-Sing Pavneet-Sing Mar 16, 2023

Choose a reason for hiding this comment

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

I think I explained clearly but here's more info.
I have started using streams because now we can https://bravesoftware.slack.com/archives/C03MMJ4CHEZ/p1675178531068709 but this does not mean this we should use this everywhere possible to replace the existing working solution. Plus I also wanted to remove the char at last and the above solution is easy and more efficient than streams.

It's also good practice to not recommend partial or incomplete solutions without information. I think it is better to add subjective suggestions as nit and would recommend the same to separate important vs subjective feedbacks.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for the feedback and further elaboration @Pavneet-Sing.
I completely agree with what you said about the use of Java streams.

It's important to remember that we're all human, and suggestions may not always be perfect, but that should not deter us from constructive criticism. It provides invaluable insights!

Code reviews have many purposes, not only merging the code back to the main branch. They are an invaluable opportunity to discuss many things, just to name a few:

  • Provide feedback and suggestions
  • Creating connections with other team members
  • Raising awareness of current coding styles and best practices

All of this becomes extremely hard (or impossible) if feedback is not accepted gracefully or (even worse) when the answers become rude. Demonstrating a courteous and receptive attitude towards feedback is crucial for a productive and harmonious workplace.
Really! I couldn't stress this point enough, we should try to be excellent to each other, and being courteous with those who review your code is the foundation for a fully functional team.

Let's continue with this offline, feedback is an essential part of the development process, it plays a crucial part, but discussing it in PR comments may not be appropriate.
It's better to continue these conversations offline to prevent clogging up the PR comments section. Once again, thanks for your valuable input!

Copy link
Author

@Pavneet-Sing Pavneet-Sing Mar 16, 2023

Choose a reason for hiding this comment

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

I didn't deny the feedback or anything that you've mentioned above with a long paragraph and details, which often not needed. been seeing this patterns many times. The extra details was provided because it was asked.
I just clearly explained that we should not be tempted to use streams and should not enforce this in review, especially with partial solutions and without full understanding. Applying streams here would be an overkill. Would suggest the same to take things more gracefully.

@Pavneet-Sing
Copy link
Author

Pavneet-Sing commented Mar 15, 2023

Sorry for the drive by comment, but this comment came off as lacking in courtesy and I had to comment...

Probably, I can post and get help from other reviewers who are used to review large PR in brave

It doesn't matter how great a reviewer is, if you have a very big commit that mixes several concerns, it will not be reviewed properly.

It is not a matter of reviewer experience.

It is up to the person creating pull requests to split up a pull request's concerns into multiple digestible commits. The author should create a story with their commits and have 1 concern per commit.

What's more is that when combining multiple things it makes them inseparable. Maybe 1 concern of many needs special attention and needs an uplift. It could be cherry-picked if it was split up correctly, but cannot if it is buried in a big set of other changes.

Some sources, but it's not hard to find more:

Probably, I can post and get help from other reviewers who are used to review large PR in brave

@Pavneet-Sing , there's no need. I'm always up for a challenge. Please don't take it the wrong way, small PRs should always be preferable, when I noticed the LOC were over a thousand it was natural for me expressing that as a candid observation.

At the end of the day, honest feedback is an invaluable tool that will make us better developers. I hope it didn't make you feel bad or anything, as your comment sounded a bit harsh. I just wanted to help.

I'm going to finish soon an initial review round 😀

I have been following the practices based on past PRs at brave to move forward quickly as often preferred. As I mentioned above, this was back and forth fixes so hard to maintain a history. Maintaining PR history is good but I personally don't like to add random or partial commits but will do it for big PRs if that's what we prefer now.

I will split this PR into 3-4 parts tomorrow. brave/brave-browser#27074 will be in a QA/No PR as it won't be testable alone.

@Pavneet-Sing Pavneet-Sing marked this pull request as draft March 15, 2023 17:21
@bbondy
Copy link
Member

bbondy commented Mar 15, 2023

I personally don't like to add random or partial commits bit will do it for big PRs if that's what we prefer now.

I don't think I suggested to add random or partial commits.
Please don't do that for large PRs.

I did ask that you be courteous instead of defensive in review feedback, and that you split up concerns logically in a pull request in a way that makes sense to the reviewer and tells a story. Covering one major concern per commit when possible.

@Pavneet-Sing
Copy link
Author

Pavneet-Sing commented Mar 16, 2023

I personally don't like to add random or partial commits bit will do it for big PRs if that's what we prefer now.

I don't think I suggested to add random or partial commits. Please don't do that for large PRs.

I did ask that you be courteous instead of defensive in review feedback, and that you split up concerns logically in a pull request in a way that makes sense to the reviewer and tells a story. Covering one major concern per commit when possible.

As mentioned above, this solutions were implemented in iterations/fragments while implementing the other parts to test and move with the All network implementation. Random/partial commits was regarding this. will never do it.
Note: The commit summary of this draft is just a list of weekly updates on multi chain in prioritize manner.
Will follow this practice going forward to list and organise the issues/solutions with commits.

@Pavneet-Sing Pavneet-Sing deleted the feat-portfolio-multichain-support branch March 30, 2023 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI/skip-ios Do not run CI builds for iOS CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-windows-x64 Do not run CI builds for Windows x64 feature/web3/wallet unused-CI/skip-linux-x64 Do not run CI builds for Linux x64
Projects
None yet
4 participants