Changeset View
Changeset View
Standalone View
Standalone View
web/cashtab/src/hooks/useWallet.js
Show First 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | const deriveAccount = async (BCH, { masterHDNode, path }) => { | ||||
cashAddress, | cashAddress, | ||||
slpAddress, | slpAddress, | ||||
fundingWif: BCH.HDNode.toWIF(node), | fundingWif: BCH.HDNode.toWIF(node), | ||||
fundingAddress: BCH.SLP.Address.toSLPAddress(cashAddress), | fundingAddress: BCH.SLP.Address.toSLPAddress(cashAddress), | ||||
legacyAddress: BCH.SLP.Address.toLegacyAddress(cashAddress), | legacyAddress: BCH.SLP.Address.toLegacyAddress(cashAddress), | ||||
}; | }; | ||||
}; | }; | ||||
const loadWalletFromStorageOnStartup = async setWallet => { | |||||
// get wallet object from localforage | |||||
const wallet = await getWallet(); | |||||
// If wallet object in storage is valid, use it to set state on startup | |||||
if (isValidStoredWallet(wallet)) { | |||||
// Convert all the token balance figures to big numbers | |||||
const liveWalletState = loadStoredWallet(wallet.state); | |||||
wallet.state = liveWalletState; | |||||
setWallet(wallet); | |||||
return setLoading(false); | |||||
} | |||||
// Loading will remain true until API calls populate this legacy wallet | |||||
setWallet(wallet); | |||||
}; | |||||
const haveUtxosChanged = (wallet, utxos, previousUtxos) => { | const haveUtxosChanged = (wallet, utxos, previousUtxos) => { | ||||
// Relevant points for this array comparing exercise | // Relevant points for this array comparing exercise | ||||
// https://stackoverflow.com/questions/13757109/triple-equal-signs-return-false-for-arrays-in-javascript-why | // https://stackoverflow.com/questions/13757109/triple-equal-signs-return-false-for-arrays-in-javascript-why | ||||
// https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript | // https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript | ||||
// If this is initial state | // If this is initial state | ||||
if (utxos === null) { | if (utxos === null) { | ||||
// Then make sure to get slpBalancesAndUtxos | // Then make sure to get slpBalancesAndUtxos | ||||
Show All 9 Lines | const haveUtxosChanged = (wallet, utxos, previousUtxos) => { | ||||
// If previousUtxos are undefined, see if you have previousUtxos in wallet state | // If previousUtxos are undefined, see if you have previousUtxos in wallet state | ||||
// If you do, and it has everything you need, set wallet state with that instead of calling hydrateUtxos on all utxos | // If you do, and it has everything you need, set wallet state with that instead of calling hydrateUtxos on all utxos | ||||
if (isValidStoredWallet(wallet)) { | if (isValidStoredWallet(wallet)) { | ||||
// Convert all the token balance figures to big numbers | // Convert all the token balance figures to big numbers | ||||
const liveWalletState = loadStoredWallet(wallet.state); | const liveWalletState = loadStoredWallet(wallet.state); | ||||
return setWalletState(liveWalletState); | return setWalletState(liveWalletState); | ||||
} | } | ||||
const cachedUtxos = wallet.state.utxos; | // If wallet in storage is a legacy wallet or otherwise does not have all state fields, | ||||
// Compare | // then assume utxos have changed | ||||
return !_.isEqual(utxos, cachedUtxos); | return true; | ||||
} | } | ||||
// return true for empty array, since this means you definitely do not want to skip the next API call | // return true for empty array, since this means you definitely do not want to skip the next API call | ||||
if (utxos && utxos.length === 0) { | if (utxos && utxos.length === 0) { | ||||
return true; | return true; | ||||
} | } | ||||
// Compare utxo sets | // Compare utxo sets | ||||
const utxoArraysUnchanged = _.isEqual(utxos, previousUtxos); | const utxoArraysUnchanged = _.isEqual(utxos, previousUtxos); | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | const update = async ({ wallet, setWalletState }) => { | ||||
newState.parsedTxHistory = parsedWithTokens; | newState.parsedTxHistory = parsedWithTokens; | ||||
newState.utxos = utxos; | newState.utxos = utxos; | ||||
newState.hydratedUtxoDetails = hydratedUtxoDetails; | newState.hydratedUtxoDetails = hydratedUtxoDetails; | ||||
setWalletState(newState); | setWalletState(newState); | ||||
// Set wallet with new state field | |||||
// Note: now that wallet carries state, maintaining a separate walletState object is redundant | |||||
// TODO clear up in future diff | |||||
wallet.state = wallet.newState; | |||||
setWallet(wallet); | |||||
// Write this state to indexedDb using localForage | // Write this state to indexedDb using localForage | ||||
writeWalletState(wallet, newState); | writeWalletState(wallet, newState); | ||||
// If everything executed correctly, remove apiError | // If everything executed correctly, remove apiError | ||||
setApiError(false); | setApiError(false); | ||||
} catch (error) { | } catch (error) { | ||||
console.log(`Error in update({wallet, setWalletState})`); | console.log(`Error in update({wallet, setWalletState})`); | ||||
console.log(error); | console.log(error); | ||||
// Set this in state so that transactions are disabled until the issue is resolved | // Set this in state so that transactions are disabled until the issue is resolved | ||||
▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | */ | ||||
await localforage.setItem('wallet', walletToActivate); | await localforage.setItem('wallet', walletToActivate); | ||||
} catch (err) { | } catch (err) { | ||||
console.log( | console.log( | ||||
`Error in localforage.setItem("wallet", walletToActivate) in activateWallet()`, | `Error in localforage.setItem("wallet", walletToActivate) in activateWallet()`, | ||||
); | ); | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Make sure stored wallet is in correct format to be used as live wallet | |||||
if (isValidStoredWallet(walletToActivate)) { | |||||
// Convert all the token balance figures to big numbers | |||||
const liveWalletState = loadStoredWallet(walletToActivate.state); | |||||
walletToActivate.state = liveWalletState; | |||||
} | |||||
return walletToActivate; | return walletToActivate; | ||||
}; | }; | ||||
const renameWallet = async (oldName, newName) => { | const renameWallet = async (oldName, newName) => { | ||||
// Load savedWallets | // Load savedWallets | ||||
let savedWallets; | let savedWallets; | ||||
try { | try { | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | ) => { | ||||
} | } | ||||
} catch (err) { | } catch (err) { | ||||
console.log(err); | console.log(err); | ||||
return false; | return false; | ||||
} | } | ||||
}; | }; | ||||
const handleUpdateWallet = async setWallet => { | const handleUpdateWallet = async setWallet => { | ||||
const wallet = await getWallet(); | await loadWalletFromStorageOnStartup(setWallet); | ||||
setWallet(wallet); | |||||
}; | }; | ||||
// Parse for incoming BCH transactions | // Parse for incoming BCH transactions | ||||
// Only notify if websocket is not connected | // Only notify if websocket is not connected | ||||
if ( | if ( | ||||
(ws === null || ws.readyState !== 1) && | (ws === null || ws.readyState !== 1) && | ||||
previousBalances && | previousBalances && | ||||
balances && | balances && | ||||
▲ Show 20 Lines • Show All 495 Lines • ▼ Show 20 Lines | return { | ||||
wallet: newWallet, | wallet: newWallet, | ||||
setWalletState, | setWalletState, | ||||
}).finally(() => setLoading(false)); | }).finally(() => setLoading(false)); | ||||
}, | }, | ||||
activateWallet: async walletToActivate => { | activateWallet: async walletToActivate => { | ||||
setLoading(true); | setLoading(true); | ||||
const newWallet = await activateWallet(walletToActivate); | const newWallet = await activateWallet(walletToActivate); | ||||
setWallet(newWallet); | setWallet(newWallet); | ||||
if (isValidStoredWallet(walletToActivate)) { | |||||
// If you have all state parameters needed in storage, immediately load the wallet | |||||
setLoading(false); | |||||
} else { | |||||
// If the wallet is missing state parameters in storage, wait for API info | |||||
// This handles case of unmigrated legacy wallet | |||||
update({ | update({ | ||||
wallet: newWallet, | wallet: newWallet, | ||||
setWalletState, | setWalletState, | ||||
}).finally(() => setLoading(false)); | }).finally(() => setLoading(false)); | ||||
} | |||||
}, | }, | ||||
addNewSavedWallet, | addNewSavedWallet, | ||||
renameWallet, | renameWallet, | ||||
deleteWallet, | deleteWallet, | ||||
}; | }; | ||||
}; | }; | ||||
export default useWallet; | export default useWallet; |