Skip to content

Commit e86773d

Browse files
committed
refactor: cleanup Lane's table logic
1 parent 6cc53ab commit e86773d

File tree

2 files changed

+151
-104
lines changed

2 files changed

+151
-104
lines changed

src/components/CCIP/Drawer/LaneDrawer.tsx

Lines changed: 87 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import Address from "~/components/AddressReact.tsx"
22
import "../Tables/Table.css"
3-
import { Environment, LaneConfig, LaneFilter, Version } from "~/config/data/ccip/types.ts"
4-
import { getNetwork, getTokenData } from "~/config/data/ccip/data.ts"
3+
import { Environment, LaneConfig, LaneFilter } from "~/config/data/ccip/types.ts"
4+
import { getNetwork } from "~/config/data/ccip/data.ts"
55
import { determineTokenMechanism } from "~/config/data/ccip/utils.ts"
66
import { useState } from "react"
77
import LaneDetailsHero from "../ChainHero/LaneDetailsHero.tsx"
8-
import { getExplorerAddressUrl, getTokenIconUrl, fallbackTokenIconUrl } from "~/features/utils/index.ts"
8+
import { getExplorerAddressUrl, fallbackTokenIconUrl } from "~/features/utils/index.ts"
99
import TableSearchInput from "../Tables/TableSearchInput.tsx"
1010
import { Tooltip } from "~/features/common/Tooltip/Tooltip.tsx"
1111
import { ChainType, ExplorerInfo } from "@config/types.ts"
1212
import { useTokenRateLimits } from "~/hooks/useTokenRateLimits.ts"
1313
import { RateLimitCell } from "~/components/CCIP/RateLimitCell.tsx"
14-
import { realtimeDataService } from "~/lib/ccip/services/realtime-data-instance.ts"
14+
import { useLaneTokens } from "~/hooks/useLaneTokens.ts"
1515

