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
31f72a54
Unverified
Commit
31f72a54
authored
May 13, 2020
by
Moody Salem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up transaction modal behavior with new store
parent
287f64cf
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
150 additions
and
121 deletions
+150
-121
index.tsx
src/components/WalletModal/index.tsx
+2
-2
index.tsx
src/components/Web3Status/index.tsx
+19
-3
index.tsx
src/index.tsx
+6
-6
updater.ts
src/state/application/updater.ts
+1
-1
hooks.tsx
src/state/transactions/hooks.tsx
+2
-78
reducer.ts
src/state/transactions/reducer.ts
+7
-1
updater.tsx
src/state/transactions/updater.tsx
+81
-0
hooks.tsx
src/state/user/hooks.tsx
+2
-30
updater.tsx
src/state/user/updater.tsx
+30
-0
No files found.
src/components/WalletModal/index.tsx
View file @
31f72a54
...
...
@@ -119,8 +119,8 @@ export default function WalletModal({
confirmedTransactions
,
ENSName
}:
{
pendingTransactions
:
any
[]
confirmedTransactions
:
any
[]
pendingTransactions
:
string
[]
// hashes of pending
confirmedTransactions
:
string
[]
// hashes of confirmed
ENSName
?:
string
})
{
const
{
active
,
account
,
connector
,
activate
,
error
}
=
useWeb3React
()
...
...
src/components/Web3Status/index.tsx
View file @
31f72a54
import
React
from
'
react
'
import
React
,
{
useMemo
}
from
'
react
'
import
styled
,
{
css
}
from
'
styled-components
'
import
{
useTranslation
}
from
'
react-i18next
'
import
{
useWeb3React
,
UnsupportedChainIdError
}
from
'
@web3-react/core
'
import
{
darken
,
lighten
}
from
'
polished
'
import
{
Activity
}
from
'
react-feather
'
import
{
useWalletModalToggle
}
from
'
../../state/application/hooks
'
import
{
TransactionDetails
}
from
'
../../state/transactions/reducer
'
import
Identicon
from
'
../Identicon
'
import
PortisIcon
from
'
../../assets/images/portisIcon.png
'
...
...
@@ -121,6 +122,15 @@ const NetworkIcon = styled(Activity)`
height: 16px;
`
// we want the latest one to come first, so return negative if a is after b
function
newTranscationsFirst
(
a
:
TransactionDetails
,
b
:
TransactionDetails
)
{
return
b
.
addedTime
-
a
.
addedTime
}
function
recentTransactionsOnly
(
a
:
TransactionDetails
)
{
return
new
Date
().
getTime
()
-
a
.
addedTime
<
86
_400_000
}
export
default
function
Web3Status
()
{
const
{
t
}
=
useTranslation
()
const
{
active
,
account
,
connector
,
error
}
=
useWeb3React
()
...
...
@@ -129,8 +139,14 @@ export default function Web3Status() {
const
ENSName
=
useENSName
(
account
)
const
allTransactions
=
useAllTransactions
()
const
pending
=
Object
.
keys
(
allTransactions
).
filter
(
hash
=>
!
allTransactions
[
hash
].
receipt
)
const
confirmed
=
Object
.
keys
(
allTransactions
).
filter
(
hash
=>
allTransactions
[
hash
].
receipt
)
const
sortedRecentTransactions
=
useMemo
(()
=>
{
const
txs
=
Object
.
values
(
allTransactions
)
return
txs
.
filter
(
recentTransactionsOnly
).
sort
(
newTranscationsFirst
)
},
[
allTransactions
])
const
pending
=
sortedRecentTransactions
.
filter
(
tx
=>
!
tx
.
receipt
).
map
(
tx
=>
tx
.
hash
)
const
confirmed
=
sortedRecentTransactions
.
filter
(
tx
=>
tx
.
receipt
).
map
(
tx
=>
tx
.
hash
)
const
hasPendingTransactions
=
!!
pending
.
length
...
...
src/index.tsx
View file @
31f72a54
...
...
@@ -7,12 +7,12 @@ import { Provider } from 'react-redux'
import
{
NetworkContextName
}
from
'
./constants
'
import
{
isMobile
}
from
'
react-device-detect
'
import
{
Updater
as
LocalStorageContextUpdater
}
from
'
./state/user/hooks
'
import
{
Updater
as
TransactionContextUpdater
}
from
'
./state/transactions/hooks
'
import
BalancesContextProvider
,
{
Updater
as
BalancesContextUpdater
}
from
'
./contexts/Balances
'
import
App
from
'
./pages/App
'
import
store
from
'
./state
'
import
{
Updater
as
ApplicationContextUpdater
}
from
'
./state/application/updater
'
import
ApplicationUpdater
from
'
./state/application/updater
'
import
TransactionUpdater
from
'
./state/transactions/updater
'
import
UserUpdater
from
'
./state/user/updater
'
import
ThemeProvider
,
{
FixedGlobalStyle
,
ThemedGlobalStyle
}
from
'
./theme
'
import
'
./i18n
'
...
...
@@ -42,9 +42,9 @@ function ContextProviders({ children }: { children: React.ReactNode }) {
function
Updaters
()
{
return
(
<>
<
LocalStorageContext
Updater
/>
<
Application
Context
Updater
/>
<
Transaction
Context
Updater
/>
<
User
Updater
/>
<
ApplicationUpdater
/>
<
TransactionUpdater
/>
<
BalancesContextUpdater
/>
</>
)
...
...
src/state/application/updater.ts
View file @
31f72a54
...
...
@@ -3,7 +3,7 @@ import { useWeb3React } from '../../hooks'
import
{
updateBlockNumber
}
from
'
./actions
'
import
{
useDispatch
}
from
'
react-redux
'
export
function
Updater
()
{
export
default
function
Updater
()
{
const
{
library
,
chainId
}
=
useWeb3React
()
const
dispatch
=
useDispatch
()
...
...
src/state/transactions/hooks.tsx
View file @
31f72a54
import
{
TransactionResponse
}
from
'
@ethersproject/providers
'
import
{
useCallback
,
useEffect
}
from
'
react
'
import
{
useCallback
}
from
'
react
'
import
{
useDispatch
,
useSelector
}
from
'
react-redux
'
import
{
useWeb3React
}
from
'
../../hooks
'
import
{
useAddPopup
,
useBlockNumber
}
from
'
../application/hooks
'
import
{
AppDispatch
,
AppState
}
from
'
../index
'
import
{
addTransaction
,
checkTransaction
,
finalizeTransaction
}
from
'
./actions
'
import
{
addTransaction
}
from
'
./actions
'
import
{
TransactionDetails
}
from
'
./reducer
'
export
function
Updater
()
{
const
{
chainId
,
library
}
=
useWeb3React
()
const
globalBlockNumber
=
useBlockNumber
()
const
dispatch
=
useDispatch
<
AppDispatch
>
()
const
transactions
=
useSelector
<
AppState
>
(
state
=>
state
.
transactions
)
const
allTransactions
=
transactions
[
chainId
]
??
{}
// show popup on confirm
const
addPopup
=
useAddPopup
()
useEffect
(()
=>
{
if
((
chainId
||
chainId
===
0
)
&&
library
)
{
let
stale
=
false
Object
.
keys
(
allTransactions
)
.
filter
(
hash
=>
!
allTransactions
[
hash
].
receipt
&&
allTransactions
[
hash
].
blockNumberChecked
!==
globalBlockNumber
)
.
forEach
(
hash
=>
{
library
.
getTransactionReceipt
(
hash
)
.
then
(
receipt
=>
{
if
(
!
stale
)
{
if
(
!
receipt
)
{
dispatch
(
checkTransaction
({
chainId
,
hash
,
blockNumber
:
globalBlockNumber
}))
}
else
{
dispatch
(
finalizeTransaction
({
chainId
,
hash
,
receipt
:
{
blockHash
:
receipt
.
blockHash
,
blockNumber
:
receipt
.
blockNumber
,
contractAddress
:
receipt
.
contractAddress
,
from
:
receipt
.
from
,
status
:
receipt
.
status
,
to
:
receipt
.
to
,
transactionHash
:
receipt
.
transactionHash
,
transactionIndex
:
receipt
.
transactionIndex
}
})
)
// add success or failure popup
if
(
receipt
.
status
===
1
)
{
addPopup
({
txn
:
{
hash
,
success
:
true
,
summary
:
allTransactions
[
hash
]?.
response
?.
summary
}
})
}
else
{
addPopup
({
txn
:
{
hash
,
success
:
false
,
summary
:
allTransactions
[
hash
]?.
response
?.
summary
}
})
}
}
}
})
.
catch
(()
=>
{
dispatch
(
checkTransaction
({
chainId
,
hash
,
blockNumber
:
globalBlockNumber
}))
})
})
return
()
=>
{
stale
=
true
}
}
},
[
chainId
,
library
,
allTransactions
,
globalBlockNumber
,
dispatch
,
addPopup
])
return
null
}
// helper that can take a ethers library transaction response and add it to the list of transactions
export
function
useTransactionAdder
():
(
response
:
TransactionResponse
,
...
...
src/state/transactions/reducer.ts
View file @
31f72a54
import
{
createReducer
}
from
'
@reduxjs/toolkit
'
import
{
addTransaction
,
checkTransaction
,
finalizeTransaction
,
SerializableTransactionReceipt
}
from
'
./actions
'
const
now
=
()
=>
new
Date
().
getTime
()
export
interface
TransactionDetails
{
hash
:
string
approvalOfToken
?:
string
blockNumberChecked
?:
number
summary
?:
string
receipt
?:
SerializableTransactionReceipt
addedTime
:
number
confirmedTime
?:
number
}
export
interface
TransactionState
{
...
...
@@ -23,7 +28,7 @@ export default createReducer(initialState, builder =>
throw
Error
(
'
Attempted to add existing transaction.
'
)
}
state
[
chainId
]
=
state
[
chainId
]
??
{}
state
[
chainId
][
hash
]
=
{
approvalOfToken
,
summary
}
state
[
chainId
][
hash
]
=
{
hash
,
approvalOfToken
,
summary
,
addedTime
:
now
()
}
})
.
addCase
(
checkTransaction
,
(
state
,
{
payload
:
{
chainId
,
blockNumber
,
hash
}
})
=>
{
if
(
!
state
[
chainId
]?.[
hash
])
{
...
...
@@ -38,5 +43,6 @@ export default createReducer(initialState, builder =>
}
state
[
chainId
]
=
state
[
chainId
]
??
{}
state
[
chainId
][
hash
].
receipt
=
receipt
state
[
chainId
][
hash
].
confirmedTime
=
now
()
})
)
src/state/transactions/updater.tsx
0 → 100644
View file @
31f72a54
import
{
useEffect
}
from
'
react
'
import
{
useDispatch
,
useSelector
}
from
'
react-redux
'
import
{
useWeb3React
}
from
'
../../hooks
'
import
{
useAddPopup
,
useBlockNumber
}
from
'
../application/hooks
'
import
{
AppDispatch
,
AppState
}
from
'
../index
'
import
{
checkTransaction
,
finalizeTransaction
}
from
'
./actions
'
export
default
function
Updater
()
{
const
{
chainId
,
library
}
=
useWeb3React
()
const
globalBlockNumber
=
useBlockNumber
()
const
dispatch
=
useDispatch
<
AppDispatch
>
()
const
transactions
=
useSelector
<
AppState
>
(
state
=>
state
.
transactions
)
const
allTransactions
=
transactions
[
chainId
]
??
{}
// show popup on confirm
const
addPopup
=
useAddPopup
()
useEffect
(()
=>
{
if
((
chainId
||
chainId
===
0
)
&&
library
)
{
let
stale
=
false
Object
.
keys
(
allTransactions
)
.
filter
(
hash
=>
!
allTransactions
[
hash
].
receipt
&&
allTransactions
[
hash
].
blockNumberChecked
!==
globalBlockNumber
)
.
forEach
(
hash
=>
{
library
.
getTransactionReceipt
(
hash
)
.
then
(
receipt
=>
{
if
(
!
stale
)
{
if
(
!
receipt
)
{
dispatch
(
checkTransaction
({
chainId
,
hash
,
blockNumber
:
globalBlockNumber
}))
}
else
{
dispatch
(
finalizeTransaction
({
chainId
,
hash
,
receipt
:
{
blockHash
:
receipt
.
blockHash
,
blockNumber
:
receipt
.
blockNumber
,
contractAddress
:
receipt
.
contractAddress
,
from
:
receipt
.
from
,
status
:
receipt
.
status
,
to
:
receipt
.
to
,
transactionHash
:
receipt
.
transactionHash
,
transactionIndex
:
receipt
.
transactionIndex
}
})
)
// add success or failure popup
if
(
receipt
.
status
===
1
)
{
addPopup
({
txn
:
{
hash
,
success
:
true
,
summary
:
allTransactions
[
hash
]?.
summary
}
})
}
else
{
addPopup
({
txn
:
{
hash
,
success
:
false
,
summary
:
allTransactions
[
hash
]?.
summary
}
})
}
}
}
})
.
catch
(()
=>
{
dispatch
(
checkTransaction
({
chainId
,
hash
,
blockNumber
:
globalBlockNumber
}))
})
})
return
()
=>
{
stale
=
true
}
}
},
[
chainId
,
library
,
allTransactions
,
globalBlockNumber
,
dispatch
,
addPopup
])
return
null
}
src/state/user/hooks.tsx
View file @
31f72a54
import
{
ChainId
,
JSBI
,
Pair
,
Token
,
TokenAmount
,
WETH
}
from
'
@uniswap/sdk
'
import
{
useWeb3React
}
from
'
@web3-react/core
'
import
{
useCallback
,
use
Effect
,
use
Memo
}
from
'
react
'
import
{
useCallback
,
useMemo
}
from
'
react
'
import
{
shallowEqual
,
useDispatch
,
useSelector
}
from
'
react-redux
'
import
{
useAllTokens
}
from
'
../../contexts/Tokens
'
import
{
getTokenDecimals
,
getTokenName
,
getTokenSymbol
}
from
'
../../utils
'
...
...
@@ -12,9 +12,7 @@ import {
removeSerializedToken
,
SerializedPair
,
SerializedToken
,
updateMatchesDarkMode
,
updateUserDarkMode
,
updateVersion
updateUserDarkMode
}
from
'
./actions
'
function
serializeToken
(
token
:
Token
):
SerializedToken
{
...
...
@@ -37,32 +35,6 @@ function deserializeToken(serializedToken: SerializedToken): Token {
)
}
export
function
Updater
()
{
const
dispatch
=
useDispatch
<
AppDispatch
>
()
useEffect
(()
=>
{
dispatch
(
updateVersion
())
},
[
dispatch
])
// keep dark mode in sync with the system
useEffect
(()
=>
{
const
darkHandler
=
(
match
:
MediaQueryListEvent
)
=>
{
dispatch
(
updateMatchesDarkMode
({
matchesDarkMode
:
match
.
matches
}))
}
const
match
=
window
?.
matchMedia
(
'
(prefers-color-scheme: dark)
'
)
dispatch
(
updateMatchesDarkMode
({
matchesDarkMode
:
match
.
matches
}))
match
?.
addEventListener
(
'
change
'
,
darkHandler
)
return
()
=>
{
match
?.
removeEventListener
(
'
change
'
,
darkHandler
)
}
},
[
dispatch
])
return
null
}
// this currently isn't used anywhere, but is kept as an example of how to store/update a simple boolean
export
function
useBetaMessageManager
()
{
const
betaMessageDismissed
=
useSelector
<
AppState
,
boolean
>
(
state
=>
state
.
user
.
betaMessageDismissed
)
...
...
src/state/user/updater.tsx
0 → 100644
View file @
31f72a54
import
{
useEffect
}
from
'
react
'
import
{
useDispatch
}
from
'
react-redux
'
import
{
AppDispatch
}
from
'
../index
'
import
{
updateMatchesDarkMode
,
updateVersion
}
from
'
./actions
'
export
default
function
Updater
()
{
const
dispatch
=
useDispatch
<
AppDispatch
>
()
useEffect
(()
=>
{
dispatch
(
updateVersion
())
},
[
dispatch
])
// keep dark mode in sync with the system
useEffect
(()
=>
{
const
darkHandler
=
(
match
:
MediaQueryListEvent
)
=>
{
dispatch
(
updateMatchesDarkMode
({
matchesDarkMode
:
match
.
matches
}))
}
const
match
=
window
?.
matchMedia
(
'
(prefers-color-scheme: dark)
'
)
dispatch
(
updateMatchesDarkMode
({
matchesDarkMode
:
match
.
matches
}))
match
?.
addEventListener
(
'
change
'
,
darkHandler
)
return
()
=>
{
match
?.
removeEventListener
(
'
change
'
,
darkHandler
)
}
},
[
dispatch
])
return
null
}
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