Skip to content

Sort token selector by positive balance first #466

@gabitoesmiapodo

Description

@gabitoesmiapodo

User story / Problem statement

Currently, TokenSelect lists tokens in the token-list's source order. Users who already hold tokens have to scroll or search to find them, even though those are overwhelmingly the ones they want to pick. Burying held tokens under a long alphabetical list hurts discoverability.

The sort-by-USD-value logic already exists in src/hooks/useTokens.ts (sortFn at L240-L247) but is gated on the showBalance prop, which defaults to false. That prop conflates two concerns: (a) fetch balances + sort, and (b) render a balance column per row.

On chains not covered by LI.FI (e.g. Sepolia), the sort never runs even with showBalance={true}, because the LI.FI price/balance queries return nothing.

Expected outcome

When a user connects a wallet and opens the token selector, tokens with a positive balance appear at the top of the list, ordered by USD value descending. Tokens with zero balance follow, in the current source order. This happens on any chain LI.FI supports, regardless of whether the consumer opted into showing the balance column.

Disconnected users see the current source-order list with no balance-fetching side effects.

Acceptance criteria

  • Connecting a wallet and opening the token selector shows tokens with positive balances at the top, highest USD value first, on any chain LI.FI supports -- without the consumer needing to set showBalance={true}.
  • Disconnected wallet state: list renders in source order (no regression, no failed balance requests).
  • showBalance continues to control only whether the balance column is rendered in each row.
  • New sortByBalance prop is documented in JSDoc on TokenSelect, TokenInput, TokenDropdown.
  • Existing call sites (TokenInput demo at src/components/pageComponents/home/Examples/demos/TokenInput/index.tsx) keep working unchanged.
  • Unit test in useTokens.test.ts (or equivalent) asserts positive-balance tokens come before zero-balance tokens after updateTokensBalances.
  • (Stretch) Sort-by-balance works on a LI.FI-unsupported chain by falling back to on-chain multicall.

Alternatives considered

For chains LI.FI does not cover, two approaches were weighed:

  1. Batched on-chain multicall (ERC-20 balanceOf + native getBalance) for the active chain, reusing patterns from src/hooks/useErc20Balance.ts (L38-L61) and wagmi's useBalance. Higher implementation cost, consistent UX.
  2. Unsorted fallback on unsupported chains, documented as a known limitation. Zero implementation cost, inconsistent UX.

Option 1 is preferred but listed as a stretch goal above; the implementation PR picks one.

Technical notes

Proposed change.

  1. Split the two concerns. Introduce a new prop sortByBalance?: boolean on TokenSelect (and pass-through on TokenInput, TokenDropdown). Default: true when a wallet is connected.
  2. In useTokens (src/hooks/useTokens.ts), accept a separate sortByBalance param (or always fetch balance + price when an account is present) so updateTokensBalances runs even when the caller does not want to render the balance column.
  3. Zero-balance tokens retain their current ordering, grouped after positive-balance tokens. Do not drop them.

Current state -- where the sort lives.

  • Sort function: src/hooks/useTokens.ts:240-247
  • Applied at: src/hooks/useTokens.ts:214 inside updateTokensBalances
  • Gating conditions: src/hooks/useTokens.ts:129-139 (requires withBalance && account + loaded LI.FI data)
  • Consumer wiring: src/components/sharedComponents/TokenSelect/index.tsx:125-128 passes withBalance: showBalance; showBalance defaults to false (line 60)
  • Only in-repo opt-in: src/components/pageComponents/home/Examples/demos/TokenInput/index.tsx:132 uses showBalance={isWalletConnected}

Non-goals.

  • Changing the hardcoded TopTokens order (src/components/sharedComponents/TokenSelect/TopTokens/index.tsx:19-38).
  • Introducing a user-facing sort toggle.
  • Filtering out zero-balance tokens.

References.

  • useTokens hook: src/hooks/useTokens.ts
  • Existing sort function: src/hooks/useTokens.ts:240-247
  • Consumer component: src/components/sharedComponents/TokenSelect/index.tsx
  • Fallback balance hooks: src/hooks/useErc20Balance.ts, src/components/sharedComponents/TokenSelect/List/TokenBalance.tsx

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions