mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo-client.git
synced 2026-09-21 16:52:02 -07:00
Merge pull request #16 from Permissionless-Software-Foundation/dh-load-times
fix(load): Load BCH & SLP info in the background
This commit is contained in:
+46
-9
@@ -65,6 +65,44 @@ function App (props) {
|
||||
return false
|
||||
}, [appData, addToModal])
|
||||
|
||||
/**
|
||||
* Run background process to get bch and slp balance.
|
||||
* Also update the background state process.
|
||||
* On error this function should trigger a info modal notifying the errors.
|
||||
*/
|
||||
const backgroundAsync = useCallback(async (asyncLoad, walletTemp) => {
|
||||
try {
|
||||
appData.setModalBody(['Getting BCH balance in background!.'])
|
||||
// Get Wallet Balance
|
||||
await asyncLoad.getWalletBchBalance(walletTemp, appData.updateBchWalletState, appData)
|
||||
// Update Background state
|
||||
appData.updateBackGroundInitState({ bchInitLoaded: true })
|
||||
|
||||
// Get SLP Balance
|
||||
appData.setModalBody(['Getting SLP tokens in background!.'])
|
||||
await asyncLoad.getSlpTokenBalances(walletTemp, appData.updateBchWalletState, appData)
|
||||
|
||||
// Update Background state
|
||||
appData.updateBackGroundInitState({ slpInitLoaded: true, asyncBackgroundFinished: true })
|
||||
} catch (err) {
|
||||
console.log('App.js backgroundAsync() error!', err)
|
||||
|
||||
appData.updateBackGroundInitState({ asyncBackgroundFinished: true })
|
||||
|
||||
addToModal(`Error: ${err.message}`, appData)
|
||||
addToModal('Try selecting a different back end server using the drop-down menu at the bottom of the app.\'', appData)
|
||||
|
||||
// Update Modal State
|
||||
appData.setHideSpinner(true)
|
||||
appData.setShowStartModal(true)
|
||||
appData.setDenyClose(false)
|
||||
|
||||
// Update the startup state.
|
||||
appData.setAsyncInitFinished(true)
|
||||
appData.setAsyncInitSucceeded(false)
|
||||
}
|
||||
}, [appData, addToModal])
|
||||
|
||||
/** Load all required data before component start. */
|
||||
useEffect(() => {
|
||||
async function asyncEffect () {
|
||||
@@ -95,14 +133,6 @@ function App (props) {
|
||||
appData.setWallet(walletTemp)
|
||||
// appData.updateBchWalletState({ walletObj: walletTemp.walletInfo, appData })
|
||||
|
||||
// Get the BCH balance of the wallet.
|
||||
addToModal('Getting BCH balance', appData)
|
||||
await asyncLoad.getWalletBchBalance(walletTemp, appData.updateBchWalletState, appData)
|
||||
|
||||
// Get the SLP tokens held by the wallet.
|
||||
addToModal('Getting SLP tokens', appData)
|
||||
await asyncLoad.getSlpTokenBalances(walletTemp, appData.updateBchWalletState, appData)
|
||||
|
||||
// Get the BCH spot price
|
||||
addToModal('Getting BCH spot price in USD', appData)
|
||||
await asyncLoad.getUSDExchangeRate(walletTemp, appData.updateBchWalletState, appData)
|
||||
@@ -115,6 +145,13 @@ function App (props) {
|
||||
appData.setAsyncInitFinished(true)
|
||||
appData.setAsyncInitSucceeded(true)
|
||||
console.log('App.js useEffect() startup finished successfully')
|
||||
|
||||
backgroundAsync(asyncLoad, walletTemp)
|
||||
// Get the BCH balance of the wallet.
|
||||
// addToModal('Getting BCH balance', appData)
|
||||
|
||||
// Get the SLP tokens held by the wallet.
|
||||
// addToModal('Getting SLP tokens', appData)
|
||||
} catch (err) {
|
||||
const errModalBody = [
|
||||
`Error: ${err.message}`,
|
||||
@@ -134,7 +171,7 @@ function App (props) {
|
||||
}
|
||||
}
|
||||
asyncEffect()
|
||||
}, [appData, addToModal, isSignleView])
|
||||
}, [appData, addToModal, isSignleView, backgroundAsync])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
// Global npm libraries
|
||||
import React from 'react'
|
||||
import { Container, Row, Col, Card } from 'react-bootstrap'
|
||||
import { Container, Row, Col, Card, Spinner } from 'react-bootstrap'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faCoins } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
@@ -15,6 +15,11 @@ const BalanceCard = (props) => {
|
||||
const sats = appData.bchWalletState.bchBalance
|
||||
const bchBalance = bchjs.BitcoinCash.toBitcoinCash(sats)
|
||||
const usdBalance = bchjs.Util.floor2(bchBalance * appData.bchWalletState.bchUsdPrice)
|
||||
const { bchInitLoaded, asyncBackgroundFinished } = appData.asyncBackGroundInitState
|
||||
|
||||
// Background bch data loaded finished
|
||||
const backgroundDataLoaded = bchInitLoaded || asyncBackgroundFinished
|
||||
const backgroundDataError = !bchInitLoaded && asyncBackgroundFinished
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -25,25 +30,37 @@ const BalanceCard = (props) => {
|
||||
</Card.Title>
|
||||
<br />
|
||||
|
||||
<Container>
|
||||
<Row>
|
||||
<Col>
|
||||
<b>USD</b>: ${usdBalance}
|
||||
</Col>
|
||||
</Row>
|
||||
{bchInitLoaded && (
|
||||
<Container>
|
||||
<Row>
|
||||
<Col>
|
||||
<b>USD</b>: ${usdBalance}
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<b>BCH</b>: {bchBalance}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<b>BCH</b>: {bchBalance}
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<b>Satoshis</b>: {sats}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
<Row>
|
||||
<Col>
|
||||
<b>Satoshis</b>: {sats}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>)}
|
||||
{backgroundDataError && (
|
||||
<Container>
|
||||
<span style={{ color: 'red' }}>Balance could not be loaded!</span>
|
||||
</Container>
|
||||
)}
|
||||
|
||||
{!backgroundDataLoaded && (
|
||||
<div className='balance-spinner-container'>
|
||||
<Spinner animation='border' />
|
||||
</div>
|
||||
)}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</>
|
||||
|
||||
@@ -50,6 +50,9 @@ export default function RefreshBchBalance (props) {
|
||||
// Get the latest balance of the wallet.
|
||||
const newBalance = await wallet.getBalance({ bchAddress: cashAddr })
|
||||
|
||||
// if bchInitLoaded is 'false', them set as true , to show the new balance.
|
||||
appData.updateBackGroundInitState({ bchInitLoaded: true })
|
||||
|
||||
addToModal('Updating BCH per USD price...')
|
||||
const bchUsdPrice = await wallet.getUsd()
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ import RefreshBchBalance from './refresh-balance'
|
||||
function RefreshBchBalanceButton (props) {
|
||||
// Dependency injections of props
|
||||
const appData = props.appData
|
||||
const { bchInitLoaded, asyncBackgroundFinished } = appData.asyncBackGroundInitState
|
||||
|
||||
// Background bch data loaded finished
|
||||
const backgroundDataLoaded = bchInitLoaded || asyncBackgroundFinished
|
||||
|
||||
// Child function references
|
||||
const refreshBchBalanceRef = useRef()
|
||||
@@ -28,7 +32,7 @@ function RefreshBchBalanceButton (props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant='success' onClick={() => { handleButtonRefreshBalance(appData) }}>
|
||||
<Button variant='success' onClick={() => { handleButtonRefreshBalance(appData) }} disabled={!backgroundDataLoaded}>
|
||||
<FontAwesomeIcon icon={faRedo} size='lg' /> Refresh
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import RefreshBchBalance from './refresh-balance'
|
||||
function SendCard (props) {
|
||||
// Dependency injection through props
|
||||
const appData = props.appData
|
||||
const { bchInitLoaded, asyncBackgroundFinished } = appData.asyncBackGroundInitState
|
||||
|
||||
// Modal State
|
||||
const [modalBody, setModalBody] = useState([])
|
||||
@@ -29,6 +30,9 @@ function SendCard (props) {
|
||||
const [oppositeUnits, setOppositeUnits] = useState('BCH')
|
||||
const [oppositeQty, setOppositeQty] = useState(0)
|
||||
|
||||
// Background bch data loaded finished
|
||||
const backgroundDataLoaded = bchInitLoaded || asyncBackgroundFinished
|
||||
|
||||
// Child function references
|
||||
const refreshBchBalanceRef = useRef()
|
||||
|
||||
@@ -318,7 +322,7 @@ function SendCard (props) {
|
||||
|
||||
<Row>
|
||||
<Col style={{ textAlign: 'center' }}>
|
||||
<Button onClick={(e) => handleSendBch({ sendCardData, appData })}>Send</Button>
|
||||
<Button onClick={(e) => handleSendBch({ sendCardData, appData })} disabled={!backgroundDataLoaded}>Send</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
@@ -13,12 +13,17 @@ import TokenCard from './token-card'
|
||||
import RefreshTokenBalance from './refresh-tokens'
|
||||
|
||||
const SlpTokens = (props) => {
|
||||
const [appData, setAppData] = useState(props.appData)
|
||||
const { appData } = props
|
||||
const [iconsAreLoaded, setIconsAreLoaded] = useState(false)
|
||||
const [dataAreLoaded, setDataAreLoaded] = useState(false)
|
||||
const [tokens, setTokens] = useState([])
|
||||
|
||||
const refreshTokenButtonRef = React.useRef()
|
||||
const { slpInitLoaded, asyncBackgroundFinished } = props.appData.asyncBackGroundInitState
|
||||
|
||||
// Background bch data loaded finished
|
||||
const backgroundDataLoaded = slpInitLoaded || asyncBackgroundFinished
|
||||
const backgroundDataError = !slpInitLoaded && asyncBackgroundFinished
|
||||
|
||||
// Update the tokens state when the appData changes
|
||||
useEffect(() => {
|
||||
@@ -31,8 +36,7 @@ const SlpTokens = (props) => {
|
||||
// within the wallet app.
|
||||
// This function triggers the on-click function within the refresh-tokens.js button.
|
||||
const refreshTokens = async () => {
|
||||
const newAppData = await refreshTokenButtonRef.current.handleRefreshTokenBalance()
|
||||
setAppData(newAppData)
|
||||
await refreshTokenButtonRef.current.handleRefreshTokenBalance()
|
||||
}
|
||||
|
||||
// Get Cid from url
|
||||
@@ -135,6 +139,7 @@ const SlpTokens = (props) => {
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const tokens = appData.bchWalletState.slpTokens
|
||||
console.log('tokens', tokens)
|
||||
setTokens(tokens)
|
||||
await lazyLoadTokenData(tokens)
|
||||
await lazyLoadMutableData(tokens)
|
||||
@@ -142,8 +147,10 @@ const SlpTokens = (props) => {
|
||||
|
||||
// Start to load the token icons when the component is mounted
|
||||
useEffect(() => {
|
||||
loadData()
|
||||
}, [loadData])
|
||||
if (slpInitLoaded) {
|
||||
loadData()
|
||||
}
|
||||
}, [loadData, slpInitLoaded])
|
||||
|
||||
// Generate the token cards for each token in the wallet.
|
||||
const generateCards = () => {
|
||||
@@ -178,7 +185,15 @@ const SlpTokens = (props) => {
|
||||
<Row>
|
||||
<Col xs={12} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
{/** Show spinner info if tokens are loaded but data is not loaded */
|
||||
!dataAreLoaded && (
|
||||
!backgroundDataLoaded && !backgroundDataError && (
|
||||
<div style={{ borderRadius: '10px', backgroundColor: '#f0f0f0', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center', width: 'fit-content' }}>
|
||||
<span style={{ marginRight: '10px' }}>Loading Tokens </span>
|
||||
<Spinner animation='border' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/** Show spinner info if tokens are loaded but data is not loaded */
|
||||
!backgroundDataError && !dataAreLoaded && tokens.length > 0 && (
|
||||
<div style={{ borderRadius: '10px', backgroundColor: '#f0f0f0', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center', width: 'fit-content' }}>
|
||||
<span style={{ marginRight: '10px' }}>Loading Token Data </span>
|
||||
<Spinner animation='border' />
|
||||
@@ -186,7 +201,7 @@ const SlpTokens = (props) => {
|
||||
)
|
||||
}
|
||||
{/** Show spinner info if tokens are loaded but icons are not loaded */
|
||||
dataAreLoaded && !iconsAreLoaded && (
|
||||
backgroundDataLoaded && dataAreLoaded && !iconsAreLoaded && (
|
||||
<div style={{ borderRadius: '10px', backgroundColor: '#f0f0f0', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center', width: 'fit-content' }}>
|
||||
<span style={{ marginRight: '10px' }}>Loading Token Icons </span>
|
||||
<Spinner animation='border' />
|
||||
@@ -202,11 +217,16 @@ const SlpTokens = (props) => {
|
||||
{generateCards()}
|
||||
</Row>
|
||||
{/** Display a message if no tokens are found */}
|
||||
{tokens.length === 0 && (
|
||||
{backgroundDataLoaded && !backgroundDataError && tokens.length === 0 && (
|
||||
<Row className='text-center'>
|
||||
<span> No tokens found in wallet </span>
|
||||
</Row>
|
||||
)}
|
||||
{backgroundDataError && (
|
||||
<Row style={{ color: 'red' }} className='text-center'>
|
||||
<span>Tokens could not be loaded! </span>
|
||||
</Row>
|
||||
)}
|
||||
|
||||
</Container>
|
||||
</>
|
||||
|
||||
@@ -18,6 +18,10 @@ function RefreshTokenBalance ({ appData: initialAppData, ref, lazyLoadTokenIcons
|
||||
const [modalBody, setModalBody] = useState([])
|
||||
const [hideSpinner, setHideSpinner] = useState(false)
|
||||
const [hideWaitingModal, setHideWaitingModal] = useState(true)
|
||||
const { slpInitLoaded, asyncBackgroundFinished } = initialAppData.asyncBackGroundInitState
|
||||
|
||||
// Background bch data loaded finished
|
||||
const backgroundDataLoaded = slpInitLoaded || asyncBackgroundFinished
|
||||
|
||||
// Add a new line to the waiting modal.
|
||||
const addToModal = (inStr) => {
|
||||
@@ -58,6 +62,10 @@ function RefreshTokenBalance ({ appData: initialAppData, ref, lazyLoadTokenIcons
|
||||
appData.updateBchWalletState({ walletObj: walletState, appData })
|
||||
|
||||
const newAppData = { ...appData, bchWalletState: walletState }
|
||||
|
||||
// if slpInitLoaded is 'false', them set as true , to show the new balance.
|
||||
appData.updateBackGroundInitState({ slpInitLoaded: true })
|
||||
|
||||
// Update state
|
||||
setHideWaitingModal(true)
|
||||
setAppData(newAppData)
|
||||
@@ -82,7 +90,7 @@ function RefreshTokenBalance ({ appData: initialAppData, ref, lazyLoadTokenIcons
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant='success' onClick={handleRefreshTokenBalance}>
|
||||
<Button variant='success' onClick={handleRefreshTokenBalance} disabled={!backgroundDataLoaded}>
|
||||
<FontAwesomeIcon icon={faRedo} size='lg' /> Refresh
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export function UninitializedView (props = {}) {
|
||||
/>
|
||||
{
|
||||
appData.asyncInitFinished
|
||||
? <AppBody menuState={100} wallet={appData.wallet} appData={appData} />
|
||||
? <> <br /><AppBody menuState={100} wallet={appData.wallet} appData={appData} /></>
|
||||
: null
|
||||
}
|
||||
</>
|
||||
|
||||
+26
-2
@@ -36,6 +36,10 @@ function useAppState () {
|
||||
const [denyClose, setDenyClose] = useState(false)
|
||||
|
||||
const [isSingleView, setIsSingleView] = useState(false)
|
||||
// Background process state
|
||||
const [asyncBackGroundInitState, setAsyncBackGroundInitState] = useState({
|
||||
bchInitLoaded: false, slpInitLoaded: false, asyncBackgroundFinished: false
|
||||
})
|
||||
|
||||
// The wallet state makes this a true progressive web app (PWA). As
|
||||
// balances, UTXOs, and tokens are retrieved, this state is updated.
|
||||
@@ -96,6 +100,25 @@ function useAppState () {
|
||||
}
|
||||
}
|
||||
|
||||
// Update background state
|
||||
function updateBackGroundInitState (inObj = {}) {
|
||||
try {
|
||||
setAsyncBackGroundInitState(oldState => {
|
||||
// console.log('background old state: ', oldState)
|
||||
|
||||
const state = Object.assign({}, oldState, inObj)
|
||||
// console.log('background state: ', state)
|
||||
|
||||
return state
|
||||
})
|
||||
|
||||
// console.log(`New wallet state: ${JSON.stringify(bchWalletState, null, 2)}`)
|
||||
} catch (err) {
|
||||
console.error('Error in App.js updateBackGroundInitState()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
serverUrl,
|
||||
setServerUrl,
|
||||
@@ -129,8 +152,9 @@ function useAppState () {
|
||||
appUtil: new AppUtil(),
|
||||
currentPath: location.pathname,
|
||||
setIsSingleView,
|
||||
isSingleView
|
||||
|
||||
isSingleView,
|
||||
asyncBackGroundInitState,
|
||||
updateBackGroundInitState
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,11 @@ class AsyncLoad {
|
||||
// Get the BCH balance of the wallet.
|
||||
async getWalletBchBalance (wallet, updateBchWalletState, appData) {
|
||||
try {
|
||||
/* // Force error for development
|
||||
await sleep(6000)
|
||||
throw new Error('getWalletBchBalance error')
|
||||
*/
|
||||
|
||||
// Get the BCH balance of the wallet.
|
||||
const bchBalance = await wallet.getBalance({ bchAddress: wallet.walletInfo.cashAddress })
|
||||
|
||||
@@ -111,6 +116,10 @@ class AsyncLoad {
|
||||
// Get a list of SLP tokens held by the wallet.
|
||||
async getSlpTokenBalances (wallet, updateBchWalletState, appData) {
|
||||
try {
|
||||
/* // Force error for development
|
||||
await sleep(6000)
|
||||
throw new Error('getSlpTokenBalances error')
|
||||
*/
|
||||
// Get token information from the wallet. This will also initialize the UTXO store.
|
||||
const slpTokens = await wallet.listTokens(wallet.walletInfo.cashAddress)
|
||||
// console.log('slpTokens: ', slpTokens)
|
||||
|
||||
Reference in New Issue
Block a user