Skip to content

Conversation

@Jon-edge
Copy link
Collaborator

@Jon-edge Jon-edge commented Dec 3, 2025

Overview

The wallet search supports:

  • Multi-word search: Space-delimited terms with AND logic
  • Field-specific matching: Different fields use different matching strategies
  • Case-insensitive: All searches are case-insensitive

Field Matching Rules

startsWith Fields (Asset Identification)

These fields only match if the search term appears at the beginning of the field value.

Field Applies To Example
currencyCode All items "eth" matches "ETH", not "WETH"
displayName All items "bit" matches "Bitcoin", not "Stablebit"
assetDisplayName Mainnet only "ether" matches "Ethereum"

Rationale: Prevents partial matches like "eth" matching "Tether"

includes Fields (Discovery/Context)

These fields match if the search term appears anywhere in the field value.

Field Applies To Example
chainDisplayName Mainnet only "ase" matches "Base"
wallet name All items "savings" matches "My Savings Wallet"
contractAddress Tokens only "dac17f" matches "0xdac17f958d2..."

Rationale: Allows broader discovery by network name, wallet name, or contract address


Multi-Word Search (AND Logic)

When multiple words are entered (space-separated), ALL terms must match at least one field.

Examples

Search Matches Explanation
base eth ETH on Base "base" → chainDisplayName, "eth" → currencyCode
eth base ETH on Base Order doesn't matter
btc savings BTC in "Savings" wallet "btc" → currencyCode, "savings" → wallet name
base btc Nothing No wallet has both Base chain AND BTC currency

Mainnet vs Token Behavior

Some fields are only searched for mainnet assets (not tokens):

Field Mainnet Tokens Reason
assetDisplayName Describes the chain's native asset, not tokens
chainDisplayName Would match ALL tokens on that chain
currencyCode Identifies the specific asset
displayName Token's display name
wallet name Find all assets in a wallet
contractAddress N/A Only tokens have contracts

Why This Matters

Without this restriction, searching "eth" would match:

  • ✅ ETH mainnet (via currencyCode)
  • ❌ USDT on Ethereum (via chainDisplayName "Ethereum")
  • ❌ USDC on Ethereum (via chainDisplayName "Ethereum")

This would defeat the purpose of the startsWith matching for asset identification.


Wallet Name Behavior

Wallet name search uses includes and applies to all items (mainnet and tokens).

Important Implication

If a wallet is named "My Ethereum", searching "eth" will match:

  • The ETH mainnet asset (via currencyCode AND wallet name)
  • All tokens on that wallet (via wallet name)

This is intentional - searching by wallet name should find everything in that wallet.

Example

Wallet: "My Ethereum" (contains ETH, USDT, USDC)

Search "eth":
  → ETH mainnet ✅ (currencyCode starts with "eth")
  → USDT ✅ (wallet name "My Ethereum" contains "eth")
  → USDC ✅ (wallet name "My Ethereum" contains "eth")

Search "usdt":
  → USDT ✅ (currencyCode starts with "usdt")
  → ETH ❌
  → USDC ❌

Case Studies

Case 1: Finding ETH on Base Network

Goal: Find Ethereum on Base L2

Search: "base eth"

Evaluation for Base ETH wallet:
  Term "base":
    - currencyCode "ETH".startsWith("base") → false
    - displayName "Ethereum".startsWith("base") → false
    - assetDisplayName "Ethereum".startsWith("base") → false
    - chainDisplayName "Base".includes("base") → TRUE ✅
  
  Term "eth":
    - currencyCode "ETH".startsWith("eth") → TRUE ✅

Result: MATCH (both terms satisfied)

Case 2: "eth" Should NOT Match Tether

Goal: Searching "eth" should find Ethereum, not Tether

Search: "eth"

Evaluation for Tether (USDT) on "Savings" wallet:
  Term "eth":
    - currencyCode "USDT".startsWith("eth") → false
    - displayName "Tether".startsWith("eth") → false
    - wallet name "Savings".includes("eth") → false
    - contractAddress "0xdac17f...".includes("eth") → false

Result: NO MATCH ✅

Evaluation for Ethereum mainnet:
  Term "eth":
    - currencyCode "ETH".startsWith("eth") → TRUE ✅

Result: MATCH ✅

Case 3: "teth" SHOULD Match Tether

Goal: Partial match at start of display name

Search: "teth"

Evaluation for Tether (USDT):
  Term "teth":
    - currencyCode "USDT".startsWith("teth") → false
    - displayName "Tether".startsWith("teth") → TRUE ✅

Result: MATCH ✅

Case 4: "steth" Should NOT Match WSTETH

Goal: Middle-of-word matches should not work for asset fields

Search: "steth"

Evaluation for Wrapped stETH (WSTETH):
  Term "steth":
    - currencyCode "WSTETH".startsWith("steth") → false (starts with "w")
    - displayName "Wrapped stETH".startsWith("steth") → false (starts with "w")

