Skip to content

Commit

Permalink
feat: add configurable route labels/badges
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Jan 3, 2025
1 parent 825856c commit ede5fbe
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 3 deletions.
43 changes: 43 additions & 0 deletions packages/widget-playground/src/defaultWidgetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,49 @@ export const widgetBaseConfig: WidgetConfig = {
// 42161: ['https://scan.li.fi'], // Arbitrum
// internal: ['https://jumper.exchange/scan'], // Transder ID Card
// },
// routeLabels: [
// {
// label: {
// text: 'OP Reward',
// sx: {
// background: 'linear-gradient(90deg, #ff0404, #ff04c8)',
// '@keyframes gradient': {
// '0%': { backgroundPosition: '0% 50%' },
// '50%': { backgroundPosition: '100% 50%' },
// '100%': { backgroundPosition: '0% 50%' },
// },
// animation: 'gradient 3s ease infinite',
// backgroundSize: '200% 200%',
// color: '#ffffff',
// },
// },
// fromChainId: [ChainId.OPT],
// },
// {
// label: {
// text: 'LI.FI Bonus',
// sx: () => ({
// display: 'flex',
// alignItems: 'center',
// position: 'relative',
// overflow: 'hidden',
// marginLeft: 'auto',
// order: 1,
// backgroundImage:
// 'url(https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/lifidexaggregator.svg)',
// backgroundPosition: 'left center',
// backgroundRepeat: 'no-repeat',
// backgroundSize: '24px',
// paddingLeft: '12px',
// backgroundColor: '#f5b5ff',
// }),
// },
// fromChainId: [ChainId.OPT],
// exchanges: {
// allow: ['lifidexaggregator'],
// },
// },
// ],
}

export const defaultWidgetConfig: Partial<WidgetConfig> = {
Expand Down
1 change: 0 additions & 1 deletion packages/widget/src/components/Card/CardLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export const CardLabel = styled(Box, {
minWidth: 24,
userSelect: 'none',
fontSize: '1rem',
marginRight: theme.spacing(1),
backgroundColor: blend(
theme.palette.background.paper,
theme.palette.common.white,
Expand Down
14 changes: 12 additions & 2 deletions packages/widget/src/components/RouteCard/RouteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Token } from '../Token/Token.js'
import { TokenContainer } from './RouteCard.style.js'
import { RouteCardEssentials } from './RouteCardEssentials.js'
import { RouteCardEssentialsExpanded } from './RouteCardEssentialsExpanded.js'
import { getMatchingLabels } from './getMatchingLabels.js'
import type { RouteCardProps } from './types.js'

export const RouteCard: React.FC<
Expand All @@ -26,7 +27,7 @@ export const RouteCard: React.FC<
...other
}) => {
const { t } = useTranslation()
const { subvariant, subvariantOptions } = useWidgetConfig()
const { subvariant, subvariantOptions, routeLabels } = useWidgetConfig()
const [cardExpanded, setCardExpanded] = useState(defaulExpanded)

const handleExpand: MouseEventHandler<HTMLButtonElement> = (e) => {
Expand All @@ -43,6 +44,7 @@ export const RouteCard: React.FC<
? { ...route.fromToken, amount: BigInt(route.fromAmount) }
: undefined

const customLabels = getMatchingLabels(route, routeLabels)
const tags = route.tags?.filter(
(tag) => tag === 'CHEAPEST' || tag === 'FASTEST'
)
Expand All @@ -53,12 +55,15 @@ export const RouteCard: React.FC<
flex: 1,
}}
>
{subvariant !== 'refuel' && route.tags?.length ? (
{subvariant !== 'refuel' &&
(route.tags?.length || customLabels.length) ? (
<Box
sx={{
display: 'flex',
alignItems: 'center',
mb: 2,
gap: 1,
flexWrap: 'wrap',
}}
>
{tags?.length ? (
Expand All @@ -68,6 +73,11 @@ export const RouteCard: React.FC<
</CardLabelTypography>
</CardLabel>
) : null}
{customLabels.map((label, index) => (
<CardLabel key={index} sx={label.sx}>
<CardLabelTypography>{label.text}</CardLabelTypography>
</CardLabel>
))}
</Box>
) : null}
<TokenContainer>
Expand Down
53 changes: 53 additions & 0 deletions packages/widget/src/components/RouteCard/getMatchingLabels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Route } from '@lifi/sdk'
import type { RouteLabel, RouteLabelRule } from '../../types/widget.js'
import { isItemAllowed } from '../../utils/item.js'

export const getMatchingLabels = (
route: Route,
routeLabels?: RouteLabelRule[]
): RouteLabel[] => {
if (!routeLabels?.length) {
return []
}

return routeLabels
.filter((rule) => {
const conditions: boolean[] = []

// Check bridge/exchange matches if specified
if (rule.bridges || rule.exchanges) {
const toolNames = route.steps.flatMap((step) =>
step.includedSteps.map((s) => s.tool)
)
conditions.push(
toolNames.some(
(toolName) =>
isItemAllowed(toolName, rule.bridges) &&
isItemAllowed(toolName, rule.exchanges)
)
)
}

// Check token matches if specified
if (rule.fromTokenAddress?.length) {
conditions.push(rule.fromTokenAddress.includes(route.fromToken.address))
}

if (rule.toTokenAddress?.length) {
conditions.push(rule.toTokenAddress.includes(route.toToken.address))
}

// Check chain matches if specified
if (rule.fromChainId?.length) {
conditions.push(rule.fromChainId.includes(route.fromChainId))
}

if (rule.toChainId?.length) {
conditions.push(rule.toChainId.includes(route.toChainId))
}

// Must have at least one condition and all conditions must be true
return conditions.length && conditions.every(Boolean)
})
.map((rule) => rule.label)
}
22 changes: 22 additions & 0 deletions packages/widget/src/types/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
PaletteMode,
PaletteOptions,
Shape,
SxProps,
Theme,
} from '@mui/material'
import type { TypographyOptions } from '@mui/material/styles/createTypography.js'
Expand Down Expand Up @@ -191,6 +192,22 @@ export type WidgetLanguages = {

export type PoweredByType = 'default' | 'jumper'

export interface RouteLabel {
text: string
sx?: SxProps<Theme>
}

export interface RouteLabelRule {
label: RouteLabel
// Matching criteria
bridges?: AllowDeny<string>
exchanges?: AllowDeny<string>
fromChainId?: number[]
toChainId?: number[]
fromTokenAddress?: string[]
toTokenAddress?: string[]
}

export interface WidgetConfig {
fromChain?: number
toChain?: number
Expand Down Expand Up @@ -243,6 +260,11 @@ export interface WidgetConfig {
explorerUrls?: Record<number, string[]> &
Partial<Record<'internal', string[]>>
poweredBy?: PoweredByType

/**
* Custom labels/badges to show on routes based on specified rules
*/
routeLabels?: RouteLabelRule[]
}

export interface FormFieldOptions {
Expand Down

0 comments on commit ede5fbe

Please sign in to comment.