Skip to content

Commit d15939a

Browse files
authored
Merge pull request #5237 from swaponline/fix-quickswap-api
Fix: Quickswap
2 parents 2e37034 + 0b7fa95 commit d15939a

File tree

13 files changed

+453
-143
lines changed

13 files changed

+453
-143
lines changed

src/common/utils/request.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ const sendRequest = (options) => {
112112
const opts = { ...defaultOptions, ...options }
113113
const req = request[opts.method](opts.endpoint)
114114

115-
// req.set({
116-
// 'Content-Type': opts.formData ? 'application/x-www-form-urlencoded; charset=UTF-8' : 'application/json',
117-
// ...(opts.headers || {}),
118-
// })
115+
if (opts.headers) {
116+
req.set({
117+
...opts.headers,
118+
})
119+
}
119120

120121
if (opts.timeout) {
121122
req.timeout({

src/front/config/mainnet/api.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export default {
44
zeroxPolygon: 'https://polygon.api.0x.org',
55
zeroxFantom: 'https://fantom.api.0x.org',
66
zeroxAvalanche: 'https://avalanche.api.0x.org',
7+
zeroxArbitrum: 'https://arbitrum.api.0x.org',
78
oneinch: 'https://api.1inch.exchange/v3.0',
89
limitOrders: 'https://limit-orders.1inch.exchange/v1.0',
910
horizon: 'https://horizon.stellar.org',

src/front/config/mainnet/swapContract.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default {
88
protectedBtcKey: '025c8ee352e8b0d12aecd8b3d9ac3bd93cae1b2cc5de7ac56c2995ab506ac800bd',
99
btcPinKey: '032aec5d20f9a0bb913a9835330259748392927c9a812299c4498a9e2ed3e78d3f',
1010
zerox: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
11-
11+
zeroxFantom: '0xdef189deaef76e379df891899eb5a00a94cbc250',
1212
uniswapRouter: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', // Ethereum
1313
uniswapFactory: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f',
1414
pancakeswapRouter: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // BSC

src/front/config/testnet/api.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export default {
2-
zeroxRopsten: 'https://ropsten.api.0x.org',
2+
zeroxSepolia: 'https://sepolia.api.0x.org',
3+
zeroxMumbai: 'https://mumbai.api.0x.org',
34
oneinch: 'https://api.1inch.exchange/v3.0',
45
limitOrders: 'https://limit-orders.1inch.exchange/v1.0',
56
horizon: 'https://horizon-testnet.stellar.org',

src/front/config/testnet/swapContract.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export default {
99
reputationOracle: '0x6260B5ef52d72732674fF4BDE3B37a4222dB1785',
1010
protectedBtcKey: '023d894571a253b87868db7d54a8b583e0c8ce53b484af8a0b0390b7722975cfaa',
1111
btcPinKey: '02094916ddab5abf215a49422a71be54ceb92c3d8114909048fc45ee90acdb5b32',
12-
12+
zeroxSepolia: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
13+
zeroxMumbai: '0xf471d32cb40837bf24529fcf17418fc1a4807626',
1314
uniswapRouter: '0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506', // Rinkeby
1415
uniswapFactory: '0xc35DADB65012eC5796536bD9864eD8773aBc74C4',
1516
pancakeswapRouter: '0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3', // BSC testnet

src/front/shared/pages/Exchange/QuickSwap/Feedback.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl'
33
import CSSModules from 'react-css-modules'
44
import styles from './index.scss'
55
import { BlockReasons, Actions } from './types'
6-
import { API_NAME } from './constants'
6+
import { SWAP_API } from './constants'
77

88
function Feedback(props) {
99
const {
@@ -25,7 +25,7 @@ function Feedback(props) {
2525

2626
return (
2727
<section>
28-
{!isSourceMode && !API_NAME[network?.networkVersion] ? (
28+
{!isSourceMode && !SWAP_API[network?.networkVersion] ? (
2929
<p styleName="dangerousNotice">
3030
<FormattedMessage
3131
id="aggregatorCannotUseThisNetwork"

src/front/shared/pages/Exchange/QuickSwap/Footer.tsx

+58-14
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,43 @@
11
import { FormattedMessage } from 'react-intl'
2+
import { useState } from 'react'
23
import CSSModules from 'react-css-modules'
34
import styles from './index.scss'
45
import utils from 'common/utils'
56
import ADDRESSES from 'common/helpers/constants/ADDRESSES'
67
import actions from 'redux/actions'
78
import { feedback, externalConfig, constants, transactions, routing } from 'helpers'
89
import { ComponentState, BlockReasons, Actions, Direction } from './types'
9-
import { GWEI_DECIMALS, COIN_DECIMALS, LIQUIDITY_SOURCE_DATA, SEC_PER_MINUTE } from './constants'
10+
import {
11+
SWAP_API,
12+
GWEI_DECIMALS,
13+
COIN_DECIMALS,
14+
LIQUIDITY_SOURCE_DATA,
15+
SEC_PER_MINUTE,
16+
} from './constants'
1017
import Button from 'components/controls/Button/Button'
18+
import ReviewSwapModal from './ReviewSwapModal'
1119

1220
type FooterProps = {
21+
history: any
1322
parentState: ComponentState
1423
insufficientBalanceA: boolean
1524
insufficientBalanceB: boolean
1625
isSourceMode: boolean
1726
sourceAction: Actions
1827
reportError: (e: IError) => void
19-
resetSwapData: () => void
20-
resetSpendedAmount: () => void
28+
resetSwapData: VoidFunction
29+
resetSpendedAmount: VoidFunction
2130
setBlockReason: (a: BlockReasons) => void
2231
isApiRequestBlocking: () => boolean
2332
setPending: (a: boolean) => void
24-
onInputDataChange: () => void
33+
onInputDataChange: VoidFunction
34+
finalizeApiSwapData: () => Promise<void>
2535
baseChainWallet: IUniversalObj
2636
}
2737

2838
function Footer(props: FooterProps) {
2939
const {
40+
history,
3041
parentState,
3142
isSourceMode,
3243
sourceAction,
@@ -40,6 +51,7 @@ function Footer(props: FooterProps) {
4051
setPending,
4152
baseChainWallet,
4253
onInputDataChange,
54+
finalizeApiSwapData,
4355
} = props
4456
const {
4557
blockReason,
@@ -60,12 +72,22 @@ function Footer(props: FooterProps) {
6072
error,
6173
slippage,
6274
currentLiquidityPair,
75+
swapFee,
76+
serviceFee,
77+
fiat,
6378
} = parentState
6479

80+
const [finalizeSwap, setFinalizeSwap] = useState<boolean>(false)
81+
82+
const startSwapReview = async () => {
83+
setFinalizeSwap(true)
84+
await finalizeApiSwapData()
85+
}
86+
6587
const approve = async (direction) => {
66-
const spender = isSourceMode
88+
const spender: `0x${number}` = isSourceMode
6789
? LIQUIDITY_SOURCE_DATA[network.networkVersion]?.router
68-
: externalConfig.swapContract.zerox
90+
: externalConfig.swapContract[SWAP_API[network.networkVersion].spender]
6991

7092
let wallet = fromWallet
7193
let amount = spendedAmount
@@ -97,6 +119,10 @@ function Footer(props: FooterProps) {
97119

98120
const apiSwap = async () => {
99121
if (isSourceMode) return
122+
if (!swapData) throw new Error('No swap data. Can not complete swap')
123+
if (swapData.to !== externalConfig.swapContract[SWAP_API[network.networkVersion].spender]) {
124+
return console.log('%c0x constant proxy is not equal to swap transaction proxy', 'color:red')
125+
}
100126

101127
const baseCurrency = fromWallet.standard ? fromWallet.baseCurrency : fromWallet.currency
102128
const assetName = fromWallet.standard ? fromWallet.tokenKey : fromWallet.currency
@@ -107,10 +133,6 @@ function Footer(props: FooterProps) {
107133
setPending(true)
108134

109135
try {
110-
if (!swapData) {
111-
throw new Error('No swap data. Can not complete swap')
112-
}
113-
114136
if (gasLimit) swapData.gas = gasLimit
115137
if (gasPrice) swapData.gasPrice = utils.amount.formatWithDecimals(gasPrice, GWEI_DECIMALS)
116138

@@ -120,7 +142,6 @@ function Footer(props: FooterProps) {
120142

121143
if (txHash) {
122144
const txInfoUrl = transactions.getTxRouter(assetName.toLowerCase(), txHash)
123-
124145
routing.redirectTo(txInfoUrl)
125146
}
126147

@@ -131,6 +152,7 @@ function Footer(props: FooterProps) {
131152
}
132153

133154
setPending(false)
155+
setFinalizeSwap(false)
134156
}
135157

136158
const directSwap = async () => {
@@ -227,7 +249,11 @@ function Footer(props: FooterProps) {
227249

228250
const doNotMakeApiRequest = isApiRequestBlocking()
229251

230-
const commonBlockReasons = isPending || (blockReason !== BlockReasons.NotApproved && !!error && (!error.message?.match('transfer amount exceeds allowance')))
252+
const commonBlockReasons =
253+
isPending ||
254+
(blockReason !== BlockReasons.NotApproved &&
255+
!!error &&
256+
!error.message?.match('transfer amount exceeds allowance'))
231257
const formFilled = !!spendedAmount && !!receivedAmount
232258

233259
const approvingDoesNotMakeSense =
@@ -252,6 +278,24 @@ function Footer(props: FooterProps) {
252278

253279
return (
254280
<div styleName="footer">
281+
{finalizeSwap && (
282+
<ReviewSwapModal
283+
isPending={isPending}
284+
data={swapData}
285+
onSwap={apiSwap}
286+
onClose={() => setFinalizeSwap(false)}
287+
history={history}
288+
swapFee={swapFee}
289+
fiat={fiat}
290+
serviceFee={serviceFee}
291+
slippage={slippage}
292+
network={network}
293+
spendedAmount={spendedAmount}
294+
baseChainWallet={baseChainWallet}
295+
fromWallet={fromWallet}
296+
toWallet={toWallet}
297+
/>
298+
)}
255299
{needApproveA ? (
256300
<Button
257301
pending={isPending}
@@ -281,8 +325,8 @@ function Footer(props: FooterProps) {
281325
/>
282326
</Button>
283327
) : !isSourceMode ? (
284-
<Button pending={isPending} disabled={!apiSwapIsAvailable} onClick={apiSwap} brand>
285-
<FormattedMessage id="swap" defaultMessage="Swap" />
328+
<Button pending={isPending} disabled={!apiSwapIsAvailable} onClick={startSwapReview} brand>
329+
<FormattedMessage id="reviewSwap" defaultMessage="Review swap" />
286330
</Button>
287331
) : sourceAction === Actions.Swap ? (
288332
<Button pending={isPending} disabled={!directSwapIsAvailable} onClick={directSwap} brand>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { FormattedMessage } from 'react-intl'
2+
import { useState } from 'react'
3+
import { Modal } from 'components/modal'
4+
import Button from 'components/controls/Button/Button'
5+
import UserInfo from './UserInfo'
6+
import { SwapInfo, SwapData } from './types'
7+
8+
interface Props {
9+
onSwap: VoidFunction
10+
onClose: VoidFunction
11+
history: any,
12+
isPending: boolean,
13+
data: SwapData | undefined
14+
}
15+
16+
export default function ReviewSwapModal(props: Props & SwapInfo) {
17+
const {
18+
isPending,
19+
data,
20+
onSwap,
21+
onClose,
22+
history,
23+
swapFee,
24+
fiat,
25+
serviceFee,
26+
slippage,
27+
network,
28+
spendedAmount,
29+
baseChainWallet,
30+
fromWallet,
31+
toWallet,
32+
} = props
33+
34+
const [isSwapStarted, setIsSwapStarted] = useState(false)
35+
36+
const startSwap = () => {
37+
setIsSwapStarted(true)
38+
onSwap()
39+
}
40+
41+
return (
42+
<Modal
43+
name={'Preview swap'}
44+
title={<FormattedMessage id="previewSwap" defaultMessage="Preview swap" />}
45+
onClose={onClose}
46+
showCloseButton
47+
>
48+
<div className="swapPreviewWrapper">
49+
{!isPending && (
50+
<UserInfo
51+
history={history}
52+
isSourceMode={false}
53+
slippage={slippage}
54+
network={network}
55+
swapData={data}
56+
swapFee={swapFee}
57+
spendedAmount={spendedAmount}
58+
baseChainWallet={baseChainWallet}
59+
fromWallet={fromWallet}
60+
toWallet={toWallet}
61+
fiat={fiat}
62+
serviceFee={serviceFee}
63+
/>
64+
)}
65+
{isSwapStarted && (
66+
<p className="swapInProgressMessage">
67+
<FormattedMessage id="waitUntilSwapComplete" defaultMessage="Please wait until the swap is complete" />
68+
</p>
69+
)}
70+
<Button pending={isPending} disabled={isPending} onClick={startSwap} brand fullWidth>
71+
<FormattedMessage id="swap" defaultMessage="Swap" />
72+
</Button>
73+
</div>
74+
</Modal>
75+
)
76+
}

src/front/shared/pages/Exchange/QuickSwap/constants.ts

+33-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,39 @@ export const GWEI_DECIMALS = 9
1111
export const MAX_PERCENT = 100
1212
export const SEC_PER_MINUTE = 60
1313

14-
export const API_NAME = {
15-
1: 'zeroxEthereum',
16-
56: 'zeroxBsc',
17-
137: 'zeroxPolygon',
18-
250: 'zeroxFantom',
19-
43114: 'zeroxAvalanche',
14+
export const SWAP_API = {
15+
1: {
16+
name: 'zeroxEthereum',
17+
spender: 'zerox',
18+
},
19+
11155111: {
20+
name: 'zeroxSepolia',
21+
spender: 'zeroxSepolia',
22+
},
23+
56: {
24+
name: 'zeroxBsc',
25+
spender: 'zerox',
26+
},
27+
137: {
28+
name: 'zeroxPolygon',
29+
spender: 'zerox',
30+
},
31+
80001: {
32+
name: 'zeroxMumbai',
33+
spender: 'zeroxMumbai',
34+
},
35+
250: {
36+
name: 'zeroxFantom',
37+
spender: 'zeroxFantom',
38+
},
39+
43114: {
40+
name: 'zeroxAvalanche',
41+
spender: 'zerox',
42+
},
43+
42161: {
44+
name: 'zeroxArbitrum',
45+
spender: 'zerox',
46+
},
2047
}
2148

2249
export const API_GAS_LIMITS = {

src/front/shared/pages/Exchange/QuickSwap/index.scss

+10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ $maxWidth: 38em;
216216
margin-bottom: 0.5rem;
217217
}
218218

219+
.swapPreviewWrapper {
220+
max-width: $maxWidth;
221+
}
222+
223+
.swapInProgressMessage {
224+
width: 100%;
225+
padding: 30px 0;
226+
text-align: center;
227+
}
228+
219229
@media all and (max-width: 500px) {
220230
.newTokenInstruction {
221231
font-size: 0.95rem;

0 commit comments

Comments
 (0)