Result: NO MATCH ✅

Case 5: Finding by Contract Address

Goal: Search by partial contract address

Search: "dac17f"

Evaluation for USDT (contract: 0xdac17f958d2ee523a2206206994597c13d831ec7):
  Term "dac17f":
    - contractAddress.includes("dac17f") → TRUE ✅

Result: MATCH ✅

Edge Cases

Empty/Whitespace Search

Search Result
"" (empty) Returns all items
" " (whitespace only) Returns all items

Multiple Spaces Between Terms

Search: "base   eth" (multiple spaces)
→ Treated as: ["base", "eth"]
→ Same result as "base eth"

Special Characters

Contract addresses with 0x prefix work normally:

Search: "0xdac17f"
→ Matches tokens with that contract address prefix

No Matches

When no items match all search terms:

Search: "xyz123notfound"
→ Returns empty array []

Summary Table

Search Term Matches Does NOT Match
eth ETH, Ethereum Tether, WETH
teth Tether ETH
base eth ETH on Base ETH on Ethereum, BTC
bitcoin Bitcoin, BTC Ethereum
wsteth WSTETH, Wrapped stETH stETH
steth stETH WSTETH
savings All assets in "Savings" wallet Assets in other wallets
0xdac17f USDT (by contract) Other tokens

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Note

Adds case-insensitive, multi-word AND search with startsWith/includes rules across wallet items and create-wallet items, including mainnet-only field handling and contract address matching, plus comprehensive tests.

  • Search behavior (wallet list):
    • Multi-word (space-delimited) AND search; each term must match.
    • Field-specific matching: currencyCode/displayName/assetDisplayName use startsWith; chainDisplayName (mainnet only), wallet name, and contractAddress use includes.
    • Mainnet vs token: assetDisplayName and chainDisplayName only applied to mainnet; filters out loading items.
  • Create wallet list filtering:
    • Adds assetDisplayName to create items and applies same multi-term rules.
    • Includes pluginId (mainnet only) and networkLocation (e.g., contractAddress) in includes matching.
  • Tests:
    • New walletSearch.test.ts covering single/multi-word, case-insensitivity, mainnet vs token behavior, contract address, and regressions.
    • Snapshot updated to include assetDisplayName in create list item.

Written by Cursor Bugbot for commit 9798ffe. This will update automatically on new commits. Configure here.


Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 297 to 300
const startsWithMatch =
normalizeForSearch(currencyCode).startsWith(term) ||
normalizeForSearch(displayName).startsWith(term) ||
normalizeForSearch(assetDisplayName).startsWith(term)

Choose a reason for hiding this comment

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

P1 Badge Guard optional asset display names in wallet search

In searchWalletList the search predicate unconditionally normalizes assetDisplayName; many currency infos still omit this new field, so entering any search text for those wallets will throw at runtime (normalizeForSearch expects a string), crashing the wallet list instead of filtering. A null check or fallback is needed before normalizing optional fields.

Useful? React with 👍 / 👎.

Split search queries by spaces so users can search multiple terms
like 'base eth' to find Ethereum on Base network. All terms must
match at least one searchable field (AND logic).

Add chainDisplayName as a searchable field in searchWalletList to
enable searching by network/chain name.
Include assetDisplayName from currencyInfo as a searchable field
for wallet and create-wallet searches. This allows users to search
by the asset's display name (e.g., 'Ethereum') in addition to other
existing searchable fields.
Change search matching for currencyCode, displayName, and
assetDisplayName from includes() to startsWith(). This prevents
partial substring matches that crowd search results.

For example, searching 'eth' now shows Ethereum assets but not
Tether (which contains 'eth' in the middle). Context fields like
chainDisplayName, wallet name, and contractAddress still use
includes() for broader discovery.
Test coverage for:
- Multi-word search with space delimiter (AND logic)
- startsWith matching for currencyCode, displayName, assetDisplayName
- includes matching for chainDisplayName, wallet name, contractAddress
- assetDisplayName and chainDisplayName only searched for mainnet assets
- Regression tests for original issues (#1: 'base eth', #3: 'eth' vs Tether)
normalizeForSearch(assetDisplayName).startsWith(term)
) {
return true
}
Copy link

Choose a reason for hiding this comment

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

Bug: Missing mainnet guard for assetDisplayName in filter function

The assetDisplayName search in filterWalletCreateItemListBySearchText lacks the walletType != null guard that the adjacent pluginId search has. The comment says "for mainnet create items" but the code allows tokens with assetDisplayName to match. While tokens currently don't have assetDisplayName set, this inconsistency between the documented behavior and implementation could cause unexpected matches if token items gain this field later. The searchWalletList function correctly uses token == null for this restriction.

Fix in Cursor Fix in Web

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants