Skip to content

Commit

Permalink
feat: IBC Swaps using Squid Router (#1208)
Browse files Browse the repository at this point in the history
* wip: ibc swaps ui

* wip: ibc swaps integration

* wip: ibc swap

* wip

* fetch balances

* wip

* wip

* wip

* wip

* feat: integrate execute route

* add loading state for swap txn

* chore: fix lint issues

* swap with squid: wip

* wip

* fix: executeRoute

* wip: ibc swap

* add validations

* track tx status

* add retry for stargate client

* chore: add exp suggest chain

* wip

* chore

* chore: review changes

* feat: add swap route preview

* chore: review changes

* chore: refactor

* refactor
  • Loading branch information
Hemanthghs authored Apr 10, 2024
1 parent 7c88798 commit 4f4aef2
Show file tree
Hide file tree
Showing 29 changed files with 2,791 additions and 361 deletions.
4 changes: 4 additions & 0 deletions frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**',
},
{
protocol: 'https',
hostname: 'raw.githubusercontent.com',
Expand Down
4 changes: 3 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"lint": "next lint --no-cache"
},
"dependencies": {
"@0xsquid/sdk": "^1.14.15",
"@cosmjs/amino": "^0.31.3",
"@cosmjs/proto-signing": "^0.32.1",
"@cosmjs/stargate": "^0.32.1",
Expand All @@ -22,13 +23,14 @@
"@mui/material": "^5.14.10",
"@mui/x-date-pickers": "5.0.4",
"@reduxjs/toolkit": "^1.9.7",
"@skip-router/core": "^1.1.1",
"@skip-router/core": "^1.3.11",
"@types/node": "20.6.5",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"autoprefixer": "10.4.16",
"axios": "^1.5.1",
"axios-retry": "^4.0.0",
"chain-registry": "1.28.1",
"chart.js": "^4.4.1",
"cosmjs-types": "^0.9.0",
"date-fns": "2.30.0",
Expand Down
3 changes: 3 additions & 0 deletions frontend/public/down-arrow-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions frontend/public/ibc-swap-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions frontend/src/app/(routes)/transfers/components/AssetsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from 'react';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';
import Avatar from '@mui/material/Avatar';
import { CircularProgress, Paper } from '@mui/material';
import { shortenName } from '@/utils/util';
import { AssetConfig } from '@/types/swaps';

export default function AssetsAutocomplete({
options,
handleChange,
selectedAsset,
assetsLoading,
}: {
options: AssetConfig[];
handleChange: (option: AssetConfig | null) => void;
selectedAsset: AssetConfig | null;
assetsLoading: boolean;
}) {
/* eslint-disable @typescript-eslint/no-explicit-any */
const renderOption = (props: any, option: AssetConfig) => (
<li {...props} key={option.symbol + option.logoURI + option.denom}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<Avatar
src={option.logoURI}
alt={option.label}
sx={{ width: '24px', height: '24px' }}
/>
<div className="flex flex-col">
<span className="font-semibold truncate">
{shortenName(option.symbol, 15)}
</span>
<span className="font-extralight truncate text-[12px]">
{shortenName(option.name, 20)}
</span>
</div>
</div>
</li>
);

/* eslint-disable @typescript-eslint/no-explicit-any */
const renderInput = (params: any) => (
<TextField
className="bg-[#171328] rounded-2xl drop-down"
placeholder="Select Asset"
{...params}
InputProps={{
...params.InputProps,
startAdornment: (
<React.Fragment>
{selectedAsset && (
<Avatar
src={selectedAsset.logoURI}
alt={selectedAsset.label}
style={{ marginRight: 1 }}
sx={{ width: '24px', height: '24px' }}
/>
)}
{params.InputProps.startAdornment}
</React.Fragment>
),
}}
sx={{
'& .MuiInputBase-input': {
color: 'white',
fontSize: '16px',
fontWeight: 300,
fontFamily: 'inter',
},
'& .MuiOutlinedInput-notchedOutline': {
border: 'none',
},
'& .MuiSvgIcon-root': {
color: 'white',
},
}}
/>
);

return (
<Autocomplete
disablePortal
fullWidth
id="chain-autocomplete"
options={options}
getOptionLabel={(option: AssetConfig) => option.symbol}
renderOption={renderOption}
renderInput={renderInput}
onChange={(_, newValue) => handleChange(newValue)}
value={selectedAsset}
PaperComponent={({ children }) => (
<Paper
style={{
background:
'linear-gradient(178deg, #241B61 1.71%, #69448D 98.35%, #69448D 98.35%)',
color: 'white',
borderRadius: '12px',
padding: 1,
}}
>
{assetsLoading ? (
<div className="flex justify-center items-center p-4">
<CircularProgress color="inherit" size={20} />
</div>
) : (
children
)}
</Paper>
)}
/>
);
}
121 changes: 121 additions & 0 deletions frontend/src/app/(routes)/transfers/components/ChainsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from 'react';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';
import Avatar from '@mui/material/Avatar';
import { CircularProgress, Paper } from '@mui/material';
import { shortenName } from '@/utils/util';
import { ChainConfig } from '@/types/swaps';

interface ChainOption {
label: string;
chainID: string;
logoURI: string;
}

export default function ChainsList({
options,
handleChange,
selectedChain,
dataLoading,
}: {
options: ChainConfig[];
handleChange: (option: ChainOption | null) => void;
selectedChain: ChainConfig | null;
dataLoading: boolean;
}) {
/* eslint-disable @typescript-eslint/no-explicit-any */
const renderOption = (props: any, option: ChainOption) => (
<li {...props} key={option.chainID}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<Avatar
src={option.logoURI}
alt={option.label}
sx={{ width: '24px', height: '24px' }}
/>
<div className="flex flex-col">
<span className="font-semibold truncate text-capitalize">
{shortenName(option.label, 15)}
</span>
<span className="font-extralight truncate text-[12px]">
{shortenName(option.chainID, 15)}
</span>
</div>
</div>
</li>
);

/* eslint-disable @typescript-eslint/no-explicit-any */
const renderInput = (params: any) => (
<TextField
className="bg-[#171328] rounded-2xl drop-down"
placeholder="Select Network"
{...params}
InputProps={{
...params.InputProps,
startAdornment: (
<React.Fragment>
{selectedChain && (
<Avatar
src={selectedChain.logoURI}
alt={selectedChain.label}
style={{ marginRight: 1 }}
sx={{ width: '24px', height: '24px' }}
/>
)}
{params.InputProps.startAdornment}
</React.Fragment>
),
}}
sx={{
'& .MuiInputBase-input': {
color: 'white',
fontSize: '16px',
fontWeight: 300,
fontFamily: 'inter',
textTransform: 'capitalize',
},
'& .MuiOutlinedInput-notchedOutline': {
border: 'none',
},
'& .MuiSvgIcon-root': {
color: 'white',
},
}}
/>
);

return (
<div>
<Autocomplete
disablePortal
fullWidth
id="chain-autocomplete"
options={options}
getOptionLabel={(option: ChainOption) => option.label}
renderOption={renderOption}
renderInput={renderInput}
onChange={(_, newValue) => handleChange(newValue)}
value={selectedChain}
PaperComponent={({ children }) => (
<Paper
style={{
background:
'linear-gradient(178deg, #241B61 1.71%, #69448D 98.35%, #69448D 98.35%)',
color: 'white',
borderRadius: '12px',
padding: 1,
}}
>
{dataLoading ? (
<div className="flex justify-center items-center p-4">
<CircularProgress color="inherit" size={20} />
</div>
) : (
children
)}
</Paper>
)}
/>
</div>
);
}
Loading

0 comments on commit 4f4aef2

Please sign in to comment.