Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: lifi integration #1776

Merged
merged 24 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bda6fe7
WIP: lifi xswap integration
0xMasayoshi Dec 12, 2024
3e5c7cf
feat: xswap route sorting
0xMasayoshi Dec 13, 2024
e1dc8be
feat: update xswap fee display format
0xMasayoshi Dec 13, 2024
a995cd2
feat: add loading and no route states to CrossChainRouteSelector
0xMasayoshi Dec 13, 2024
93c5a6b
chore: update xswap layout
0xMasayoshi Dec 18, 2024
fcef60a
chore: add back swap details to CrossChainRouteCard
0xMasayoshi Dec 18, 2024
7c91072
feat: display network name under token symbol
0xMasayoshi Dec 18, 2024
618eb6c
chore: add xswap review dialog fee subtitles
0xMasayoshi Dec 18, 2024
88a6292
feat: xswap route visualization
0xMasayoshi Dec 20, 2024
be7b6d1
Merge remote-tracking branch 'origin/master' into feat/lifi
0xMasayoshi Dec 20, 2024
62b66c5
feat: lifi route selector mobile view
0xMasayoshi Dec 21, 2024
4713f04
chore: style
0xMasayoshi Dec 24, 2024
8dad43d
fix: xswap route selector route selector placement
0xMasayoshi Jan 8, 2025
efd1d96
fix: mobile xswap route selector overflow
0xMasayoshi Jan 8, 2025
0c0aa98
chore: add cronos to XSWAP_SUPPORTED_CHAIN_IDS
0xMasayoshi Jan 9, 2025
223c841
chore: add copy to xswap route selector loading state
0xMasayoshi Jan 10, 2025
b3a2791
fix: xswap route view
0xMasayoshi Jan 10, 2025
733399b
chore: update xswap cache & refetch rate
0xMasayoshi Jan 10, 2025
c5862e5
fix: selectedBridge
0xMasayoshi Jan 10, 2025
a8d2b41
chore: placeholder data in XSwap review dialog
0xMasayoshi Jan 10, 2025
3372761
fix: handle unpriced token
0xMasayoshi Jan 13, 2025
5bc73d8
chore: xswap route selector loading animation
0xMasayoshi Jan 15, 2025
417a018
Merge remote-tracking branch 'origin/master' into feat/lifi
0xMasayoshi Jan 16, 2025
e422bf9
chore: update No Routes Found view
0xMasayoshi Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { XSWAP_SUPPORTED_CHAIN_IDS, isXSwapSupportedChainId } from 'src/config'
import { ChainId } from 'sushi/chain'
import {
SUSHIXSWAP_2_SUPPORTED_CHAIN_IDS,
isSushiXSwap2ChainId,
} from 'sushi/config'
import { SidebarContainer } from '~evm/_common/ui/sidebar'
import { Providers } from './providers'