1616
function LaneDrawer({
1717
lane,
@@ -47,6 +47,15 @@ function LaneDrawer({
4747
// Fetch rate limits data using custom hook
4848
const { rateLimits, isLoading: isLoadingRateLimits } = useTokenRateLimits(source, destination, environment)
4949

50+
// Process tokens with hook
51+
const { tokens: processedTokens, count: tokenCount } = useLaneTokens({
52+
tokens: lane.supportedTokens,
53+
environment,
54+
rateLimitsData: rateLimits,
55+
inOutbound,
56+
searchQuery: search,
57+
})
58+
5059
return (
5160
<>
5261
<h2 className="ccip-table__drawer-heading">Lane Details</h2>
@@ -73,7 +82,7 @@ function LaneDrawer({
7382
<div className="ccip-table__filters">
7483
<div>
7584
<div className="ccip-table__filters-title">
76-
Tokens <span>({lane?.supportedTokens ? lane.supportedTokens.length : 0})</span>
85+
Tokens <span>({tokenCount})</span>
7786
</div>
7887
</div>
7988
<TableSearchInput search={search} setSearch={setSearch} />
@@ -183,109 +192,83 @@ function LaneDrawer({
183192
</tr>
184193
</thead>
185194
<tbody>
186-
{lane.supportedTokens &&
187-
lane.supportedTokens
188-
.filter((token) => token.toLowerCase().includes(search.toLowerCase()))
189-
.map((token, index) => {
190-
const data = getTokenData({
191-
environment,
192-
version: Version.V1_2_0,
193-
tokenId: token || "",
194-
})
195-
if (!Object.keys(data).length) return null
196-
const logo = getTokenIconUrl(token)
197-
198-
// Get rate limit data for this token
199-
const tokenRateLimits = rateLimits[token]
200-
201-
// Determine direction based on inOutbound filter
202-
const direction = inOutbound === LaneFilter.Outbound ? "out" : "in"
203-
204-
// Get standard and FTF rate limits
205-
const allLimits = realtimeDataService.getAllRateLimitsForDirection(tokenRateLimits, direction)
206-
207-
// Token is paused if standard rate limit capacity is 0
208-
const tokenPaused = allLimits.standard?.capacity === "0"
209-
210-
return (
211-
<tr key={index} className={tokenPaused ? "ccip-table__row--paused" : ""}>
212-
<td>
213-
<a href={`/ccip/directory/${environment}/token/${token}`}>
214-
<div
215-
className={`ccip-table__network-name ${tokenPaused ? "ccip-table__network-name--paused" : ""}`}
216-
>
217-
<img
218-
src={logo}
219-
alt={`${token} logo`}
220-
className="ccip-table__logo"
221-
onError={({ currentTarget }) => {
222-
currentTarget.onerror = null // prevents looping
223-
currentTarget.src = fallbackTokenIconUrl
224-
}}
225-
/>
226-
{token}
227-
{tokenPaused && (
228-
<span className="ccip-table__paused-badge" title="Transfers are currently paused">
229-
⏸️
230-
</span>
231-
)}
232-
</div>
233-
</a>
234-
</td>
235-
<td data-clipboard-type="token">
236-
<Address
237-
address={data[sourceNetwork.key].tokenAddress}
238-
endLength={4}
239-
contractUrl={getExplorerAddressUrl(explorer)(data[sourceNetwork.key].tokenAddress)}
240-
/>
241-
</td>
242-
<td>{data[sourceNetwork.key].decimals}</td>
243-
<td>
244-
{inOutbound === LaneFilter.Outbound
245-
? determineTokenMechanism(
246-
data[sourceNetwork.key].pool.type,
247-
data[destinationNetwork.key].pool.type
248-
)
249-
: determineTokenMechanism(
250-
data[destinationNetwork.key].pool.type,
251-
data[sourceNetwork.key].pool.type
252-
)}
253-
</td>
195+
{processedTokens.map((token, index) => (
196+
<tr key={index} className={token.isPaused ? "ccip-table__row--paused" : ""}>
197+
<td>
198+
<a href={`/ccip/directory/${environment}/token/${token.id}`}>
199+
<div
200+
className={`ccip-table__network-name ${token.isPaused ? "ccip-table__network-name--paused" : ""}`}
201+
>
202+
<img
203+
src={token.logo}
204+
alt={`${token.id} logo`}
205+
className="ccip-table__logo"
206+
onError={({ currentTarget }) => {
207+
currentTarget.onerror = null // prevents looping
208+
currentTarget.src = fallbackTokenIconUrl
209+
}}
210+
/>
211+
{token.id}
212+
{token.isPaused && (
213+
<span className="ccip-table__paused-badge" title="Transfers are currently paused">
214+
⏸️
215+
</span>
216+
)}
217+
</div>
218+
</a>
219+
</td>
220+
<td data-clipboard-type="token">
221+
<Address
222+
address={token.data[sourceNetwork.key].tokenAddress}
223+
endLength={4}
224+
contractUrl={getExplorerAddressUrl(explorer)(token.data[sourceNetwork.key].tokenAddress)}
225+
/>
226+
</td>
227+
<td>{token.data[sourceNetwork.key].decimals}</td>
228+
<td>
229+
{inOutbound === LaneFilter.Outbound
230+
? determineTokenMechanism(
231+
token.data[sourceNetwork.key].pool.type,
232+
token.data[destinationNetwork.key].pool.type
233+
)
234+
: determineTokenMechanism(
235+
token.data[destinationNetwork.key].pool.type,
236+
token.data[sourceNetwork.key].pool.type
237+
)}
238+
</td>
254239

255-
<td>
256-
<RateLimitCell
257-
isLoading={isLoadingRateLimits}
258-
rateLimit={allLimits.standard}
259-
type="capacity"
260-
showUnavailableTooltip
261-
/>
262-
</td>
263-
<td className="rate-tooltip-cell">
264-
<RateLimitCell isLoading={isLoadingRateLimits} rateLimit={allLimits.standard} type="rate" />
265-
</td>
266-
<td>
267-
<RateLimitCell
268-
isLoading={isLoadingRateLimits}
269-
rateLimit={allLimits.ftf}
270-
type="capacity"
271-
showUnavailableTooltip
272-
/>
273-
</td>
274-
<td>
275-
<RateLimitCell isLoading={isLoadingRateLimits} rateLimit={allLimits.ftf} type="rate" />
276-
</td>
277-
</tr>
278-
)
279-
})}
240+
<td>
241+
<RateLimitCell
242+
isLoading={isLoadingRateLimits}
243+
rateLimit={token.rateLimits.standard}
244+
type="capacity"
245+
showUnavailableTooltip
246+
/>
247+
</td>
248+
<td className="rate-tooltip-cell">
249+
<RateLimitCell
250+
isLoading={isLoadingRateLimits}
251+
rateLimit={token.rateLimits.standard}
252+
type="rate"
253+
/>
254+
</td>
255+
<td>
256+
<RateLimitCell
257+
isLoading={isLoadingRateLimits}
258+
rateLimit={token.rateLimits.ftf}
259+
type="capacity"
260+
showUnavailableTooltip
261+
/>
262+
</td>
263+
<td>
264+
<RateLimitCell isLoading={isLoadingRateLimits} rateLimit={token.rateLimits.ftf} type="rate" />
265+
</td>
266+
</tr>
267+
))}
280268
</tbody>
281269
</table>
282270
</div>
283-
<div className="ccip-table__notFound">
284-
{lane.supportedTokens &&
285-
lane.supportedTokens.filter((token) => token.toLowerCase().includes(search.toLowerCase())).length === 0 && (
286-
<>No tokens found</>
287-
)}
288-
</div>
271+
<div className="ccip-table__notFound">{processedTokens.length === 0 && <>No tokens found</>}</div>
289272
</div>
290273
</>
291274
)

src/hooks/useLaneTokens.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useMemo } from "react"
2+
import { Environment, LaneFilter, Version } from "~/config/data/ccip/types"
3+
import { getTokenData } from "~/config/data/ccip/data"
4+
import { getTokenIconUrl } from "~/features/utils"
5+
import { realtimeDataService } from "~/lib/ccip/services/realtime-data-instance"
6+
7+
export interface ProcessedToken {
8+
id: string
9+
data: ReturnType<typeof getTokenData>
10+
logo: string
11+
rateLimits: {
12+
standard?: { capacity: string; rate: string; isEnabled: boolean }
13+
ftf?: { capacity: string; rate: string; isEnabled: boolean }
14+
}
15+
isPaused: boolean
16+
}
17+
18+
interface UseLaneTokensParams {
19+
tokens: string[] | undefined
20+
environment: Environment
21+
rateLimitsData: Record<string, any>
22+
inOutbound: LaneFilter
23+
searchQuery: string
24+
}
25+
26+
export function useLaneTokens({ tokens, environment, rateLimitsData, inOutbound, searchQuery }: UseLaneTokensParams) {
27+
const processedTokens = useMemo(() => {
28+
if (!tokens) return []
29+
30+
const direction = inOutbound === LaneFilter.Outbound ? "out" : "in"
31+
32+
return tokens
33+
.filter((token) => token.toLowerCase().includes(searchQuery.toLowerCase()))
34+
.map((token) => {
35+
const data = getTokenData({
36+
environment,
37+
version: Version.V1_2_0,
38+
tokenId: token || "",
39+
})
40+
41+
// Skip tokens with no data
42+
if (!Object.keys(data).length) return null
43+
44+
const logo = getTokenIconUrl(token)
45+
const tokenRateLimits = rateLimitsData[token]
46+
const allLimits = realtimeDataService.getAllRateLimitsForDirection(tokenRateLimits, direction)
47+
const isPaused = allLimits.standard?.capacity === "0"
48+
49+
return {
50+
id: token,
51+
data,
52+
logo,
53+
rateLimits: allLimits,
54+
isPaused,
55+
}
56+
})
57+
.filter((token): token is ProcessedToken => token !== null)
58+
}, [tokens, environment, rateLimitsData, inOutbound, searchQuery])
59+
60+
return {
61+
tokens: processedTokens,
62+
count: tokens?.length ?? 0,
63+
}
64+
}

0 commit comments

Comments
 (0)