Skip to content

Commit 4a90f3c

Browse files
authored
Merge pull request #122 from primev/redeploy-updates
Redeploy: UI upgrades
2 parents e99fc22 + f930d4b commit 4a90f3c

3 files changed

Lines changed: 48 additions & 12 deletions

File tree

src/components/swap/TokenSelectorModal.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ export const DEFAULT_ETH_TOKEN: Token = {
136136

137137
const SEARCH_DEBOUNCE_MS = 150
138138
const BARTER_SEARCH_CAP = 50
139+
/** Hide held tokens worth less than this (USD) from the default "Your tokens"
140+
* list so the section isn't crowded with dust. Unpriced tokens are also hidden
141+
* — if we can't confirm value ≥ threshold, treat it as dust. */
142+
const DUST_USD_THRESHOLD = 0.1
139143

140144
const TokenSelectorModalComponent = ({
141145
open,
@@ -210,13 +214,23 @@ const TokenSelectorModalComponent = ({
210214
}
211215
}, [open])
212216

217+
// Held tokens minus dust: applied to the default "Your tokens" section so it
218+
// doesn't fill up with sub-$0.10 balances or unpriced tokens (airdrop junk).
219+
// Require a known USD price AND value ≥ threshold. Search results still use
220+
// the full heldTokens list so users can find anything by name or address.
221+
const visibleHeld = useMemo(
222+
() => (heldTokens ?? []).filter((h) => h.usdPrice != null && h.usdValue >= DUST_USD_THRESHOLD),
223+
[heldTokens]
224+
)
225+
213226
// Default view: short curated blue-chip list minus anything in Your tokens.
227+
// Dedup against the visible held list so a dust-hidden token (e.g. tiny USDC
228+
// balance) still shows up in Popular rather than disappearing entirely.
214229
const defaultPopular = useMemo(() => {
215-
const held = heldTokens ?? []
216-
if (held.length === 0) return popularTokens
217-
const heldSet = new Set(held.map((h) => h.token.address.toLowerCase()))
230+
if (visibleHeld.length === 0) return popularTokens
231+
const heldSet = new Set(visibleHeld.map((h) => h.token.address.toLowerCase()))
218232
return popularTokens.filter((t) => !heldSet.has(t.address.toLowerCase()))
219-
}, [popularTokens, heldTokens])
233+
}, [popularTokens, visibleHeld])
220234

221235
// Search view: full 344-entry curated list minus held, still filtered below.
222236
const searchCurated = useMemo(() => {
@@ -242,6 +256,12 @@ const TokenSelectorModalComponent = ({
242256
[heldTokens, q, excludeAddrLower]
243257
)
244258

259+
// Default "Your tokens" list: held minus dust and minus the excluded side.
260+
const defaultHeld: HeldToken[] = useMemo(
261+
() => visibleHeld.filter((h) => h.token.address.toLowerCase() !== excludeAddrLower),
262+
[visibleHeld, excludeAddrLower]
263+
)
264+
245265
const filteredCurated = useMemo(
246266
() => searchCurated.filter(matchesQuery),
247267
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -329,7 +349,7 @@ const TokenSelectorModalComponent = ({
329349
filteredCurated.length > 0 ||
330350
barterMatches.length > 0 ||
331351
pastedBarterToken !== null
332-
: filteredHeld.length > 0 || filteredRecent.length > 0 || defaultPopular.length > 0
352+
: defaultHeld.length > 0 || filteredRecent.length > 0 || defaultPopular.length > 0
333353

334354
return (
335355
<Dialog open={open} onOpenChange={onOpenChange}>
@@ -450,14 +470,14 @@ const TokenSelectorModalComponent = ({
450470
) : (
451471
// Default view: Your tokens + Recent searches + Popular tokens.
452472
<>
453-
{filteredHeld.length > 0 && (
473+
{defaultHeld.length > 0 && (
454474
<section>
455475
<SectionHeader
456476
icon={<Coins className="h-4 w-4" />}
457477
label="Your tokens"
458-
count={filteredHeld.length}
478+
count={defaultHeld.length}
459479
/>
460-
{filteredHeld.map((h) => (
480+
{defaultHeld.map((h) => (
461481
<TokenRow
462482
key={`held-${h.token.address}`}
463483
token={h.token}
@@ -515,7 +535,7 @@ const TokenSelectorModalComponent = ({
515535
))}
516536
</section>
517537
)}
518-
{isLoadingHeld && filteredHeld.length === 0 && address && (
538+
{isLoadingHeld && defaultHeld.length === 0 && address && (
519539
<p className="px-3 py-2 text-xs text-muted-foreground">Loading your balances…</p>
520540
)}
521541
</>

src/hooks/use-wait-for-tx-confirmation.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,16 @@ export function useWaitForTxConfirmation({
142142
hasConfirmedRef.current = true
143143
if (abortRef.current) abortRef.current.abort()
144144

145-
const e = receiptError instanceof Error ? receiptError : new Error(String(receiptError))
145+
// If wagmi reports a dropped/replaced transaction, surface the full hash
146+
// so users can look it up. Wagmi's own message doesn't always include it.
147+
const raw = receiptError instanceof Error ? receiptError.message : String(receiptError)
148+
const mentionsDropped = /drop|replac/i.test(raw)
149+
const e =
150+
mentionsDropped && hash
151+
? new Error(`Transaction ${hash} was dropped by the network.`)
152+
: receiptError instanceof Error
153+
? receiptError
154+
: new Error(String(receiptError))
146155
setError(e)
147156
onErrorRef.current?.(e)
148157
}, [hash, receiptError])
@@ -189,7 +198,7 @@ export function useWaitForTxConfirmation({
189198
if (mcStatus === "failed") {
190199
hasConfirmedRef.current = true
191200
abortController.abort()
192-
const e = new Error("Transaction was dropped by the network.")
201+
const e = new Error(`Transaction ${hash} was dropped by the network.`)
193202
setError(e)
194203
onErrorRef.current?.(e)
195204
} else if (mcStatus === "confirmed") {
@@ -296,7 +305,7 @@ export function useWaitForTxConfirmation({
296305
hasConfirmedRef.current = true
297306
abortController.abort()
298307
clearInterval(dbPollInterval)
299-
const e = new Error("Transaction was dropped by the network.")
308+
const e = new Error(`Transaction ${hash} was dropped by the network.`)
300309
setError(e)
301310
onErrorRef.current?.(e)
302311
return

src/lib/transaction-errors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ function mapErrorMessage(error: unknown): string | null {
121121
return null
122122
}
123123

124+
// Dropped transactions have their own hash-bearing message that must pass
125+
// through unmodified. Check before the generic network heuristic below
126+
// since the message contains the word "network".
127+
if (message.includes("was dropped by the network")) {
128+
return null
129+
}
130+
124131
if (
125132
message.includes("failed to fetch") ||
126133
message.includes("rpc") ||

0 commit comments

Comments
 (0)