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: Sort/Import Tokens in Extension #27184

Open
wants to merge 114 commits into
base: develop
Choose a base branch
from

Conversation

gambinish
Copy link
Contributor

@gambinish gambinish commented Sep 17, 2024

Description

This PR adds Token sorting to the Asset List page, and also moves Token importing to the top of the Token List. A few of the main changes introduced:

  1. Include NativeToken in TokenList component to be included in sorting logic, and treated (as far as sorting is concerned) as any other token in the list
  2. Intoduce a tokenSortConfig into state that keeps track of the sort order, the key being sorted by, and the direction of the sort order. Also includes an action to update this state.
  3. Introduce a useEffect that subscribes to tokenSortConfig as well as a few other application state variables to update and sort tokenList when appropriate.
  4. Clean up asset-list component, and move some of it's relevant code into the useAccountTotalFiatBalance

Acceptance Criteria:

  1. Tokens should be sorted by default by declining balance
  2. Sort controls should sort tokens alphabetically, and by decreasing fiat token balance
  3. Sort order should persist through refresh
  4. Sort order should persist after app is closed and reopened
  5. When a token gets imported, it should be included in the sort list, in the correct order in the list

A couple of disclaimers. There are still (at least) two bugs that I discovered that were not caught by tests:

  1. When toggling preferred currency setting, Native Token sorted incorrectly by decreasing fiat balance ✅ fixed
  2. When switching between accounts, token list does not update ✅ fixed

Open in GitHub Codespaces

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/MMASSETS-356

Manual testing steps

  1. Go to AssetList page, and click dropdown and select option to sort by
  2. Tokens should sort, and remain sorted through refresh and application close/open (it is in state)
  3. Importing tokens should import them into the sort order

Screenshots/Recordings

Screen.Recording.2024-09-16.at.7.57.32.PM.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

gambinish and others added 30 commits September 5, 2024 12:23
…ub.com:MetaMask/metamask-extension into feat/mmassets-356_sort-import-tokens-extension
…ub.com:MetaMask/metamask-extension into feat/mmassets-356_sort-import-tokens-extension
…ub.com:MetaMask/metamask-extension into feat/mmassets-356_sort-import-tokens-extension
@metamaskbot
Copy link
Collaborator

Builds ready [8b8f05d]
Page Load Metrics (1653 ± 77 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint40021041590317152
domContentLoaded13802063163015876
load13882101165316077
domInteractive12165474421
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 192 Bytes (0.00%)
  • ui: 15.2 KiB (0.21%)
  • common: 351 Bytes (0.00%)

Copy link
Contributor

@darkwing darkwing left a comment

Choose a reason for hiding this comment

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

Added some code nits! Overall I really like what you've done!

@@ -136,6 +136,9 @@ describe('Transfer custom tokens @no-mmi', function () {
text: '-1.5 TST',
});

// this delay helps prevent flakiness. it allows driver to wait until send transer is "confirmed"
await driver.delay(5000);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a selector we can poll for here? We really want to get away from these types of generic delays.

borderStyle={BorderStyle.solid}
color={TextColor.textDefault}
>
Sort By
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs localization

padding-left: 16px;
padding-right: 16px;
padding-top: 16px;
padding-bottom: 16px;
Copy link
Contributor

Choose a reason for hiding this comment

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

We can just do padding: 16px;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call. I should probably use the design system props here actually

isSelected={tokenSortConfig.key === 'symbol'}
onClick={() => handleSort('symbol', 'alphaNumeric', 'asc')}
>
Alphabetically (A-Z)
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs localization

isSelected={tokenSortConfig.key === 'tokenFiatAmount'}
onClick={() => handleSort('tokenFiatAmount', 'stringNumeric', 'dsc')}
>
Declining balance ($ high-low)
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs localization

@gambinish gambinish mentioned this pull request Sep 18, 2024
7 tasks
@gambinish
Copy link
Contributor Author

gambinish commented Sep 18, 2024

Closed my previous PR, but want to surface this comment as it is still relevant regarding selectable-list-item component: #27084 (comment)

@@ -114,7 +114,7 @@ const HeaderInfo = () => {
alignSelf: 'flex-end',
}}
>
<Tooltip position="bottom" title={t('accountDetails')} interactive>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was also breaking an e2e test. I'm wondering if someone on @MetaMask/confirmations can help me understand this

const controlBarRef = useRef<HTMLDivElement>(null); // Create a ref
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this TODO to be removed?

) => {
dispatch(
setTokenSortConfig({
key,
Copy link
Contributor

@sahar-fehri sahar-fehri Sep 19, 2024

Choose a reason for hiding this comment

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

Looks like we are setting tokenSortConfig only in this component and i did not see a default value in preferences-controller for tokenSortConfig,

this could result in this selector erroring

  const tokenSortConfig = useSelector((state: any) => {
    return state.metamask.preferences.tokenSortConfig;
  });

Similary to what you added in fixture-builder; im thinking we can add in preferences controller default values for tokenSortConfig?

          tokenSortConfig: {
            key: 'tokenFiatAmount',
            order: 'dsc',
            sortCriteria: 'stringNumeric',
          },

I think we will also need to create a new migration for users who upgrade to add tokenSortConfig preference into their state 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great points, ty for pointing this out

// TODO: Replace `any` with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tokenSortConfig = useSelector((state: any) => {
return state.metamask.preferences.tokenSortConfig;
Copy link
Contributor

Choose a reason for hiding this comment

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

We can maybe create a selector for this?
const tokenSortConfig = useSelector(getTokenSortConfig);

and then in selectors.js

export function getTokenSortConfig(state) {
  const { tokenSortConfig } = getPreferences(state);
  return tokenSortConfig;
}

if (err) {
dispatch(displayWarning(err));
reject(err);
return;
}
console.log('updatedPreferences', updatedPreferences);
Copy link
Contributor

Choose a reason for hiding this comment

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

console to remove

@sahar-fehri
Copy link
Contributor

sahar-fehri commented Sep 19, 2024

Looks great! 🎉

I noticed this behavior where when you click on the sort selector; then you click outside without choosing a select option; the dropdown does not close; is that intentional?

Screen.Recording.2024-09-19.at.11.21.35.mov

const showFiat = useSelector(getMultichainShouldShowFiat);
const primaryTokenImage = useSelector(getMultichainCurrencyImage);
const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences);
const { chainId, ticker, type, rpcUrl } = useSelector(
Copy link
Contributor

Choose a reason for hiding this comment

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

Just mentioning thatuseNativeCurrencyAsPrimaryCurrency will be removed in the aggregated balance feature;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, this is definitely something that we are going to have conflicts with, hoping it should just be an easy swap. Will keep this comment open to keep eyes on this

@sahar-fehri
Copy link
Contributor

The sort selector looks good in MM small view; but in extended view, maybe its just me, but it feels like there is too much blank space?

Screenshot 2024-09-19 at 11 55 54

@gambinish
Copy link
Contributor Author

The sort selector looks good in MM small view; but in extended view, maybe its just me, but it feels like there is too much blank space?

Screenshot 2024-09-19 at 11 55 54

The sort selector looks good in MM small view; but in extended view, maybe its just me, but it feels like there is too much blank space?

Screenshot 2024-09-19 at 11 55 54

I also noticed this. I will circle back with design for feedback

Copy link

sonarcloud bot commented Sep 21, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants