Skip to content
Merged
Binary file added app/public/images/icons/usds.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion app/src/components/footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const ExternalLink = styled.a`
align-items: center;
column-gap: var(--theme-common-space);
display: flex;
font-size: 1.2rem;
font-size: 1.4rem;
text-decoration: none;

&:active {
Expand Down Expand Up @@ -106,6 +106,13 @@ export const Footer: React.FC = (props) => {
</ExternalLink>
</Start>
<End>
<ExternalLink
href="https://docs.gnosischain.com/bridges/"
rel="noreferrer"
target="_blank"
>
Documentation
</ExternalLink>
<Link href="/faq">FAQ</Link>
{/* <NextLink href="/privacy" passHref>
<Link>Privacy Policy</Link>
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const TR = styled.div<{ $compact?: boolean }>`
row-gap: calc(var(--table-padding-common));
transition: none;

&:hover > * {
&:hover > *:not(:last-child) {
opacity: 0.8;
}

Expand Down
16 changes: 0 additions & 16 deletions app/src/constants/bridged_tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -9762,22 +9762,6 @@
"symbol": "UDT",
"total_supply": "9936213363153110036806",
"type": "ERC-20"
},
{
"bridge_type": "xdai",
"foreign_address": "0xdC035D45d973E3EC169d2276DDab16f1e407384F",
"origin_chain_id": "1",
"address": "",
"circulating_market_cap": null,
"decimals": "18",
"exchange_rate": null,
"holders": "2281",
"icon_url": null,
"is_bridged": true,
"name": "USDS",
"symbol": "USDS",
"total_supply": "3854025994000000000000000000",
"type": "ERC-20"
}
]
}
5 changes: 5 additions & 0 deletions app/src/constants/bridges.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Chains } from './config/chains'
import { contracts } from './config/contracts'

