Skip to content

Commit

Permalink
fixup! Split data+logic for Portfolio vs Discover
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-edge committed Nov 27, 2024
1 parent 7a39881 commit 21ec4f7
Showing 1 changed file with 105 additions and 53 deletions.
158 changes: 105 additions & 53 deletions src/components/scenes/Staking/EarnScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ import { cacheStyles, Theme, useTheme } from '../../services/ThemeContext'
interface Props extends EdgeAppSceneProps<'earnScene'> {}

let USERNAME: string | undefined
let DISCOVER_ITEMS: DiscoverStakeInfo[] = []
let PORTFOLIO_ITEMS: PortfolioStakeInfo[] = []
let DISCOVER_MAP: DiscoverStakeMap = {}
let PORTFOLIO_MAP: PortfolioStakeMap = {}

interface DiscoverStakeInfo {
pluginId: string
stakePlugin: StakePlugin
stakePolicy: StakePolicy
}
Expand All @@ -40,23 +39,47 @@ interface PortfolioStakeInfo extends DiscoverStakeInfo {
walletStakeInfos: WalletStakeInfo[]
}

interface DiscoverStakeMap {
[stakePolicyId: string]: DiscoverStakeInfo
}

interface PortfolioStakeMap {
[stakePolicyId: string]: PortfolioStakeInfo
}

interface WalletStakeInfo {
wallet: EdgeCurrencyWallet
isPositionOpen: boolean
stakePosition: StakePosition
}

const useStakeMaps = () => {
const [, forceUpdate] = React.useReducer(x => x + 1, 0)

const updateMaps = React.useCallback((updates: () => void) => {
updates()
forceUpdate()
}, [])

return {
discoverMap: DISCOVER_MAP,
portfolioMap: PORTFOLIO_MAP,
updateMaps
}
}

