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
c3472764
Unverified
Commit
c3472764
authored
May 03, 2021
by
Noah Zinsmeister
Committed by
GitHub
May 03, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add basic sushi support (#87)
parent
807860aa
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
163 additions
and
30 deletions
+163
-30
Sushi.tsx
src/components/PositionCard/Sushi.tsx
+69
-0
MigrateV2Pair.tsx
src/pages/MigrateV2/MigrateV2Pair.tsx
+6
-3
index.tsx
src/pages/MigrateV2/index.tsx
+88
-27
No files found.
src/components/PositionCard/Sushi.tsx
0 → 100644
View file @
c3472764
import
React
from
'
react
'
import
{
Token
}
from
'
@uniswap/sdk-core
'
import
{
Link
}
from
'
react-router-dom
'
import
{
Text
}
from
'
rebass
'
import
styled
from
'
styled-components
'
import
{
unwrappedToken
}
from
'
../../utils/wrappedCurrency
'
import
{
ButtonEmpty
}
from
'
../Button
'
import
{
transparentize
}
from
'
polished
'
import
{
CardNoise
}
from
'
../earn/styled
'
import
{
useColor
}
from
'
../../hooks/useColor
'
import
{
LightCard
}
from
'
../Card
'
import
{
AutoColumn
}
from
'
../Column
'
import
DoubleCurrencyLogo
from
'
../DoubleLogo
'
import
{
RowFixed
,
AutoRow
}
from
'
../Row
'
import
{
Dots
}
from
'
../swap/styleds
'
import
{
FixedHeightRow
}
from
'
.
'
const
StyledPositionCard
=
styled
(
LightCard
)
<
{
bgColor
:
any
}
>
`
border: none;
background:
${({
theme
,
bgColor
})
=>
`radial-gradient(91.85% 100% at 1.84% 0%,
${
transparentize
(
0.8
,
bgColor
)}
0%,
${
theme
.
bg3
}
100%) `
}
;
position: relative;
overflow: hidden;
`
interface
PositionCardProps
{
tokenA
:
Token
tokenB
:
Token
liquidityToken
:
Token
border
?:
string
}
export
default
function
SushiPositionCard
({
tokenA
,
tokenB
,
liquidityToken
,
border
}:
PositionCardProps
)
{
const
currency0
=
unwrappedToken
(
tokenA
)
const
currency1
=
unwrappedToken
(
tokenB
)
const
backgroundColor
=
useColor
(
tokenA
)
return
(
<
StyledPositionCard
border=
{
border
}
bgColor=
{
backgroundColor
}
>
<
CardNoise
/>
<
AutoColumn
gap=
"12px"
>
<
FixedHeightRow
>
<
AutoRow
gap=
"8px"
>
<
DoubleCurrencyLogo
currency0=
{
currency0
}
currency1=
{
currency1
}
size=
{
20
}
/>
<
Text
fontWeight=
{
500
}
fontSize=
{
20
}
>
{
!
currency0
||
!
currency1
?
<
Dots
>
Loading
</
Dots
>
:
`${currency0.symbol}/${currency1.symbol}`
}
</
Text
>
(Sushi)
</
AutoRow
>
<
RowFixed
gap=
"8px"
>
<
ButtonEmpty
padding=
"0px 35px 0px 0px"
borderRadius=
"12px"
width=
"fit-content"
as=
{
Link
}
to=
{
`/migrate/v2/${liquidityToken.address}`
}
>
Migrate
</
ButtonEmpty
>
</
RowFixed
>
</
FixedHeightRow
>
</
AutoColumn
>
</
StyledPositionCard
>
)
}
src/pages/MigrateV2/MigrateV2Pair.tsx
View file @
c3472764
import
React
,
{
useCallback
,
useMemo
,
useState
}
from
'
react
'
import
React
,
{
useCallback
,
useMemo
,
useState
}
from
'
react
'
import
{
Fraction
,
Price
,
Token
,
TokenAmount
,
WETH9
}
from
'
@uniswap/sdk-core
'
import
{
Fraction
,
Price
,
Token
,
TokenAmount
,
WETH9
}
from
'
@uniswap/sdk-core
'
import
{
JSBI
}
from
'
@uniswap/v2-sdk
'
import
{
FACTORY_ADDRESS
,
JSBI
}
from
'
@uniswap/v2-sdk
'
import
{
Redirect
,
RouteComponentProps
}
from
'
react-router
'
import
{
Redirect
,
RouteComponentProps
}
from
'
react-router
'
import
{
Text
}
from
'
rebass
'
import
{
Text
}
from
'
rebass
'
import
{
AutoColumn
}
from
'
../../components/Column
'
import
{
AutoColumn
}
from
'
../../components/Column
'
...
@@ -109,6 +109,9 @@ function V2PairMigration({
...
@@ -109,6 +109,9 @@ function V2PairMigration({
const
{
chainId
,
account
}
=
useActiveWeb3React
()
const
{
chainId
,
account
}
=
useActiveWeb3React
()
const
theme
=
useTheme
()
const
theme
=
useTheme
()
const
pairFactory
=
useSingleCallResult
(
pair
,
'
factory
'
)
const
isNotUniswap
=
pairFactory
.
result
?.[
0
]
!==
FACTORY_ADDRESS
const
deadline
=
useTransactionDeadline
()
// custom from users settings
const
deadline
=
useTransactionDeadline
()
// custom from users settings
const
blockTimestamp
=
useCurrentBlockTimestamp
()
const
blockTimestamp
=
useCurrentBlockTimestamp
()
const
[
allowedSlippage
]
=
useUserSlippageTolerance
()
// custom from users
const
[
allowedSlippage
]
=
useUserSlippageTolerance
()
// custom from users
...
@@ -231,8 +234,8 @@ function V2PairMigration({
...
@@ -231,8 +234,8 @@ function V2PairMigration({
const
{
signatureData
,
gatherPermitSignature
}
=
useV2LiquidityTokenPermit
(
pairBalance
,
migratorAddress
)
const
{
signatureData
,
gatherPermitSignature
}
=
useV2LiquidityTokenPermit
(
pairBalance
,
migratorAddress
)
const
approve
=
useCallback
(
async
()
=>
{
const
approve
=
useCallback
(
async
()
=>
{
gatherPermitSignature
?
gatherPermitSignature
()
:
approveManually
?
approveManually
()
:
null
isNotUniswap
?
approveManually
()
:
gatherPermitSignature
?
gatherPermitSignature
()
:
approveManually
()
},
[
gatherPermitSignature
,
approveManually
])
},
[
isNotUniswap
,
gatherPermitSignature
,
approveManually
])
const
addTransaction
=
useTransactionAdder
()
const
addTransaction
=
useTransactionAdder
()
const
isMigrationPending
=
useIsTransactionPending
(
pendingMigrationHash
??
undefined
)
const
isMigrationPending
=
useIsTransactionPending
(
pendingMigrationHash
??
undefined
)
...
...
src/pages/MigrateV2/index.tsx
View file @
c3472764
import
React
,
{
useContext
,
useMemo
}
from
'
react
'
import
React
,
{
useContext
,
useMemo
}
from
'
react
'
import
{
Pair
}
from
'
@uniswap/v2-sdk
'
import
{
Pair
}
from
'
@uniswap/v2-sdk
'
import
{
Token
,
ChainId
}
from
'
@uniswap/sdk-core
'
import
{
ThemeContext
}
from
'
styled-components
'
import
{
ThemeContext
}
from
'
styled-components
'
import
{
AutoColumn
}
from
'
../../components/Column
'
import
{
AutoColumn
}
from
'
../../components/Column
'
import
{
AutoRow
}
from
'
../../components/Row
'
import
{
AutoRow
}
from
'
../../components/Row
'
...
@@ -13,10 +14,11 @@ import QuestionHelper from '../../components/QuestionHelper'
...
@@ -13,10 +14,11 @@ import QuestionHelper from '../../components/QuestionHelper'
import
{
Dots
}
from
'
../../components/swap/styleds
'
import
{
Dots
}
from
'
../../components/swap/styleds
'
import
{
toV2LiquidityToken
,
useTrackedTokenPairs
}
from
'
../../state/user/hooks
'
import
{
toV2LiquidityToken
,
useTrackedTokenPairs
}
from
'
../../state/user/hooks
'
import
MigrateV2PositionCard
from
'
components/PositionCard/V2
'
import
MigrateV2PositionCard
from
'
components/PositionCard/V2
'
import
{
useV2Pairs
}
from
'
hooks/useV2Pairs
'
import
MigrateSushiPositionCard
from
'
components/PositionCard/Sushi
'
import
{
PairState
,
useV2Pairs
}
from
'
hooks/useV2Pairs
'
import
{
getCreate2Address
}
from
'
@ethersproject/address
'
import
{
pack
,
keccak256
}
from
'
@ethersproject/solidity
'
// TODO there's a bug in loading where "No V2 Liquidity found" flashes
// TODO add support for more pairs
function
EmptyState
({
message
}:
{
message
:
string
})
{
function
EmptyState
({
message
}:
{
message
:
string
})
{
return
(
return
(
<
AutoColumn
style=
{
{
minHeight
:
200
,
justifyContent
:
'
center
'
,
alignItems
:
'
center
'
}
}
>
<
AutoColumn
style=
{
{
minHeight
:
200
,
justifyContent
:
'
center
'
,
alignItems
:
'
center
'
}
}
>
...
@@ -25,37 +27,83 @@ function EmptyState({ message }: { message: string }) {
...
@@ -25,37 +27,83 @@ function EmptyState({ message }: { message: string }) {
)
)
}
}
// quick hack because sushi init code hash is different
const
computeSushiPairAddress
=
({
tokenA
,
tokenB
}:
{
tokenA
:
Token
;
tokenB
:
Token
}):
string
=>
{
const
[
token0
,
token1
]
=
tokenA
.
sortsBefore
(
tokenB
)
?
[
tokenA
,
tokenB
]
:
[
tokenB
,
tokenA
]
// does safety checks
return
getCreate2Address
(
'
0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac
'
,
keccak256
([
'
bytes
'
],
[
pack
([
'
address
'
,
'
address
'
],
[
token0
.
address
,
token1
.
address
])]),
'
0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
'
)
}
/**
* Given two tokens return the sushiswap liquidity token that represents its liquidity shares
* @param tokenA one of the two tokens
* @param tokenB the other token
*/
function
toSushiLiquidityToken
([
tokenA
,
tokenB
]:
[
Token
,
Token
]):
Token
{
return
new
Token
(
tokenA
.
chainId
,
computeSushiPairAddress
({
tokenA
,
tokenB
}),
18
,
'
SLP
'
,
'
SushiSwap LP Token
'
)
}
export
default
function
MigrateV2
()
{
export
default
function
MigrateV2
()
{
const
theme
=
useContext
(
ThemeContext
)
const
theme
=
useContext
(
ThemeContext
)
const
{
account
}
=
useActiveWeb3React
()
const
{
account
,
chainId
}
=
useActiveWeb3React
()
// fetch the user's balances of all tracked V2 LP tokens
// fetch the user's balances of all tracked V2 LP tokens
const
trackedTokenPairs
=
useTrackedTokenPairs
()
const
trackedTokenPairs
=
useTrackedTokenPairs
()
// calculate v2 + sushi pair contract addresses for all token pairs
const
tokenPairsWithLiquidityTokens
=
useMemo
(
const
tokenPairsWithLiquidityTokens
=
useMemo
(
()
=>
trackedTokenPairs
.
map
((
tokens
)
=>
({
liquidityToken
:
toV2LiquidityToken
(
tokens
),
tokens
})),
()
=>
[
trackedTokenPairs
]
trackedTokenPairs
.
map
((
tokens
)
=>
{
// sushi liquidity token or null
const
sushiLiquidityToken
=
chainId
===
ChainId
.
MAINNET
?
toSushiLiquidityToken
(
tokens
)
:
null
return
{
v2liquidityToken
:
toV2LiquidityToken
(
tokens
),
sushiLiquidityToken
,
tokens
,
}
}),
[
trackedTokenPairs
,
chainId
]
)
)
const
liquidityTokens
=
useMemo
(()
=>
tokenPairsWithLiquidityTokens
.
map
((
tpwlt
)
=>
tpwlt
.
liquidityToken
),
[
tokenPairsWithLiquidityTokens
,
// get pair liquidity token addresses for balance-fetching purposes
])
const
allLiquidityTokens
=
useMemo
(()
=>
{
const
[
v2PairsBalances
,
fetchingV2PairBalances
]
=
useTokenBalancesWithLoadingIndicator
(
const
v2
=
tokenPairsWithLiquidityTokens
.
map
(({
v2liquidityToken
})
=>
v2liquidityToken
)
const
sushi
=
tokenPairsWithLiquidityTokens
.
map
(({
sushiLiquidityToken
})
=>
sushiLiquidityToken
)
.
filter
((
token
):
token
is
Token
=>
!!
token
)
return
[...
v2
,
...
sushi
]
},
[
tokenPairsWithLiquidityTokens
])
// fetch pair balances
const
[
pairBalances
,
fetchingPairBalances
]
=
useTokenBalancesWithLoadingIndicator
(
account
??
undefined
,
account
??
undefined
,
l
iquidityTokens
allL
iquidityTokens
)
)
// fetch the reserves for all V2 pools in which the user has a balance
// filter for v2 liquidity tokens that the user has a balance in
const
liquidityTokensWithBalances
=
useMemo
(
const
tokenPairsWithV2Balance
=
useMemo
(()
=>
{
()
=>
if
(
fetchingPairBalances
)
return
[]
tokenPairsWithLiquidityTokens
.
filter
(({
liquidityToken
})
=>
v2PairsBalances
[
liquidityToken
.
address
]?.
greaterThan
(
'
0
'
)
),
[
tokenPairsWithLiquidityTokens
,
v2PairsBalances
]
)
const
v2Pairs
=
useV2Pairs
(
liquidityTokensWithBalances
.
map
(({
tokens
})
=>
tokens
))
return
tokenPairsWithLiquidityTokens
const
v2IsLoading
=
.
filter
(({
v2liquidityToken
})
=>
pairBalances
[
v2liquidityToken
.
address
]?.
greaterThan
(
0
))
fetchingV2PairBalances
||
v2Pairs
?.
length
<
liquidityTokensWithBalances
.
length
||
v2Pairs
?.
some
((
V2Pair
)
=>
!
V2Pair
)
.
map
((
tokenPairsWithLiquidityTokens
)
=>
tokenPairsWithLiquidityTokens
.
tokens
)
const
allV2PairsWithLiquidity
=
v2Pairs
.
map
(([,
pair
])
=>
pair
).
filter
((
v2Pair
):
v2Pair
is
Pair
=>
Boolean
(
v2Pair
))
},
[
fetchingPairBalances
,
tokenPairsWithLiquidityTokens
,
pairBalances
])
// filter for v2 liquidity tokens that the user has a balance in
const
tokenPairsWithSushiBalance
=
useMemo
(()
=>
{
if
(
fetchingPairBalances
)
return
[]
return
tokenPairsWithLiquidityTokens
.
filter
(
({
sushiLiquidityToken
})
=>
!!
sushiLiquidityToken
&&
pairBalances
[
sushiLiquidityToken
.
address
]?.
greaterThan
(
0
)
)
},
[
fetchingPairBalances
,
tokenPairsWithLiquidityTokens
,
pairBalances
])
const
v2Pairs
=
useV2Pairs
(
tokenPairsWithV2Balance
)
const
v2IsLoading
=
fetchingPairBalances
||
v2Pairs
.
some
(([
pairState
])
=>
pairState
===
PairState
.
LOADING
)
return
(
return
(
<
BodyWrapper
style=
{
{
padding
:
24
}
}
>
<
BodyWrapper
style=
{
{
padding
:
24
}
}
>
...
@@ -85,11 +133,24 @@ export default function MigrateV2() {
...
@@ -85,11 +133,24 @@ export default function MigrateV2() {
<
Dots
>
Loading
</
Dots
>
<
Dots
>
Loading
</
Dots
>
</
TYPE
.
body
>
</
TYPE
.
body
>
</
LightCard
>
</
LightCard
>
)
:
allV2PairsWithLiquidity
?
.
length
>
0
?
(
)
:
v2Pairs
.
filter
(([,
pair
])
=>
!!
pair
)
.
length
>
0
?
(
<>
<>
{
allV2PairsWithLiquidity
.
map
((
pair
)
=>
(
{
v2Pairs
<
MigrateV2PositionCard
key=
{
pair
.
liquidityToken
.
address
}
pair=
{
pair
}
/>
.
filter
(([,
pair
])
=>
!!
pair
)
))
}
.
map
(([,
pair
])
=>
(
<
MigrateV2PositionCard
key=
{
(
pair
as
Pair
).
liquidityToken
.
address
}
pair=
{
pair
as
Pair
}
/>
))
}
{
tokenPairsWithSushiBalance
.
map
(({
sushiLiquidityToken
,
tokens
})
=>
{
return
(
<
MigrateSushiPositionCard
key=
{
(
sushiLiquidityToken
as
Token
).
address
}
tokenA=
{
tokens
[
0
]
}
tokenB=
{
tokens
[
1
]
}
liquidityToken=
{
sushiLiquidityToken
as
Token
}
/>
)
})
}
</>
</>
)
:
(
)
:
(
<
EmptyState
message=
"No V2 Liquidity found."
/>
<
EmptyState
message=
"No V2 Liquidity found."
/>
...
...
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