Expand All @@ -24,18 +21,20 @@ export default async function CrossChainSwapLayout(props: {

const chainId = +params.chainId as ChainId

if (!isSushiXSwap2ChainId(chainId)) {
if (!isXSwapSupportedChainId(chainId)) {
return notFound()
}

return (
<Providers chainId={chainId}>
<SidebarContainer
selectedNetwork={chainId}
supportedNetworks={SUSHIXSWAP_2_SUPPORTED_CHAIN_IDS}
supportedNetworks={XSWAP_SUPPORTED_CHAIN_IDS}
unsupportedNetworkHref="/ethereum/cross-chain-swap"
>
<main className="lg:p-4 mt-16 mb-[86px]">{children}</main>
<main className="lg:p-4 mt-16 mb-[86px] h-[clamp(600px,_calc(100vh_-_280px),_800px)]">
{children}
</main>
</SidebarContainer>
</Providers>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ export default function CrossChainSwapLoading() {
<div className="flex flex-col gap-4">
<div />
<div className="flex flex-col gap-2 mb-4 sm:mt-10 mt-2">
<SkeletonBox className="w-[140px] h-[53px]" />
<SkeletonBox className="h-[20px] w-[280px]" />
<SkeletonBox className="w-[140px] h-[36px] lg:h-[53px] rounded-xl" />
<SkeletonBox className="h-[20px] w-[280px] rounded-xl" />
</div>
<div className="flex gap-2">
<SkeletonBox className="h-[36px] w-[61px]" />
<SkeletonBox className="h-[36px] w-[56px]" />
<SkeletonBox className="h-[36px] w-[54px]" />
<SkeletonBox className="h-[36px] w-[136px]" />
<SkeletonBox className="h-[36px] w-[61px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[56px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[54px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[136px] rounded-xl" />
</div>
<div className="flex flex-col gap-2.5">
<SkeletonBox className="w-full h-[169px]" />
<SkeletonBox className="w-full h-[169px]" />
<div className="flex flex-col gap-[10px]">
<SkeletonBox className="w-full h-[142px] rounded-xl" />
<SkeletonBox className="w-full h-[142px] rounded-xl" />
</div>
<SkeletonBox className="w-full h-[52px]" />
<SkeletonBox className="w-full h-[52px] rounded-xl" />
</div>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
import { Container } from '@sushiswap/ui'
'use client'

import { Container, classNames } from '@sushiswap/ui'
import { useSidebar } from 'src/ui/sidebar'
import { CrossChainSwapRouteSelector } from 'src/ui/swap/cross-chain/cross-chain-swap-route-selector'
import { CrossChainSwapWidget } from 'src/ui/swap/cross-chain/cross-chain-swap-widget'
import { useCrossChainTradeRoutes } from 'src/ui/swap/cross-chain/derivedstate-cross-chain-swap-provider'

export default function CrossChainSwapPage() {
const { isLoading, isFetched } = useCrossChainTradeRoutes()
const { isOpen: isSidebarOpen } = useSidebar()

const showRouteSelector = isLoading || isFetched

export default async function CrossChainSwapPage() {
return (
<Container maxWidth="lg" className="px-4">
<CrossChainSwapWidget />
</Container>
<div
className={classNames(
'flex justify-center flex-wrap gap-y-4 h-full',
showRouteSelector && isSidebarOpen ? 'lg:ml-56' : '',
)}
>
<Container maxWidth="lg" className="px-4 !mx-[unset]">
<CrossChainSwapWidget />
</Container>
{showRouteSelector ? (
<Container maxWidth="lg" className="px-4 !mx-[unset] flex items-center">
<CrossChainSwapRouteSelector />
</Container>
) : null}
</div>
)
}
20 changes: 10 additions & 10 deletions apps/web/src/app/(networks)/(evm)/[chainId]/(trade)/dca/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ export default function SimpleSwapLoading() {
<div className="flex flex-col gap-4">
<div />
<div className="flex flex-col gap-2 mb-4 sm:mt-10 mt-2">
<SkeletonBox className="w-[140px] h-[53px]" />
<SkeletonBox className="h-[20px] w-[280px]" />
<SkeletonBox className="w-[140px] h-[36px] lg:h-[53px] rounded-xl" />
<SkeletonBox className="h-[20px] w-[280px] rounded-xl" />
</div>
<div className="flex gap-2">
<SkeletonBox className="h-[36px] w-[61px]" />
<SkeletonBox className="h-[36px] w-[56px]" />
<SkeletonBox className="h-[36px] w-[54px]" />
<SkeletonBox className="h-[36px] w-[136px]" />
<SkeletonBox className="h-[36px] w-[61px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[56px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[54px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[136px] rounded-xl" />
</div>
<div className="flex flex-col gap-2.5">
<SkeletonBox className="w-full h-[142px]" />
<SkeletonBox className="w-full h-[142px]" />
<div className="flex flex-col gap-[10px]">
<SkeletonBox className="w-full h-[142px] rounded-xl" />
<SkeletonBox className="w-full h-[142px] rounded-xl" />
</div>
<SkeletonBox className="w-full h-[52px]" />
<SkeletonBox className="w-full h-[52px] rounded-xl" />
</div>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ export default function SimpleSwapLoading() {
<div className="flex flex-col gap-4">
<div />
<div className="flex flex-col gap-2 mb-4 sm:mt-10 mt-2">
<SkeletonBox className="w-[140px] h-[53px]" />
<SkeletonBox className="h-[20px] w-[280px]" />
<SkeletonBox className="w-[140px] h-[36px] lg:h-[53px] rounded-xl" />
<SkeletonBox className="h-[20px] w-[280px] rounded-xl" />
</div>
<div className="flex gap-2">
<SkeletonBox className="h-[36px] w-[61px]" />
<SkeletonBox className="h-[36px] w-[56px]" />
<SkeletonBox className="h-[36px] w-[54px]" />
<SkeletonBox className="h-[36px] w-[136px]" />
<SkeletonBox className="h-[36px] w-[61px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[56px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[54px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[136px] rounded-xl" />
</div>
<div className="flex flex-col gap-2.5">
<SkeletonBox className="w-full h-[142px]" />
<SkeletonBox className="w-full h-[142px]" />
<div className="flex flex-col gap-[10px]">
<SkeletonBox className="w-full h-[142px] rounded-xl" />
<SkeletonBox className="w-full h-[142px] rounded-xl" />
</div>
<SkeletonBox className="w-full h-[52px]" />
<SkeletonBox className="w-full h-[52px] rounded-xl" />
</div>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ export default function SimpleSwapLoading() {
<div className="flex flex-col gap-4">
<div />
<div className="flex flex-col gap-2 mb-4 sm:mt-10 mt-2">
<SkeletonBox className="w-[140px] h-[53px]" />
<SkeletonBox className="h-[20px] w-[280px]" />
<SkeletonBox className="w-[140px] h-[36px] lg:h-[53px] rounded-xl" />
<SkeletonBox className="h-[20px] w-[280px] rounded-xl" />
</div>
<div className="flex gap-2">
<SkeletonBox className="h-[36px] w-[61px]" />
<SkeletonBox className="h-[36px] w-[56px]" />
<SkeletonBox className="h-[36px] w-[54px]" />
<SkeletonBox className="h-[36px] w-[136px]" />
<SkeletonBox className="h-[36px] w-[61px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[56px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[54px] rounded-xl" />
<SkeletonBox className="h-[36px] w-[136px] rounded-xl" />
</div>
<div className="flex flex-col gap-2.5">
<SkeletonBox className="w-full h-[142px]" />
<SkeletonBox className="w-full h-[142px]" />
<div className="flex flex-col gap-[10px]">
<SkeletonBox className="w-full h-[142px] rounded-xl" />
<SkeletonBox className="w-full h-[142px] rounded-xl" />
</div>
<SkeletonBox className="w-full h-[52px]" />
<SkeletonBox className="w-full h-[52px] rounded-xl" />
</div>
</Container>
)
Expand Down
75 changes: 0 additions & 75 deletions apps/web/src/app/(networks)/(evm)/api/cross-chain/route.ts

This file was deleted.

80 changes: 80 additions & 0 deletions apps/web/src/app/(networks)/(evm)/api/cross-chain/routes/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { NextRequest } from 'next/server'
import { isXSwapSupportedChainId } from 'src/config'
import { isAddress } from 'viem'
import { z } from 'zod'

const schema = z.object({
fromChainId: z.coerce
.number()
.refine((chainId) => isXSwapSupportedChainId(chainId), {
message: `fromChainId must exist in XSwapChainId`,
}),
fromAmount: z.string(),
fromTokenAddress: z.string().refine((token) => isAddress(token), {
message: 'fromTokenAddress does not conform to Address',
}),
toChainId: z.coerce
.number()
.refine((chainId) => isXSwapSupportedChainId(chainId), {
message: `toChainId must exist in XSwapChainId`,
}),
toTokenAddress: z.string().refine((token) => isAddress(token), {
message: 'toTokenAddress does not conform to Address',
}),
fromAddress: z
.string()
.refine((address) => isAddress(address), {
message: 'fromAddress does not conform to Address',
})
.optional(),
toAddress: z
.string()
.refine((address) => isAddress(address), {
message: 'toAddress does not conform to Address',
})
.optional(),
slippage: z.coerce.number(), // decimal
order: z.enum(['CHEAPEST', 'FASTEST']).optional(),
})

export const revalidate = 20

export async function GET(request: NextRequest) {
const params = Object.fromEntries(request.nextUrl.searchParams.entries())

const { slippage, order = 'CHEAPEST', ...parsedParams } = schema.parse(params)

const url = new URL('https://li.quest/v1/advanced/routes')

const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
...(process.env.LIFI_API_KEY && {
'x-lifi-api-key': process.env.LIFI_API_KEY,
}),
},
body: JSON.stringify({
...parsedParams,
options: {
slippage,
order,
integrator: 'sushi',
exchanges: { allow: ['sushiswap'] },
allowSwitchChain: false,
allowDestinationCall: true,
// fee: // TODO: must set up feeReceiver w/ lifi
},
}),
}

const response = await fetch(url, options)

return Response.json(await response.json(), {
status: response.status,
headers: {
'Cache-Control': 's-maxage=15, stale-while-revalidate=20',
},
})
}
Loading
Loading