Skip to content

Commit 090f594

Browse files
committed
grey paused tokens
1 parent d9ade62 commit 090f594

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

src/components/CCIP/Drawer/LaneDrawer.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Address from "~/components/AddressReact.tsx"
22
import "../Tables/Table.css"
33
import { Environment, LaneConfig, LaneFilter, Version } from "~/config/data/ccip/types.ts"
44
import { getNetwork, getTokenData } from "~/config/data/ccip/data.ts"
5-
import { displayCapacity, determineTokenMechanism } from "~/config/data/ccip/utils.ts"
5+
import { displayCapacity, determineTokenMechanism, isTokenPaused } from "~/config/data/ccip/utils.ts"
66
import { useState } from "react"
77
import LaneDetailsHero from "../ChainHero/LaneDetailsHero.tsx"
88
import { getExplorerAddressUrl, getTokenIconUrl, fallbackTokenIconUrl } from "~/features/utils/index.ts"
@@ -136,11 +136,22 @@ function LaneDrawer({
136136
})
137137
if (!Object.keys(data).length) return null
138138
const logo = getTokenIconUrl(token)
139+
140+
// Check if token is paused
141+
const tokenPaused = isTokenPaused(
142+
data[sourceNetwork.key].decimals,
143+
lane.supportedTokens?.[token]?.rateLimiterConfig?.[
144+
inOutbound === LaneFilter.Inbound ? "in" : "out"
145+
]
146+
)
147+
139148
return (
140-
<tr key={index}>
149+
<tr key={index} className={tokenPaused ? "ccip-table__row--paused" : ""}>
141150
<td>
142151
<a href={`/ccip/directory/${environment}/token/${token}`}>
143-
<div className="ccip-table__network-name">
152+
<div
153+
className={`ccip-table__network-name ${tokenPaused ? "ccip-table__network-name--paused" : ""}`}
154+
>
144155
<img
145156
src={logo}
146157
alt={`${token} logo`}
@@ -151,6 +162,14 @@ function LaneDrawer({
151162
}}
152163
/>
153164
{token}
165+
{tokenPaused && (
166+
<span
167+
className="ccip-table__paused-badge"
168+
title="Token transfers are paused (capacity ≤ 1)"
169+
>
170+
⏸️
171+
</span>
172+
)}
154173
</div>
155174
</a>
156175
</td>

src/components/CCIP/Drawer/TokenDrawer.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
getTokenData,
1515
LaneConfig,
1616
} from "~/config/data/ccip/index.ts"
17+
import { isTokenPaused } from "~/config/data/ccip/utils.ts"
1718
import { useState } from "react"
1819
import { ChainType, ExplorerInfo, SupportedChain } from "~/config/index.ts"
1920
import LaneDrawer from "../Drawer/LaneDrawer.tsx"
@@ -214,11 +215,19 @@ function TokenDrawer({
214215
.map(({ networkDetails, laneData, destinationChain, destinationPoolType }) => {
215216
if (!laneData || !networkDetails) return null
216217

218+
// Check if token is paused on this lane
219+
const tokenPaused = isTokenPaused(
220+
network.tokenDecimals,
221+
destinationLanes[destinationChain].rateLimiterConfig?.[
222+
inOutbound === LaneFilter.Inbound ? "in" : "out"
223+
]
224+
)
225+
217226
return (
218-
<tr key={networkDetails.name}>
227+
<tr key={networkDetails.name} className={tokenPaused ? "ccip-table__row--paused" : ""}>
219228
<td>
220229
<div
221-
className="ccip-table__network-name"
230+
className={`ccip-table__network-name ${tokenPaused ? "ccip-table__network-name--paused" : ""}`}
222231
role="button"
223232
onClick={() => {
224233
drawerContentStore.set(() => (
@@ -239,6 +248,14 @@ function TokenDrawer({
239248
>
240249
<img src={networkDetails?.logo} alt={networkDetails?.name} className="ccip-table__logo" />
241250
{networkDetails?.name}
251+
{tokenPaused && (
252+
<span
253+
className="ccip-table__paused-badge"
254+
title="Token transfers are paused (capacity ≤ 1)"
255+
>
256+
⏸️
257+
</span>
258+
)}
242259
</div>
243260
</td>
244261
<td>

src/components/CCIP/Tables/Table.css

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,48 @@
253253
justify-content: center;
254254
}
255255
}
256+
257+
/* Paused token styles */
258+
.ccip-table__row--paused {
259+
opacity: 0.6;
260+
background-color: var(--gray-50);
261+
}
262+
263+
.ccip-table__row--paused:hover {
264+
opacity: 0.8;
265+
background-color: var(--gray-100);
266+
}
267+
268+
.ccip-table__network-name--paused {
269+
color: var(--gray-400) !important;
270+
filter: grayscale(0.7);
271+
}
272+
273+
.ccip-table__network-name--paused img {
274+
filter: grayscale(0.8) opacity(0.7);
275+
}
276+
277+
.ccip-table__paused-badge {
278+
margin-left: var(--space-2x);
279+
font-size: 12px;
280+
opacity: 0.8;
281+
display: inline-flex;
282+
align-items: center;
283+
cursor: help;
284+
}
285+
286+
/* Ensure paused tokens still allow interaction for tooltips */
287+
.ccip-table__row--paused .ccip-table__network-name {
288+
pointer-events: auto;
289+
}
290+
291+
/* Additional styling for capacity and rate cells in paused state */
292+
.ccip-table__row--paused td {
293+
color: var(--gray-400);
294+
}
295+
296+
.ccip-table__row--paused a {
297+
color: var(--gray-400);
298+
text-decoration: none;
299+
pointer-events: none;
300+
}

src/config/data/ccip/utils.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,34 @@ export const displayRate = (capacity: string, rate: string, symbol: string, deci
189189
maxThroughput: `Refills from 0 to ${commify(cleanedCapacity)} ${symbol} in ${displayTime}`,
190190
}
191191
}
192+
193+
// ==============================
194+
// UTILITY FUNCTIONS FOR TOKEN STATUS
195+
// ==============================
196+
197+
/**
198+
* Determines if a token is paused based on its rate limiter configuration
199+
* A token is considered paused if its capacity is <= 1
200+
*
201+
*/
202+
export const isTokenPaused = (decimals = 18, rateLimiterConfig?: RateLimiterConfig): boolean => {
203+
if (!rateLimiterConfig?.isEnabled) {
204+
return false // N/A tokens are not considered paused
205+
}
206+
207+
const capacity = rateLimiterConfig?.capacity || "0"
208+
209+
try {
210+
// Convert to BigInt for precise comparison
211+
const capacityBigInt = BigInt(capacity)
212+
// Calculate threshold: 1 token in smallest units = 10^decimals
213+
const oneTokenInSmallestUnits = BigInt(10) ** BigInt(decimals)
214+
215+
// Direct BigInt comparison - no floating point risks
216+
return capacityBigInt <= oneTokenInSmallestUnits
217+
} catch (error) {
218+
// If capacity is not a valid number, treat as paused for safety
219+
console.warn(`Invalid capacity value for rate limiter: ${capacity}`, error)
220+
return true
221+
}
222+
}

0 commit comments

Comments
 (0)