Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
interface
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LuckySwap
interface
Commits
60536862
Unverified
Commit
60536862
authored
Apr 24, 2021
by
Moody Salem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
surface the best v3 route to the swap page
parent
ca2b84ec
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
107 additions
and
22 deletions
+107
-22
useBestV3Route.ts
src/hooks/useBestV3Route.ts
+80
-14
useV2SwapCallback.ts
src/hooks/useV2SwapCallback.ts
+1
-1
useV2Trade.ts
src/hooks/useV2Trade.ts
+1
-1
index.tsx
src/pages/Swap/index.tsx
+10
-3
hooks.ts
src/state/swap/hooks.ts
+15
-3
isTradeBetter.ts
src/utils/isTradeBetter.ts
+0
-0
No files found.
src/hooks/useBestV3Route.ts
View file @
60536862
...
@@ -14,37 +14,43 @@ import { BigNumber, utils } from 'ethers'
...
@@ -14,37 +14,43 @@ import { BigNumber, utils } from 'ethers'
* @param route the v3 path to convert to an encoded path
* @param route the v3 path to convert to an encoded path
* @param chainId the current chain ID, used to wrap the route's input currency
* @param chainId the current chain ID, used to wrap the route's input currency
*/
*/
function
routeToPath
(
route
:
Route
,
chainId
:
ChainId
):
string
{
function
routeToPath
(
route
:
Route
,
chainId
:
ChainId
,
exactIn
:
boolean
):
string
{
const
firstInputToken
=
wrappedCurrency
(
route
.
input
,
chainId
)
const
firstInputToken
=
wrappedCurrency
(
route
.
input
,
chainId
)
if
(
!
firstInputToken
)
throw
new
Error
(
'
Could not wrap input currency
'
)
if
(
!
firstInputToken
)
throw
new
Error
(
'
Could not wrap input currency
'
)
return
route
.
pools
.
reduce
(
const
{
path
,
types
}
=
route
.
pools
.
reduce
(
(
(
{
inputToken
,
path
}:
{
inputToken
:
Token
;
path
:
string
},
{
inputToken
,
path
,
types
}:
{
inputToken
:
Token
;
path
:
(
string
|
number
)[];
types
:
string
[]
},
pool
:
Pool
,
pool
:
Pool
,
index
index
):
{
inputToken
:
Token
;
path
:
string
}
=>
{
):
{
inputToken
:
Token
;
path
:
(
string
|
number
)[];
types
:
string
[]
}
=>
{
const
outputToken
:
Token
=
pool
.
token0
.
equals
(
inputToken
)
?
pool
.
token1
:
pool
.
token0
const
outputToken
:
Token
=
pool
.
token0
.
equals
(
inputToken
)
?
pool
.
token1
:
pool
.
token0
if
(
index
===
0
)
{
if
(
index
===
0
)
{
return
{
return
{
inputToken
:
outputToken
,
inputToken
:
outputToken
,
path
:
utils
.
solidityPack
(
types
:
[
'
address
'
,
'
uint24
'
,
'
address
'
],
[
'
address
'
,
'
uint24
'
,
'
address
'
],
path
:
[
inputToken
.
address
,
pool
.
fee
,
outputToken
.
address
],
[
inputToken
.
address
,
pool
.
fee
,
outputToken
.
address
]
),
}
}
}
else
{
}
else
{
return
{
return
{
inputToken
:
outputToken
,
inputToken
:
outputToken
,
path
:
`
${
path
}${
utils
.
solidityPack
([
'
uint24
'
,
'
address
'
],
[
pool
.
fee
,
outputToken
.
address
]).
slice
(
2
)}
`
,
types
:
[...
types
,
'
uint24
'
,
'
address
'
],
path
:
[...
path
,
pool
.
fee
,
outputToken
.
address
],
}
}
}
}
},
},
{
inputToken
:
firstInputToken
,
path
:
''
}
{
inputToken
:
firstInputToken
,
path
:
[],
types
:
[]
}
).
path
)
return
exactIn
?
utils
.
solidityPack
(
types
,
path
)
:
utils
.
solidityPack
(
types
.
reverse
(),
path
.
reverse
())
}
}
/**
* Returns the best route for a given exact input swap, and the amount received for it
* @param amountIn the amount to swap in
* @param currencyOut the desired output currency
*/
export
function
useBestV3RouteExactIn
(
export
function
useBestV3RouteExactIn
(
amountIn
?:
CurrencyAmount
,
amountIn
?:
CurrencyAmount
,
currencyOut
?:
Currency
currencyOut
?:
Currency
...
@@ -54,14 +60,14 @@ export function useBestV3RouteExactIn(
...
@@ -54,14 +60,14 @@ export function useBestV3RouteExactIn(
const
routes
=
useAllV3Routes
(
amountIn
?.
currency
,
currencyOut
)
const
routes
=
useAllV3Routes
(
amountIn
?.
currency
,
currencyOut
)
const
paths
=
useMemo
(()
=>
{
const
paths
=
useMemo
(()
=>
{
if
(
!
chainId
)
return
[]
if
(
!
chainId
)
return
[]
return
routes
.
map
((
route
)
=>
routeToPath
(
route
,
chainId
))
return
routes
.
map
((
route
)
=>
routeToPath
(
route
,
chainId
,
true
))
},
[
chainId
,
routes
])
},
[
chainId
,
routes
])
const
quoteInputs
=
useMemo
(()
=>
{
const
quote
ExactIn
Inputs
=
useMemo
(()
=>
{
return
paths
.
map
((
path
)
=>
[
path
,
amountIn
?
`0x
${
amountIn
.
raw
.
toString
(
16
)}
`
:
undefined
])
return
paths
.
map
((
path
)
=>
[
path
,
amountIn
?
`0x
${
amountIn
.
raw
.
toString
(
16
)}
`
:
undefined
])
},
[
amountIn
,
paths
])
},
[
amountIn
,
paths
])
const
quotesResults
=
useSingleContractMultipleData
(
quoter
,
'
quoteExactInput
'
,
quoteInputs
)
const
quotesResults
=
useSingleContractMultipleData
(
quoter
,
'
quoteExactInput
'
,
quote
ExactIn
Inputs
)
return
useMemo
(()
=>
{
return
useMemo
(()
=>
{
const
{
bestRoute
,
amountOut
}
=
quotesResults
.
reduce
(
const
{
bestRoute
,
amountOut
}
=
quotesResults
.
reduce
(
...
@@ -97,3 +103,63 @@ export function useBestV3RouteExactIn(
...
@@ -97,3 +103,63 @@ export function useBestV3RouteExactIn(
}
}
},
[
currencyOut
,
quotesResults
,
routes
])
},
[
currencyOut
,
quotesResults
,
routes
])
}
}
/**
* Returns the best route for a given exact output swap, and the amount required for it
* @param currencyIn the current to swap in
* @param amountOut the desired amount out
*/
export
function
useBestV3RouteExactOut
(
currencyIn
?:
Currency
,
amountOut
?:
CurrencyAmount
):
{
route
:
Route
;
amountIn
:
CurrencyAmount
}
|
null
{
const
{
chainId
}
=
useActiveWeb3React
()
const
quoter
=
useV3Quoter
()
const
routes
=
useAllV3Routes
(
currencyIn
,
amountOut
?.
currency
)
const
paths
=
useMemo
(()
=>
{
if
(
!
chainId
)
return
[]
return
routes
.
map
((
route
)
=>
routeToPath
(
route
,
chainId
,
true
))
},
[
chainId
,
routes
])
const
quoteExactOutInputs
=
useMemo
(()
=>
{
const
amountOutEncoded
=
amountOut
?
`0x
${
amountOut
.
raw
.
toString
(
16
)}
`
:
undefined
return
paths
.
map
((
path
)
=>
[
path
,
amountOutEncoded
])
},
[
amountOut
,
paths
])
const
quotesResults
=
useSingleContractMultipleData
(
quoter
,
'
quoteExactInput
'
,
quoteExactOutInputs
)
return
useMemo
(()
=>
{
const
{
bestRoute
,
amountIn
}
=
quotesResults
.
reduce
(
(
best
:
{
bestRoute
:
Route
|
null
;
amountIn
:
BigNumber
|
null
},
{
valid
,
loading
,
result
},
i
)
=>
{
if
(
loading
||
!
valid
||
!
result
)
return
best
if
(
best
.
amountIn
===
null
)
{
return
{
bestRoute
:
routes
[
i
],
amountIn
:
result
.
amountIn
,
}
}
else
if
(
best
.
amountIn
.
gt
(
result
.
amountIn
))
{
return
{
bestRoute
:
routes
[
i
],
amountIn
:
result
.
amountIn
,
}
}
return
best
},
{
bestRoute
:
null
,
amountIn
:
null
,
}
)
if
(
!
bestRoute
||
!
amountIn
)
return
null
return
{
route
:
bestRoute
,
amountIn
:
currencyIn
instanceof
Token
?
new
TokenAmount
(
currencyIn
,
amountIn
.
toString
())
:
CurrencyAmount
.
ether
(
amountIn
.
toString
()),
}
},
[
currencyIn
,
quotesResults
,
routes
])
}
src/hooks/useSwapCallback.ts
→
src/hooks/use
V2
SwapCallback.ts
View file @
60536862
...
@@ -88,7 +88,7 @@ function useSwapCallArguments(
...
@@ -88,7 +88,7 @@ function useSwapCallArguments(
// returns a function that will execute a swap, if the parameters are all valid
// returns a function that will execute a swap, if the parameters are all valid
// and the user has approved the slippage adjusted input amount for the trade
// and the user has approved the slippage adjusted input amount for the trade
export
function
useSwapCallback
(
export
function
use
V2
SwapCallback
(
trade
:
Trade
|
undefined
,
// trade to execute, required
trade
:
Trade
|
undefined
,
// trade to execute, required
allowedSlippage
:
number
=
INITIAL_ALLOWED_SLIPPAGE
,
// in bips
allowedSlippage
:
number
=
INITIAL_ALLOWED_SLIPPAGE
,
// in bips
recipientAddressOrName
:
string
|
null
// the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
recipientAddressOrName
:
string
|
null
// the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
...
...
src/hooks/useV2Trade.ts
View file @
60536862
...
@@ -2,7 +2,7 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
...
@@ -2,7 +2,7 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import
{
Pair
,
Trade
}
from
'
@uniswap/v2-sdk
'
import
{
Pair
,
Trade
}
from
'
@uniswap/v2-sdk
'
import
{
useMemo
}
from
'
react
'
import
{
useMemo
}
from
'
react
'
import
{
useUserSingleHopOnly
}
from
'
state/user/hooks
'
import
{
useUserSingleHopOnly
}
from
'
state/user/hooks
'
import
{
isTradeBetter
}
from
'
utils/
trades
'
import
{
isTradeBetter
}
from
'
utils/
isTradeBetter
'
import
{
BETTER_TRADE_LESS_HOPS_THRESHOLD
}
from
'
../constants
'
import
{
BETTER_TRADE_LESS_HOPS_THRESHOLD
}
from
'
../constants
'
import
{
useAllCurrencyCombinations
}
from
'
./useAllCurrencyCombinations
'
import
{
useAllCurrencyCombinations
}
from
'
./useAllCurrencyCombinations
'
import
{
PairState
,
useV2Pairs
}
from
'
./useV2Pairs
'
import
{
PairState
,
useV2Pairs
}
from
'
./useV2Pairs
'
...
...
src/pages/Swap/index.tsx
View file @
60536862
...
@@ -28,7 +28,7 @@ import { useCurrency, useAllTokens } from '../../hooks/Tokens'
...
@@ -28,7 +28,7 @@ import { useCurrency, useAllTokens } from '../../hooks/Tokens'
import
{
ApprovalState
,
useApproveCallbackFromTrade
}
from
'
../../hooks/useApproveCallback
'
import
{
ApprovalState
,
useApproveCallbackFromTrade
}
from
'
../../hooks/useApproveCallback
'
import
useENSAddress
from
'
../../hooks/useENSAddress
'
import
useENSAddress
from
'
../../hooks/useENSAddress
'
import
{
useIsSwapUnsupported
}
from
'
../../hooks/useIsSwapUnsupported
'
import
{
useIsSwapUnsupported
}
from
'
../../hooks/useIsSwapUnsupported
'
import
{
use
SwapCallback
}
from
'
../../hooks/use
SwapCallback
'
import
{
use
V2SwapCallback
}
from
'
../../hooks/useV2
SwapCallback
'
import
useToggledVersion
,
{
Version
}
from
'
../../hooks/useToggledVersion
'
import
useToggledVersion
,
{
Version
}
from
'
../../hooks/useToggledVersion
'
import
useWrapCallback
,
{
WrapType
}
from
'
../../hooks/useWrapCallback
'
import
useWrapCallback
,
{
WrapType
}
from
'
../../hooks/useWrapCallback
'
import
{
useToggleSettingsMenu
,
useWalletModalToggle
}
from
'
../../state/application/hooks
'
import
{
useToggleSettingsMenu
,
useWalletModalToggle
}
from
'
../../state/application/hooks
'
...
@@ -89,7 +89,14 @@ export default function Swap({ history }: RouteComponentProps) {
...
@@ -89,7 +89,14 @@ export default function Swap({ history }: RouteComponentProps) {
// swap state
// swap state
const
{
independentField
,
typedValue
,
recipient
}
=
useSwapState
()
const
{
independentField
,
typedValue
,
recipient
}
=
useSwapState
()
const
{
v2Trade
,
currencyBalances
,
parsedAmount
,
currencies
,
inputError
:
swapInputError
}
=
useDerivedSwapInfo
()
const
{
v2Trade
,
currencyBalances
,
parsedAmount
,
currencies
,
v3Route
,
inputError
:
swapInputError
,
}
=
useDerivedSwapInfo
()
const
{
wrapType
,
execute
:
onWrap
,
inputError
:
wrapInputError
}
=
useWrapCallback
(
const
{
wrapType
,
execute
:
onWrap
,
inputError
:
wrapInputError
}
=
useWrapCallback
(
currencies
[
Field
.
INPUT
],
currencies
[
Field
.
INPUT
],
...
@@ -183,7 +190,7 @@ export default function Swap({ history }: RouteComponentProps) {
...
@@ -183,7 +190,7 @@ export default function Swap({ history }: RouteComponentProps) {
const
atMaxAmountInput
=
Boolean
(
maxAmountInput
&&
parsedAmounts
[
Field
.
INPUT
]?.
equalTo
(
maxAmountInput
))
const
atMaxAmountInput
=
Boolean
(
maxAmountInput
&&
parsedAmounts
[
Field
.
INPUT
]?.
equalTo
(
maxAmountInput
))
// the callback to execute the swap
// the callback to execute the swap
const
{
callback
:
swapCallback
,
error
:
swapCallbackError
}
=
useSwapCallback
(
trade
,
allowedSlippage
,
recipient
)
const
{
callback
:
swapCallback
,
error
:
swapCallbackError
}
=
use
V2
SwapCallback
(
trade
,
allowedSlippage
,
recipient
)
const
{
priceImpactWithoutFee
}
=
computeTradePriceBreakdown
(
trade
)
const
{
priceImpactWithoutFee
}
=
computeTradePriceBreakdown
(
trade
)
...
...
src/state/swap/hooks.ts
View file @
60536862
import
{
useBestV3RouteExactIn
}
from
'
../../hooks/useBestV3Route
'
import
{
Route
}
from
'
@uniswap/v3-sdk
'
import
{
useBestV3RouteExactIn
,
useBestV3RouteExactOut
}
from
'
../../hooks/useBestV3Route
'
import
useENS
from
'
../../hooks/useENS
'
import
useENS
from
'
../../hooks/useENS
'
import
{
parseUnits
}
from
'
@ethersproject/units
'
import
{
parseUnits
}
from
'
@ethersproject/units
'
import
{
Currency
,
CurrencyAmount
,
ETHER
,
Token
,
TokenAmount
}
from
'
@uniswap/sdk-core
'
import
{
Currency
,
CurrencyAmount
,
ETHER
,
Token
,
TokenAmount
}
from
'
@uniswap/sdk-core
'
...
@@ -112,6 +113,16 @@ export function useDerivedSwapInfo(): {
...
@@ -112,6 +113,16 @@ export function useDerivedSwapInfo(): {
parsedAmount
:
CurrencyAmount
|
undefined
parsedAmount
:
CurrencyAmount
|
undefined
v2Trade
:
Trade
|
undefined
v2Trade
:
Trade
|
undefined
inputError
?:
string
inputError
?:
string
v3Route
:
|
{
route
:
Route
amountIn
:
CurrencyAmount
}
|
{
route
:
Route
amountOut
:
CurrencyAmount
}
|
undefined
}
{
}
{
const
{
account
}
=
useActiveWeb3React
()
const
{
account
}
=
useActiveWeb3React
()
...
@@ -140,10 +151,10 @@ export function useDerivedSwapInfo(): {
...
@@ -140,10 +151,10 @@ export function useDerivedSwapInfo(): {
const
bestTradeExactOut
=
useV2TradeExactOut
(
inputCurrency
??
undefined
,
!
isExactIn
?
parsedAmount
:
undefined
)
const
bestTradeExactOut
=
useV2TradeExactOut
(
inputCurrency
??
undefined
,
!
isExactIn
?
parsedAmount
:
undefined
)
const
bestRouteExactInV3
=
useBestV3RouteExactIn
(
isExactIn
?
parsedAmount
:
undefined
,
outputCurrency
??
undefined
)
const
bestRouteExactInV3
=
useBestV3RouteExactIn
(
isExactIn
?
parsedAmount
:
undefined
,
outputCurrency
??
undefined
)
// todo: do something with this information
const
bestRouteExactOutV3
=
useBestV3RouteExactOut
(
inputCurrency
??
undefined
,
!
isExactIn
?
parsedAmount
:
undefined
)
console
.
log
(
'
best v3 route for the swap
'
,
bestRouteExactInV3
)
const
v2Trade
=
isExactIn
?
bestTradeExactIn
:
bestTradeExactOut
const
v2Trade
=
isExactIn
?
bestTradeExactIn
:
bestTradeExactOut
const
v3Route
=
(
isExactIn
?
bestRouteExactInV3
:
bestRouteExactOutV3
)
??
undefined
const
currencyBalances
=
{
const
currencyBalances
=
{
[
Field
.
INPUT
]:
relevantTokenBalances
[
0
],
[
Field
.
INPUT
]:
relevantTokenBalances
[
0
],
...
@@ -201,6 +212,7 @@ export function useDerivedSwapInfo(): {
...
@@ -201,6 +212,7 @@ export function useDerivedSwapInfo(): {
parsedAmount
,
parsedAmount
,
v2Trade
:
v2Trade
??
undefined
,
v2Trade
:
v2Trade
??
undefined
,
inputError
,
inputError
,
v3Route
,
}
}
}
}
...
...
src/utils/
trades
.ts
→
src/utils/
isTradeBetter
.ts
View file @
60536862
File moved
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment