Skip to content

Commit c383a3f

Browse files
authored
Merge pull request #177 from gnosischain/feat/usds-upgrade-step2
feat: USDS migration step2
2 parents 53a1fa6 + ea06fdc commit c383a3f

13 files changed

Lines changed: 280 additions & 102 deletions

File tree

app/public/images/icons/usds.webp

476 Bytes
Loading

app/src/components/footer/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const ExternalLink = styled.a`
5555
align-items: center;
5656
column-gap: var(--theme-common-space);
5757
display: flex;
58-
font-size: 1.2rem;
58+
font-size: 1.4rem;
5959
text-decoration: none;
6060
6161
&:active {
@@ -106,6 +106,13 @@ export const Footer: React.FC = (props) => {
106106
</ExternalLink>
107107
</Start>
108108
<End>
109+
<ExternalLink
110+
href="https://docs.gnosischain.com/bridges/"
111+
rel="noreferrer"
112+
target="_blank"
113+
>
114+
Documentation
115+
</ExternalLink>
109116
<Link href="/faq">FAQ</Link>
110117
{/* <NextLink href="/privacy" passHref>
111118
<Link>Privacy Policy</Link>

app/src/components/table/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const TR = styled.div<{ $compact?: boolean }>`
4646
row-gap: calc(var(--table-padding-common));
4747
transition: none;
4848
49-
&:hover > * {
49+
&:hover > *:not(:last-child) {
5050
opacity: 0.8;
5151
}
5252

app/src/constants/bridges.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
import { Chains } from './config/chains'
2+
import { contracts } from './config/contracts'
3+
14
export const bridgeConfig = Object.freeze({
25
XDAI: {
36
bridgeProxy: '0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016',
47
governorMultisig: '0x42F38ec5A75acCEc50054671233dfAC9C0E7A3F6',
58
tokens: {
69
dai: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
10+
usds: '0xdc035d45d973e3ec169d2276ddab16f1e407384f',
711
},
812
protocol: {
913
address: '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B',
1014
token: '0xc00e94cb662c3520282e6f5717214004a7f26888',
1115
},
16+
bridgeRouter: contracts.BridgeRouter.address[Chains.mainnet],
1217
},
1318
OMNI: {
1419
bridgeProxy: '0x88ad09518695c6c3712AC10a214bE5109a655671',

app/src/hooks/bridge/useBridgeTokenOutInfo.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const getReceivedTokenInfo = async ({
2727
fromChainId,
2828
omniBridgeInstance,
2929
receiveNativeToken,
30+
receiveUsds,
3031
toChainId,
3132
tokenAddress,
3233
}: {
@@ -35,6 +36,7 @@ const getReceivedTokenInfo = async ({
3536
tokenAddress: string
3637
omniBridgeInstance: HomeOmniMediator
3738
receiveNativeToken: boolean
39+
receiveUsds: boolean
3840
}): Promise<{ tokenOutAddress: string; canReceiveNativeToken?: boolean }> => {
3941
const { isDAI, isFromForeign, isFromHome, isNativeToken } = getBridgeCommonInfo({
4042
fromChainId,
@@ -83,6 +85,12 @@ const getReceivedTokenInfo = async ({
8385

8486
if (isFromHome) {
8587
// xDAI -> DAI
88+
if (receiveUsds) {
89+
return {
90+
tokenOutAddress: USDS_ADDRESS,
91+
}
92+
}
93+
8694
if (isNativeToken) {
8795
return {
8896
tokenOutAddress: chainsConfig[toChainId].bridge.DAI,
@@ -113,10 +121,12 @@ const getReceivedTokenInfo = async ({
113121
export const useBridgeTokenOutInfo = ({
114122
fromChainId,
115123
receiveNativeToken,
124+
receiveUsds,
116125
toChainId,
117126
token,
118127
}: {
119128
receiveNativeToken: boolean
129+
receiveUsds: boolean
120130
toChainId: ChainsValues
121131
fromChainId: ChainsValues
122132
token?: Token
@@ -127,8 +137,10 @@ export const useBridgeTokenOutInfo = ({
127137
const shouldFetch = !!(token && fromChainId && toChainId)
128138

129139
const { data } = useSWR(
130-
shouldFetch ? [token, fromChainId, toChainId, receiveNativeToken, 'bridgeTokenOut'] : null,
131-
async ([_token, _fromChainId, _toChainId, _receiveNativeToken]) => {
140+
shouldFetch
141+
? [token, fromChainId, toChainId, receiveNativeToken, receiveUsds, 'bridgeTokenOut']
142+
: null,
143+
async ([_token, _fromChainId, _toChainId, _receiveNativeToken, _receiveUsds]) => {
132144
if (
133145
_fromChainId === Chains.mainnet &&
134146
_toChainId === Chains.gnosis &&
@@ -161,6 +173,7 @@ export const useBridgeTokenOutInfo = ({
161173
tokenAddress: _token.address,
162174
fromChainId: _fromChainId,
163175
receiveNativeToken: _receiveNativeToken,
176+
receiveUsds: _receiveUsds,
164177
})
165178

166179
// if tokenOutInfo address is ZERO_ADDRESS is a new token on the other chain and we need to handle it

app/src/hooks/useSanitizedQuery.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ const sanitizeQuery = (query: ParsedUrlQuery, tokensByNetwork: TokensByNetwork):
4141

4242
export const useSanitizedQuery = (tokensByNetwork: TokensByNetwork) => {
4343
const router = useRouter()
44+
4445
return useMemo(
45-
() => sanitizeQuery(router.query, { ...tokensByNetwork, ...tokensException }),
46+
() =>
47+
sanitizeQuery(router.query, {
48+
[1]: [...tokensByNetwork[1], ...(tokensException[1] || [])],
49+
[100]: [...tokensByNetwork[100], ...(tokensException[100] || [])],
50+
}),
4651
[router.query, tokensByNetwork],
4752
)
4853
}

app/src/pagePartials/bridge/bridgeForm/ReceiveNativeTokenSwitcher.tsx renamed to app/src/pagePartials/bridge/bridgeForm/ReceiveTokenSwitcher.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,6 @@ const Wrapper = styled.div`
1111
width: 100%;
1212
`
1313

14-
// const Value = styled.span<{ disabled?: boolean }>`
15-
// font-size: 1.5rem;
16-
// font-weight: 500;
17-
// margin-left: auto;
18-
// opacity: ${({ disabled }) => (disabled ? 0.7 : 1)};
19-
20-
// @media (min-width: ${({ theme }) => theme.breakPoints.tabletLandscapeStart}) {
21-
// font-size: 1.6rem;
22-
// font-weight: 600;
23-
// }
24-
// `
25-
2614
interface IOption {
2715
disabled?: boolean
2816
icon?: string
@@ -35,19 +23,21 @@ interface Props {
3523
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
3624
options: IOption[]
3725
optionsId: string
26+
value: string
3827
}
3928

40-
export const ReceiveNativeTokenSwitcher = ({
29+
export const ReceiveTokenSwitcher = ({
4130
onChange,
4231
options,
4332
optionsId,
33+
value,
4434
...restProps
4535
}: Props) => {
4636
return (
4737
<Wrapper {...restProps}>
4838
{options.map(({ disabled, icon, label, name }, index) => (
4939
<TokenSelectButton
50-
defaultChecked={index === 0}
40+
checked={value === label}
5141
disabled={disabled}
5242
icon={icon}
5343
id={optionsId}

app/src/pagePartials/bridge/bridgeForm/ReceivedTokenInfo.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,20 @@ export const ReceivedTokenInfo: React.FC<{
88
fromChainId: ChainsValues
99
toChainId: ChainsValues
1010
setReceiveNativeToken: (receiveNative: boolean) => void
11+
setReceiveUsds: (receiveUsds: boolean) => void
1112
token: Token | undefined
1213
amountBN: BigNumber
1314
tokenOut?: Token
1415
}> = genericSuspense(
15-
({ amountBN, fromChainId, setReceiveNativeToken, toChainId, token, tokenOut }) => {
16+
({
17+
amountBN,
18+
fromChainId,
19+
setReceiveNativeToken,
20+
setReceiveUsds,
21+
toChainId,
22+
token,
23+
tokenOut,
24+
}) => {
1625
return (
1726
<>
1827
{!token || !tokenOut ? (
@@ -22,6 +31,7 @@ export const ReceivedTokenInfo: React.FC<{
2231
amount={amountBN}
2332
fromChainId={fromChainId}
2433
setReceiveNativeToken={setReceiveNativeToken}
34+
setReceiveUsds={setReceiveUsds}
2535
toChainId={toChainId}
2636
token={token}
2737
tokenOut={tokenOut}

app/src/pagePartials/bridge/bridgeForm/TokenOut.tsx

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import { getBridgeCommonInfo } from '@/src/hooks/bridge/utils/getBridgeCommonInf
77
import { Chains, ChainsValues } from '@/src/constants/config/types'
88
import { useBridgeFee } from '@/src/hooks/bridge/useBridgeFee'
99
import { formatUnits } from 'ethers/lib/utils'
10-
import { ReceiveNativeTokenSwitcher } from '@/src/pagePartials/bridge/bridgeForm/ReceiveNativeTokenSwitcher'
10+
import { ReceiveTokenSwitcher } from '@/src/pagePartials/bridge/bridgeForm/ReceiveTokenSwitcher'
1111
import { chainsConfig } from '@/src/constants/config/chains'
1212
import { genericSuspense } from '@/src/components/safeSuspense'
13+
import { NATIVE_TOKEN_ADDRESS } from '@/src/constants/config/common'
14+
import { isSameString } from '@/src/utils/tools'
15+
import React, { useState } from 'react'
1316

1417
const NoTokenSelected = styled.span`
1518
font-size: 1.5rem;
@@ -41,6 +44,19 @@ const wethOptions = [
4144
},
4245
]
4346

47+
const xdaiOptions = [
48+
{
49+
icon: '/images/icons/dai.svg',
50+
label: 'DAI',
51+
name: 'xdai-types',
52+
},
53+
{
54+
icon: '/images/icons/usds.webp',
55+
label: 'USDS',
56+
name: 'xdai-types',
57+
},
58+
]
59+
4460
export const NoTokenOut: React.FC<{ loading?: boolean }> = ({ loading }) => (
4561
<>
4662
<SkeletonLoading
@@ -61,6 +77,7 @@ export const TokenOut: React.FC<{
6177
amount: BigNumber
6278
fromChainId: ChainsValues
6379
setReceiveNativeToken: (receiveNative: boolean) => void
80+
setReceiveUsds: (receiveUsds: boolean) => void
6481
toChainId: ChainsValues
6582
token: Token
6683
tokenOut: Token
@@ -69,6 +86,7 @@ export const TokenOut: React.FC<{
6986
amount,
7087
fromChainId,
7188
setReceiveNativeToken: onReceiveNativeChange,
89+
setReceiveUsds: onReceiveUsdsChange,
7290
toChainId,
7391
token,
7492
tokenOut,
@@ -90,18 +108,37 @@ export const TokenOut: React.FC<{
90108
fromChainId == Chains.gnosis &&
91109
token.address == chainsConfig[Chains.gnosis].bridge.wForeignNative
92110

111+
const showXDaiSwitcher =
112+
fromChainId === Chains.gnosis && isSameString(token.address, NATIVE_TOKEN_ADDRESS)
113+
114+
// Add state for selected option
115+
const [selectedNativeToken, setSelectedNativeToken] = useState(wethOptions[0].label)
116+
const [selectedXDaiToken, setSelectedXDaiToken] = useState(xdaiOptions[0].label)
117+
93118
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
94119
const tokenOutAmount = formatUnits(amount.sub(feeInfo!), tokenOut?.decimals)
95120

96121
return (
97122
<>
98123
{showNativeTokenSwitcher ? (
99-
<ReceiveNativeTokenSwitcher
100-
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
124+
<ReceiveTokenSwitcher
125+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
126+
setSelectedNativeToken(event.target.value)
101127
onReceiveNativeChange(event.target.value === 'ETH')
102-
}
128+
}}
103129
options={wethOptions}
104130
optionsId="ethOptions"
131+
value={selectedNativeToken}
132+
/>
133+
) : showXDaiSwitcher ? (
134+
<ReceiveTokenSwitcher
135+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
136+
setSelectedXDaiToken(event.target.value)
137+
onReceiveUsdsChange(event.target.value === 'USDS')
138+
}}
139+
options={xdaiOptions}
140+
optionsId="xdaiOptions"
141+
value={selectedXDaiToken}
105142
/>
106143
) : (
107144
<>

app/src/pagePartials/bridge/bridgeForm/index.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ const AmountInput = styled(AmountTokenInput)`
121121
margin-right: calc(var(--theme-common-space) * -1);
122122
`
123123

124+
const Info = styled.p`
125+
color: ${({ theme: { colors } }) => colors.textColor};
126+
font-size: 1.4rem;
127+
line-height: 1.4;
128+
margin: 0;
129+
`
130+
124131
const SkeletonCommon: React.FC = () => (
125132
<Wrapper>
126133
<FormWrapper>
@@ -144,6 +151,7 @@ const initialState: BridgeFormState = {
144151
recipient: '',
145152
toChainId: Chains.gnosis,
146153
token: undefined,
154+
receiveUsds: false,
147155
}
148156

149157
const Main = () => {
@@ -231,10 +239,14 @@ const Main = () => {
231239

232240
const isUsdcEth = isSameString(formState.token?.address || '', USDC_ETHEREUM)
233241
const isUsdceGC = isSameString(formState.token?.address || '', USDCe_GNOSIS)
242+
const isXdai =
243+
formState.fromChainId === Chains.gnosis &&
244+
isSameString(formState.token?.address || '', NATIVE_TOKEN_ADDRESS)
234245

235246
const tokenOut = useBridgeTokenOutInfo({
236247
fromChainId: formState.fromChainId,
237248
receiveNativeToken: formState.receiveNativeToken,
249+
receiveUsds: formState.receiveUsds,
238250
toChainId: formState.toChainId,
239251
token: formState.token,
240252
})
@@ -314,11 +326,17 @@ const Main = () => {
314326
setReceiveNativeToken={(receiveNative: boolean) => {
315327
dispatch({ ...formState, receiveNativeToken: receiveNative })
316328
}}
329+
setReceiveUsds={(receiveUsds: boolean) => {
330+
dispatch({ ...formState, receiveUsds: receiveUsds })
331+
}}
317332
toChainId={formState.toChainId}
318333
token={formState.token}
319334
tokenOut={tokenOut}
320335
/>
321336
</BridgedToken>
337+
{isXdai && (
338+
<Info>* Provisional only — you’ll choose between USDS and DAI at claim.</Info>
339+
)}
322340
<RecipientAddress
323341
onChange={(event) => dispatch({ ...formState, recipient: event.target.value })}
324342
recipient={formState.recipient}

0 commit comments

Comments
 (0)