export const bridgeConfig = Object.freeze({
XDAI: {
bridgeProxy: '0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016',
governorMultisig: '0x42F38ec5A75acCEc50054671233dfAC9C0E7A3F6',
tokens: {
dai: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
usds: '0xdc035d45d973e3ec169d2276ddab16f1e407384f',
},
protocol: {
address: '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B',
token: '0xc00e94cb662c3520282e6f5717214004a7f26888',
},
bridgeRouter: contracts.BridgeRouter.address[Chains.mainnet],
},
OMNI: {
bridgeProxy: '0x88ad09518695c6c3712AC10a214bE5109a655671',
Expand Down
18 changes: 18 additions & 0 deletions app/src/constants/usdsToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Token } from '@/types/token'
import { getIcon } from '@/src/utils/icons'
import { NATIVE_TOKEN_ADDRESS, USDS_ADDRESS } from '@/src/constants/config/common'

export const usdsToken: Token = {
chainId: 1,
address: USDS_ADDRESS,
decimals: 18,
logoURI: getIcon('usds'),
name: 'USDS',
symbol: 'USDS',
extensions: {
bridgeInfo: {
1: { tokenAddress: USDS_ADDRESS },
100: { tokenAddress: NATIVE_TOKEN_ADDRESS },
},
},
}
17 changes: 15 additions & 2 deletions app/src/hooks/bridge/useBridgeTokenOutInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const getReceivedTokenInfo = async ({
fromChainId,
omniBridgeInstance,
receiveNativeToken,
receiveUsds,
toChainId,
tokenAddress,
}: {
Expand All @@ -35,6 +36,7 @@ const getReceivedTokenInfo = async ({
tokenAddress: string
omniBridgeInstance: HomeOmniMediator
receiveNativeToken: boolean
receiveUsds: boolean
}): Promise<{ tokenOutAddress: string; canReceiveNativeToken?: boolean }> => {
const { isDAI, isFromForeign, isFromHome, isNativeToken } = getBridgeCommonInfo({
fromChainId,
Expand Down Expand Up @@ -83,6 +85,12 @@ const getReceivedTokenInfo = async ({

if (isFromHome) {
// xDAI -> DAI
if (receiveUsds) {
return {
tokenOutAddress: USDS_ADDRESS,
}
}

if (isNativeToken) {
return {
tokenOutAddress: chainsConfig[toChainId].bridge.DAI,
Expand Down Expand Up @@ -113,10 +121,12 @@ const getReceivedTokenInfo = async ({
export const useBridgeTokenOutInfo = ({
fromChainId,
receiveNativeToken,
receiveUsds,
toChainId,
token,
}: {
receiveNativeToken: boolean
receiveUsds: boolean
toChainId: ChainsValues
fromChainId: ChainsValues
token?: Token
Expand All @@ -127,8 +137,10 @@ export const useBridgeTokenOutInfo = ({
const shouldFetch = !!(token && fromChainId && toChainId)

const { data } = useSWR(
shouldFetch ? [token, fromChainId, toChainId, receiveNativeToken, 'bridgeTokenOut'] : null,
async ([_token, _fromChainId, _toChainId, _receiveNativeToken]) => {
shouldFetch
? [token, fromChainId, toChainId, receiveNativeToken, receiveUsds, 'bridgeTokenOut']
: null,
async ([_token, _fromChainId, _toChainId, _receiveNativeToken, _receiveUsds]) => {
if (
_fromChainId === Chains.mainnet &&
_toChainId === Chains.gnosis &&
Expand Down Expand Up @@ -161,6 +173,7 @@ export const useBridgeTokenOutInfo = ({
tokenAddress: _token.address,
fromChainId: _fromChainId,
receiveNativeToken: _receiveNativeToken,
receiveUsds: _receiveUsds,
})

// if tokenOutInfo address is ZERO_ADDRESS is a new token on the other chain and we need to handle it
Expand Down
22 changes: 22 additions & 0 deletions app/src/hooks/contracts/useForeignXdaiErc20Address.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useContractInstance } from '../useContractInstance'
import { Chains } from '@/src/constants/config/chains'
import { ForeignBridgeErcToNative, ForeignBridgeErcToNative__factory } from '@/types/typechain'
import { useContractCall } from '../useContractCall'

export const useForeignXdaiErc20Address = () => {
const foreignXDAI = useContractInstance(
ForeignBridgeErcToNative__factory,
'XDAIBridge',
Chains.mainnet,
)

const erc20AddressCalls = [foreignXDAI.erc20token] as const
const [{ data: foreignXDAIContext }] = useContractCall<
ForeignBridgeErcToNative,
typeof erc20AddressCalls
>(erc20AddressCalls, [[]], 'foreignXDAIContext')

return {
foreignXdaiErc20Token: foreignXDAIContext?.[0],
}
}
7 changes: 6 additions & 1 deletion app/src/hooks/useSanitizedQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ const sanitizeQuery = (query: ParsedUrlQuery, tokensByNetwork: TokensByNetwork):

export const useSanitizedQuery = (tokensByNetwork: TokensByNetwork) => {
const router = useRouter()

return useMemo(
() => sanitizeQuery(router.query, { ...tokensByNetwork, ...tokensException }),
() =>
sanitizeQuery(router.query, {
[1]: [...tokensByNetwork[1], ...(tokensException[1] || [])],
[100]: [...tokensByNetwork[100], ...(tokensException[100] || [])],
}),
[router.query, tokensByNetwork],
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,6 @@ const Wrapper = styled.div`
width: 100%;
`

// const Value = styled.span<{ disabled?: boolean }>`
// font-size: 1.5rem;
// font-weight: 500;
// margin-left: auto;
// opacity: ${({ disabled }) => (disabled ? 0.7 : 1)};

// @media (min-width: ${({ theme }) => theme.breakPoints.tabletLandscapeStart}) {
// font-size: 1.6rem;
// font-weight: 600;
// }
// `

interface IOption {
disabled?: boolean
icon?: string
Expand All @@ -35,19 +23,21 @@ interface Props {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
options: IOption[]
optionsId: string
value: string
}

export const ReceiveNativeTokenSwitcher = ({
export const ReceiveTokenSwitcher = ({
onChange,
options,
optionsId,
value,
...restProps
}: Props) => {
return (
<Wrapper {...restProps}>
{options.map(({ disabled, icon, label, name }, index) => (
<TokenSelectButton
defaultChecked={index === 0}
checked={value === label}
disabled={disabled}
icon={icon}
id={optionsId}
Expand Down
12 changes: 11 additions & 1 deletion app/src/pagePartials/bridge/bridgeForm/ReceivedTokenInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ export const ReceivedTokenInfo: React.FC<{
fromChainId: ChainsValues
toChainId: ChainsValues
setReceiveNativeToken: (receiveNative: boolean) => void
setReceiveUsds: (receiveUsds: boolean) => void
token: Token | undefined
amountBN: BigNumber
tokenOut?: Token
}> = genericSuspense(
({ amountBN, fromChainId, setReceiveNativeToken, toChainId, token, tokenOut }) => {
({
amountBN,
fromChainId,
setReceiveNativeToken,
setReceiveUsds,
toChainId,
token,
tokenOut,
}) => {
return (
<>
{!token || !tokenOut ? (
Expand All @@ -22,6 +31,7 @@ export const ReceivedTokenInfo: React.FC<{
amount={amountBN}
fromChainId={fromChainId}
setReceiveNativeToken={setReceiveNativeToken}
setReceiveUsds={setReceiveUsds}
toChainId={toChainId}
token={token}
tokenOut={tokenOut}
Expand Down
20 changes: 11 additions & 9 deletions app/src/pagePartials/bridge/bridgeForm/TokenDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import { isSameString } from '@/src/utils/tools'
import { Spinner } from '@/src/components/loading/Spinner'
import { ERC165__factory } from '@/types/typechain/factories/ERC165__factory'
import { USDCe_GNOSIS, ZERO_ADDRESS } from '@/src/constants/misc'
import { NATIVE_TOKEN_ADDRESS } from '@/src/constants/config/common'
import { useUserTokenListBalances } from '@/src/hooks/bridge/useUserTokenListBalances'
import { useWeb3Connection } from '@/src/providers/web3ConnectionProvider'
import { fromBN } from '@/src/utils/bigNumber'
import { formatNumber } from '@/src/utils/format'
import { usdsToken } from '@/src/constants/usdsToken'

const BaseChevronDown = ({ ...restProps }) => (
<svg
Expand Down Expand Up @@ -314,6 +314,7 @@ const Dropdown: React.FC<Props> = ({
]
: [],
)
.concat(fromChainId === Chains.mainnet ? [usdsToken] : [])

const _filteredTokens = orderBy(
value
Expand Down Expand Up @@ -369,16 +370,17 @@ const Dropdown: React.FC<Props> = ({
const filteredTokens = Object.values(_tokens)
.map((_t) => tokensByChain.find((token) => isSameString(get(token, key), _t.address)))
.filter((token): token is Token => !!token)
.concat(
tokensByChain.find((item) => isSameString(item.address, NATIVE_TOKEN_ADDRESS)) as Token,
)

// Sort the filtered tokens according to their position in the _tokens array
const orderedTokens = filteredTokens
.sort(
(a, b) => symbols.indexOf(a.symbol.toUpperCase()) - symbols.indexOf(b.symbol.toUpperCase()),
)
.slice(0, 10)
const orderedTokens = [
...(fromChainId === Chains.mainnet ? [usdsToken] : []),
...filteredTokens
.sort(
(a, b) =>
symbols.indexOf(a.symbol.toUpperCase()) - symbols.indexOf(b.symbol.toUpperCase()),
)
.slice(0, 10),
]

setTopTokens(orderedTokens)
}, [ambTokensByNetwork, fromChainId, toChainId])
Expand Down
Loading