export const EarnScene = (props: Props) => {
const { navigation } = props
const theme = useTheme()
const styles = getStyles(theme)

const { discoverMap, portfolioMap, updateMaps } = useStakeMaps()

const account = useSelector(state => state.core.account)
if (USERNAME !== account.username) {
// Reset local variable if user changes
USERNAME = account.username
DISCOVER_ITEMS = []
PORTFOLIO_ITEMS = []
DISCOVER_MAP = {}
PORTFOLIO_MAP = {}
}

const currencyConfigMap = useSelector(state => state.core.account.currencyConfig)
Expand All @@ -76,27 +99,32 @@ export const EarnScene = (props: Props) => {
useAsyncEffect(
async () => {
const pluginIds = Object.keys(currencyConfigMap)
DISCOVER_ITEMS = []

for (const pluginId of pluginIds) {
setIsLoadingDiscover(true)

const isStakingSupported = SPECIAL_CURRENCY_INFO[pluginId]?.isStakingSupported === true && ENV.ENABLE_STAKING
if (!isStakingSupported) continue

const stakePlugins = await getStakePlugins(pluginId)

for (const stakePlugin of stakePlugins) {
const stakePolicies = stakePlugin.getPolicies({ pluginId }).filter(stakePolicy => !stakePolicy.deprecated)

for (const stakePolicy of stakePolicies) {
DISCOVER_ITEMS.push({
pluginId,
stakePlugin,
stakePolicy
})
updateMaps(() => {
for (const stakePlugin of stakePlugins) {
for (const stakePolicy of stakePlugin.getPolicies({ pluginId }).filter(stakePolicy => !stakePolicy.deprecated)) {
DISCOVER_MAP[stakePolicy.stakePolicyId] = {
stakePlugin,
stakePolicy
}
}
}
}
})

console.debug('getStakePlugins', pluginId, 'complete')
setIsLoadingDiscover(false)
}

setIsLoadingDiscover(false)
return () => {}
},
[],
'EarnScene Initialize Discover Items'
Expand All @@ -107,46 +135,69 @@ export const EarnScene = (props: Props) => {
async () => {
if (!isLoadingDiscover || (isFocused && !isPrevFocused)) {
setIsLoadingPortfolio(true)
PORTFOLIO_ITEMS = []

for (const discoverInfo of DISCOVER_ITEMS) {
const { pluginId, stakePlugin, stakePolicy } = discoverInfo
console.debug(`refreshing stake positions for ${pluginId} ${stakePolicy.stakePolicyId}`)
const matchingWallets = wallets.filter((wallet: EdgeCurrencyWallet) => wallet.currencyInfo.pluginId === pluginId)
const walletStakeInfos = []

for (const wallet of matchingWallets) {
try {
const stakePosition = await stakePlugin.fetchStakePosition({
stakePolicyId: stakePolicy.stakePolicyId,
wallet,
account
})
const allocations = getPositionAllocations(stakePosition)
const { staked, earned, unstaked } = allocations
const isPositionOpen = [...staked, ...earned, ...unstaked].some(positionAllocation => !zeroString(positionAllocation.nativeAmount))

if (isPositionOpen) {
walletStakeInfos.push({ wallet, isPositionOpen, stakePosition })
const controller = new AbortController()
const signal = controller.signal

try {
const stakePolicyIds = Object.keys(discoverMap)
for (const stakePolicyId of stakePolicyIds) {
if (signal.aborted) break

const discoverInfo = discoverMap[stakePolicyId]
const { stakePlugin, stakePolicy } = discoverInfo

// Find matching wallets based on the first stake asset's pluginId
const pluginId = stakePolicy.stakeAssets[0].pluginId
const matchingWallets = wallets.filter((wallet: EdgeCurrencyWallet) => wallet.currencyInfo.pluginId === pluginId)

const walletStakeInfoPromises = matchingWallets.map(async wallet => {
if (signal.aborted) return null
try {
const stakePosition = await stakePlugin.fetchStakePosition({
stakePolicyId: stakePolicy.stakePolicyId,
wallet,
account
})
const allocations = getPositionAllocations(stakePosition)
const { staked, earned, unstaked } = allocations
const isPositionOpen = [...staked, ...earned, ...unstaked].some(positionAllocation => !zeroString(positionAllocation.nativeAmount))

if (isPositionOpen) {
return { wallet, stakePosition }
}
} catch (e) {
showDevError(e)
}
} catch (e) {
showDevError(e)
return null
})

if (!signal.aborted) {
const walletStakeInfos = (await Promise.all(walletStakeInfoPromises)).filter(
(info: WalletStakeInfo | null): info is WalletStakeInfo => info != null
)

updateMaps(() => {
PORTFOLIO_MAP[stakePolicyId] = {
...discoverInfo,
walletStakeInfos
}
})
}
}

if (walletStakeInfos.length > 0) {
PORTFOLIO_ITEMS.push({
...discoverInfo,
walletStakeInfos
})
} finally {
if (!signal.aborted) {
setIsLoadingPortfolio(false)
setIsPrevFocused(isFocused)
}
}

setIsLoadingPortfolio(false)
return () => {
controller.abort()
}
}
setIsPrevFocused(isFocused)
},
[isFocused, isLoadingDiscover],
[isFocused, isLoadingDiscover, updateMaps],
'EarnScene Refresh Portfolio Data'
)

Expand Down Expand Up @@ -202,6 +253,7 @@ export const EarnScene = (props: Props) => {

const renderPortfolioItem = (portfolioStakeInfo: PortfolioStakeInfo, currencyInfo: EdgeCurrencyInfo) => {
const { stakePlugin, stakePolicy, walletStakeInfos } = portfolioStakeInfo
if (walletStakeInfos.length === 0) return null

const handlePress = async () => {
let walletId: string | undefined
Expand All @@ -215,9 +267,7 @@ export const EarnScene = (props: Props) => {
stakePosition = existingStakePosition
} else {
// Select from wallets that have an open position
const allowedWalletIds = walletStakeInfos
.filter(walletStakeInfo => walletStakeInfo.isPositionOpen)
.map(walletStakePosition => walletStakePosition.wallet.id)
const allowedWalletIds = walletStakeInfos.map(walletStakePosition => walletStakePosition.wallet.id)

const result = await Airship.show<WalletListResult>(bridge => (
<WalletListModal
Expand Down Expand Up @@ -257,8 +307,10 @@ export const EarnScene = (props: Props) => {
<SceneWrapper scroll padding={theme.rem(0.5)}>
<EdgeSwitch labelA={lstrings.staking_discover} labelB={lstrings.staking_portfolio} onSelectA={handleSelectEarn} onSelectB={handleSelectPortfolio} />
<SectionHeader leftTitle={lstrings.staking_earning_pools} />
{isPortfolioSelected && PORTFOLIO_ITEMS.map(info => renderPortfolioItem(info, currencyConfigMap[info.pluginId].currencyInfo))}
{!isPortfolioSelected && DISCOVER_ITEMS.map(info => renderDiscoverItem(info, currencyConfigMap[info.pluginId].currencyInfo))}
{isPortfolioSelected &&
Object.values(portfolioMap).map(info => renderPortfolioItem(info, currencyConfigMap[info.stakePolicy.stakeAssets[0].pluginId].currencyInfo))}
{!isPortfolioSelected &&
Object.values(discoverMap).map(info => renderDiscoverItem(info, currencyConfigMap[info.stakePolicy.stakeAssets[0].pluginId].currencyInfo))}
{((isLoadingDiscover && !isPortfolioSelected) || (isLoadingPortfolio && isPortfolioSelected)) && (
<ActivityIndicator style={styles.loader} size="large" color={theme.primaryText} />
)}
Expand Down

0 comments on commit 21ec4f7

Please sign in to comment.