diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4a116d358..62c82d0a4 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1984,4 +1984,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: d44dfed27ca86fe0b1eb67aab0856b7cc9e24ff7 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/src/features/collectables/ChangeRewardsRecipientScreen.tsx b/src/features/collectables/ChangeRewardsRecipientScreen.tsx index 1bfaef5db..6550f4727 100644 --- a/src/features/collectables/ChangeRewardsRecipientScreen.tsx +++ b/src/features/collectables/ChangeRewardsRecipientScreen.tsx @@ -27,7 +27,7 @@ import { TouchableWithoutFeedback, } from 'react-native' import { Edge } from 'react-native-safe-area-context' -import { IOT_LAZY_KEY, MOBILE_LAZY_KEY } from '@utils/constants' +import { IOT_LAZY_KEY, MOBILE_LAZY_KEY, HNT_LAZY_KEY } from '@utils/constants' import { PublicKey } from '@solana/web3.js' import TouchableOpacityBox from '@components/TouchableOpacityBox' import { useCurrentWallet } from '@hooks/useCurrentWallet' @@ -139,7 +139,7 @@ const ChangeRewardsRecipientScreen = () => { setUpdating(true) try { await submitUpdateRewardsDestination({ - lazyDistributors: [IOT_LAZY_KEY, MOBILE_LAZY_KEY], + lazyDistributors: [HNT_LAZY_KEY, IOT_LAZY_KEY, MOBILE_LAZY_KEY], destination: recipient, assetId: hotspot.id, }) @@ -157,7 +157,7 @@ const ChangeRewardsRecipientScreen = () => { setRemoving(true) try { await submitUpdateRewardsDestination({ - lazyDistributors: [IOT_LAZY_KEY, MOBILE_LAZY_KEY], + lazyDistributors: [HNT_LAZY_KEY, IOT_LAZY_KEY, MOBILE_LAZY_KEY], destination: PublicKey.default.toBase58(), assetId: hotspot.id, }) diff --git a/src/features/collectables/ClaimAllRewardsScreen.tsx b/src/features/collectables/ClaimAllRewardsScreen.tsx index b53486d7e..115d64430 100644 --- a/src/features/collectables/ClaimAllRewardsScreen.tsx +++ b/src/features/collectables/ClaimAllRewardsScreen.tsx @@ -7,7 +7,7 @@ import { DelayedFadeIn } from '@components/FadeInOut' import RewardItem from '@components/RewardItem' import Text from '@components/Text' import { useSolOwnedAmount } from '@helium/helium-react-hooks' -import { IOT_MINT, MOBILE_MINT } from '@helium/spl-utils' +import { HNT_MINT, IOT_MINT, MOBILE_MINT } from '@helium/spl-utils' import { useBN } from '@hooks/useBN' import { useCurrentWallet } from '@hooks/useCurrentWallet' import useHotspots from '@hooks/useHotspots' @@ -15,6 +15,7 @@ import useSubmitTxn from '@hooks/useSubmitTxn' import { useNavigation } from '@react-navigation/native' import { useModal } from '@storage/ModalsProvider' import { + HNT_LAZY_KEY, IOT_LAZY_KEY, MIN_BALANCE_THRESHOLD, MOBILE_LAZY_KEY, @@ -22,6 +23,7 @@ import { import BN from 'bn.js' import React, { memo, useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' +import { ScrollView } from 'react-native' import { CollectableNavigationProp } from './collectablesTypes' const ClaimAllRewardsScreen = () => { @@ -39,6 +41,7 @@ const ClaimAllRewardsScreen = () => { hotspotsWithMeta, pendingIotRewards, pendingMobileRewards, + pendingHntRewards, totalHotspots, } = useHotspots() @@ -61,7 +64,7 @@ const ClaimAllRewardsScreen = () => { setRedeeming(true) const claim = async () => { await submitClaimAllRewards( - [IOT_LAZY_KEY, MOBILE_LAZY_KEY], + [HNT_LAZY_KEY, IOT_LAZY_KEY, MOBILE_LAZY_KEY], hotspotsWithMeta, totalHotspots, ) @@ -115,31 +118,41 @@ const ClaimAllRewardsScreen = () => { {t('collectablesScreen.hotspots.hotspotsClaimMessage')} - - {hasMore || - (pendingMobileRewards && pendingMobileRewards.gt(new BN(0))) ? ( - - ) : null} - {hasMore || - (pendingIotRewards && pendingIotRewards.gt(new BN(0))) ? ( - - ) : null} - + + + {hasMore || + (pendingHntRewards && pendingHntRewards.gt(new BN(0))) ? ( + + ) : null} + {hasMore || + (pendingMobileRewards && pendingMobileRewards.gt(new BN(0))) ? ( + + ) : null} + {hasMore || + (pendingIotRewards && pendingIotRewards.gt(new BN(0))) ? ( + + ) : null} + + {claimError && ( { const mint = useMemo(() => new PublicKey(hotspot.id), [hotspot.id]) const { submitClaimRewards } = useSubmitTxn() - const { createClaimMobileTx, createClaimIotTx } = useHotspot(mint) + const { createClaimHntTx, createClaimMobileTx, createClaimIotTx } = + useHotspot(mint) const pendingIotRewards = useMemo( () => @@ -51,6 +52,14 @@ const ClaimRewardsScreen = () => { [hotspot], ) + const pendingHntRewards = useMemo( + () => + hotspot && + hotspot.pendingRewards && + new BN(hotspot.pendingRewards[Mints.HNT]), + [hotspot], + ) + const title = useMemo(() => { return t('collectablesScreen.hotspots.claimRewards') }, [t]) @@ -73,6 +82,10 @@ const ClaimRewardsScreen = () => { pendingMobileRewards && !pendingMobileRewards.eq(new BN(0)) ? await createClaimMobileTx() : undefined + const claimHntTx = + pendingHntRewards && !pendingHntRewards.eq(new BN(0)) + ? await createClaimHntTx() + : undefined const transactions: VersionedTransaction[] = [] if (claimIotTx && pendingIotRewards) { @@ -83,6 +96,10 @@ const ClaimRewardsScreen = () => { transactions.push(claimMobileTx) } + if (claimHntTx && pendingHntRewards) { + transactions.push(claimHntTx) + } + if (transactions.length > 0) { await submitClaimRewards(transactions) nav.push('ClaimingRewardsScreen') @@ -103,9 +120,11 @@ const ClaimRewardsScreen = () => { pendingIotRewards && pendingIotRewards.eq(new BN(0)) && pendingMobileRewards && - pendingMobileRewards.eq(new BN(0)) + pendingMobileRewards.eq(new BN(0)) && + pendingHntRewards && + pendingHntRewards.eq(new BN(0)) ) - }, [pendingIotRewards, pendingMobileRewards]) + }, [pendingIotRewards, pendingMobileRewards, pendingHntRewards]) const safeEdges = useMemo(() => ['top'] as Edge[], []) @@ -134,6 +153,14 @@ const ClaimRewardsScreen = () => { justifyContent="center" flexDirection="row" > + {!!pendingHntRewards && pendingHntRewards.gt(new BN(0)) && ( + + )} {!!pendingMobileRewards && pendingMobileRewards.gt(new BN(0)) && ( { const solanaPayment = useSelector( (reduxState: RootState) => reduxState.solana.payment, ) - const { pendingIotRewards, pendingMobileRewards } = useHotspots() + const { pendingIotRewards, pendingMobileRewards, pendingHntRewards } = + useHotspots() const pendingIotRewardsNum = pendingIotRewards ? toNumber(pendingIotRewards, 6) : 0 const pendingMobileRewardsNum = pendingMobileRewards ? toNumber(pendingMobileRewards, 6) : 0 + const pendingHntRewardsNum = pendingHntRewards + ? toNumber(pendingHntRewards, 8) + : 0 const video = - pendingIotRewardsNum && pendingMobileRewardsNum + (pendingIotRewardsNum && pendingMobileRewardsNum) || pendingHntRewardsNum ? iotMobileTokens : pendingMobileRewardsNum ? mobileTokens diff --git a/src/features/collectables/HotspotCompressedListItem.tsx b/src/features/collectables/HotspotCompressedListItem.tsx index bdc7ae2e4..48cf86ef2 100644 --- a/src/features/collectables/HotspotCompressedListItem.tsx +++ b/src/features/collectables/HotspotCompressedListItem.tsx @@ -1,12 +1,13 @@ import IotSymbol from '@assets/images/iotSymbol.svg' import MobileSymbol from '@assets/images/mobileSymbol.svg' +import HntSymbol from '@assets/images/hnt.svg' import { ReAnimatedBox } from '@components/AnimatedBox' import Box from '@components/Box' import ImageBox from '@components/ImageBox' import Text from '@components/Text' import TouchableOpacityBox from '@components/TouchableOpacityBox' import { useMint } from '@helium/helium-react-hooks' -import { IOT_MINT, MOBILE_MINT, toNumber } from '@helium/spl-utils' +import { HNT_MINT, IOT_MINT, MOBILE_MINT, toNumber } from '@helium/spl-utils' import { useHotspotAddress } from '@hooks/useHotspotAddress' import { BoxProps } from '@shopify/restyle' import { Theme } from '@theme/theme' @@ -44,7 +45,7 @@ const HotspotListItem = ({ const { info: iotMint } = useMint(IOT_MINT) const { info: mobileMint } = useMint(MOBILE_MINT) - + const { info: hntMint } = useMint(HNT_MINT) const pendingIotRewards = useMemo( () => hotspot.pendingRewards && new BN(hotspot.pendingRewards[Mints.IOT]), [hotspot], @@ -65,6 +66,11 @@ const HotspotListItem = ({ [hotspot.pendingRewards], ) + const pendingHntRewards = useMemo( + () => hotspot.pendingRewards && new BN(hotspot.pendingRewards[Mints.HNT]), + [hotspot.pendingRewards], + ) + const pendingMobileRewardsString = useMemo(() => { if (!hotspot.pendingRewards) return const num = toNumber( @@ -74,6 +80,15 @@ const HotspotListItem = ({ return formatLargeNumber(new BigNumber(num)) }, [hotspot, mobileMint]) + const pendingHntRewardsString = useMemo(() => { + if (!hotspot.pendingRewards) return + const num = toNumber( + new BN(hotspot.pendingRewards[Mints.HNT]), + hntMint?.decimals || 8, + ) + return formatLargeNumber(new BigNumber(num)) + }, [hotspot, hntMint]) + const eccCompact = useMemo(() => { if (!metadata || !metadata?.attributes?.length) { return undefined @@ -92,6 +107,10 @@ const HotspotListItem = ({ () => pendingMobileRewards && pendingMobileRewards.gt(new BN(0)), [pendingMobileRewards], ) + const hasHntRewards = useMemo( + () => pendingHntRewards && pendingHntRewards.gt(new BN(0)), + [pendingHntRewards], + ) const mobileRecipient = useMemo( () => hotspot?.rewardRecipients?.[Mints.MOBILE], @@ -103,6 +122,11 @@ const HotspotListItem = ({ [hotspot], ) + const hntRecipient = useMemo( + () => hotspot?.rewardRecipients?.[Mints.HNT], + [hotspot], + ) + const hasIotRecipient = useMemo( () => iotRecipient?.destination && @@ -121,9 +145,18 @@ const HotspotListItem = ({ [mobileRecipient, wallet], ) + const hasHntRecipient = useMemo( + () => + hntRecipient?.destination && + wallet && + !new PublicKey(hntRecipient.destination).equals(wallet) && + !new PublicKey(hntRecipient.destination).equals(PublicKey.default), + [hntRecipient, wallet], + ) + const hasRecipientSet = useMemo( - () => hasIotRecipient || hasMobileRecipient, - [hasIotRecipient, hasMobileRecipient], + () => hasIotRecipient || hasMobileRecipient || hasHntRecipient, + [hasIotRecipient, hasMobileRecipient, hasHntRecipient], ) return ( @@ -198,6 +231,24 @@ const HotspotListItem = ({ + {!!hasHntRewards && ( + + + + {pendingHntRewardsString} + + + )} {!!hasMobileRewards && ( { fetchingMore, pendingIotRewards, pendingMobileRewards, + pendingHntRewards, onEndReached, totalHotspots, } = useHotspots() @@ -264,6 +265,11 @@ const HotspotList = () => { p="m" > + { pendingIotRewards.eq(new BN('0')) && pendingMobileRewards && pendingMobileRewards.eq(new BN('0')) && + pendingHntRewards && + pendingHntRewards.eq(new BN('0')) && hotspotsWithMeta.length === (totalHotspots || 0)) || hotspotsWithMeta?.length === 0 } diff --git a/src/features/collectables/HotspotListItem.tsx b/src/features/collectables/HotspotListItem.tsx index e0763855d..a57f70c9f 100644 --- a/src/features/collectables/HotspotListItem.tsx +++ b/src/features/collectables/HotspotListItem.tsx @@ -3,6 +3,7 @@ import { FadeIn, FadeOut } from 'react-native-reanimated' import { BoxProps } from '@shopify/restyle' import IotSymbol from '@assets/images/iotSymbol.svg' import MobileSymbol from '@assets/images/mobileSymbol.svg' +import HntSymbol from '@assets/images/hnt.svg' import BN from 'bn.js' import Text from '@components/Text' import TouchableOpacityBox from '@components/TouchableOpacityBox' @@ -10,7 +11,7 @@ import Box from '@components/Box' import { ReAnimatedBox } from '@components/AnimatedBox' import ImageBox from '@components/ImageBox' import { Theme } from '@theme/theme' -import { IOT_MINT, MOBILE_MINT, toNumber } from '@helium/spl-utils' +import { HNT_MINT, IOT_MINT, MOBILE_MINT, toNumber } from '@helium/spl-utils' import { useMint } from '@helium/helium-react-hooks' import BigNumber from 'bignumber.js' import { useColors } from '@theme/themeHooks' @@ -38,7 +39,7 @@ const HotspotListItem = ({ const { info: iotMint } = useMint(IOT_MINT) const { info: mobileMint } = useMint(MOBILE_MINT) - + const { info: hntMint } = useMint(HNT_MINT) const pendingIotRewards = useMemo( () => hotspot.pendingRewards && new BN(hotspot.pendingRewards[Mints.IOT]), [hotspot.pendingRewards], @@ -57,6 +58,10 @@ const HotspotListItem = ({ hotspot.pendingRewards && new BN(hotspot.pendingRewards[Mints.MOBILE]), [hotspot.pendingRewards], ) + const pendingHntRewards = useMemo( + () => hotspot.pendingRewards && new BN(hotspot.pendingRewards[Mints.HNT]), + [hotspot.pendingRewards], + ) const pendingMobileRewardsString = useMemo(() => { if (!hotspot.pendingRewards) return @@ -67,6 +72,15 @@ const HotspotListItem = ({ return formatLargeNumber(new BigNumber(num)) }, [hotspot, mobileMint]) + const pendingHntRewardsString = useMemo(() => { + if (!hotspot.pendingRewards) return + const num = toNumber( + new BN(hotspot.pendingRewards[Mints.HNT]), + hntMint?.decimals || 8, + ) + return formatLargeNumber(new BigNumber(num)) + }, [hotspot, hntMint]) + const hasIotRewards = useMemo( () => pendingIotRewards && pendingIotRewards.gt(new BN(0)), [pendingIotRewards], @@ -75,6 +89,10 @@ const HotspotListItem = ({ () => pendingMobileRewards && pendingMobileRewards.gt(new BN(0)), [pendingMobileRewards], ) + const hasHntRewards = useMemo( + () => pendingHntRewards && pendingHntRewards.gt(new BN(0)), + [pendingHntRewards], + ) return ( + {!!hasHntRewards && ( + + + {pendingHntRewardsString} + + + + )} {!!hasMobileRewards && ( + hotspotWithMeta?.pendingRewards && + new BN(hotspotWithMeta?.pendingRewards[Mints.HNT]), + [hotspotWithMeta], + ) + + const pendingHntRewardsString = useMemo(() => { + if (!hotspotWithMeta?.pendingRewards) return + const num = toNumber( + new BN(hotspotWithMeta?.pendingRewards[Mints.HNT]), + hntMint?.decimals || 8, + ) + return formatLargeNumber(new BigNumber(num)) + }, [hotspotWithMeta, hntMint]) + const hasIotRewards = useMemo( () => pendingIotRewards && pendingIotRewards.gt(new BN(0)), [pendingIotRewards], @@ -247,9 +265,14 @@ export const HotspotMapHotspotDetails = ({ [pendingMobileRewards], ) + const hasHntRewards = useMemo( + () => pendingHntRewards && pendingHntRewards.gt(new BN(0)), + [pendingHntRewards], + ) + const hasRewards = useMemo( - () => hasIotRewards || hasMobileRewards, - [hasIotRewards, hasMobileRewards], + () => hasIotRewards || hasMobileRewards || hasHntRewards, + [hasIotRewards, hasMobileRewards, hasHntRewards], ) const mobileRecipient = useMemo( @@ -262,6 +285,11 @@ export const HotspotMapHotspotDetails = ({ [hotspotWithMeta], ) + const hntRecipient = useMemo( + () => hotspotWithMeta?.rewardRecipients?.[Mints.HNT], + [hotspotWithMeta], + ) + const hasIotRecipient = useMemo( () => iotRecipient?.destination && @@ -280,9 +308,18 @@ export const HotspotMapHotspotDetails = ({ [mobileRecipient, wallet], ) + const hasHntRecipient = useMemo( + () => + hntRecipient?.destination && + wallet && + !new PublicKey(hntRecipient.destination).equals(wallet) && + !new PublicKey(hntRecipient.destination).equals(PublicKey.default), + [hntRecipient, wallet], + ) + const hasRecipientSet = useMemo( - () => hasIotRecipient || hasMobileRecipient, - [hasIotRecipient, hasMobileRecipient], + () => hasIotRecipient || hasMobileRecipient || hasHntRecipient, + [hasIotRecipient, hasMobileRecipient, hasHntRecipient], ) const isLoading = useMemo( @@ -626,6 +663,31 @@ export const HotspotMapHotspotDetails = ({ // @ts-ignore gap={4} > + {!!hasHntRewards && ( + + + + {pendingHntRewardsString} + + + )} {!!hasMobileRewards && ( Promise createClaimMobileTx: () => Promise + createClaimHntTx: () => Promise iotRewardsLoading: boolean mobileRewardsLoading: boolean + hntRewardsLoading: boolean } { const { anchorProvider: provider } = useSolana() @@ -85,6 +88,39 @@ export function useHotspot(mint: PublicKey): { } }) + const { + error: hntRewardsError, + execute: createClaimHntTx, + loading: hntRewardsLoading, + } = useAsyncCallback(async () => { + if (!provider) return + const program = await init(provider) + const { connection } = provider + + if (mint && program && provider) { + const rewards = await client.getCurrentRewards( + // TODO: Fix program type once HPL is upgraded to anchor v0.26 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + program, + HNT_LAZY_KEY, + mint, + ) + + const tx = await client.formTransaction({ + // TODO: Fix program type once HPL is upgraded to anchor v0.26 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + program, + provider, + rewards, + hotspot: mint, + lazyDistributor: HNT_LAZY_KEY, + assetEndpoint: connection.rpcEndpoint, + }) + + return tx + } + }) + useEffect(() => { if (mobileRewardsError) { Logger.error(mobileRewardsError) @@ -92,6 +128,13 @@ export function useHotspot(mint: PublicKey): { } }, [error, mobileRewardsError]) + useEffect(() => { + if (hntRewardsError) { + Logger.error(hntRewardsError) + setError(hntRewardsError.message) + } + }, [error, hntRewardsError]) + return { createClaimMobileTx, createClaimIotTx, @@ -99,5 +142,8 @@ export function useHotspot(mint: PublicKey): { iotRewardsLoading, iotRewardsError, mobileRewardsError, + createClaimHntTx, + hntRewardsLoading, + hntRewardsError, } } diff --git a/src/hooks/useHotspots.ts b/src/hooks/useHotspots.ts index 64bc97cd4..7087f50c9 100644 --- a/src/hooks/useHotspots.ts +++ b/src/hooks/useHotspots.ts @@ -17,6 +17,7 @@ const useHotspots = (): { totalHotspots: number | undefined pendingIotRewards: BN | undefined pendingMobileRewards: BN | undefined + pendingHntRewards: BN | undefined hotspots: CompressedNFT[] hotspotsWithMeta: HotspotWithPendingRewards[] loading: boolean @@ -203,6 +204,14 @@ const useHotspots = (): { [hotspotsWithMeta], ) + const pendingHntRewards = useMemo( + () => + hotspotsWithMeta?.reduce((acc, hotspot) => { + return acc.add(new BN(hotspot.pendingRewards[Mints.HNT] || '0')) + }, new BN(0)), + [hotspotsWithMeta], + ) + if ( !currentAccount?.solanaAddress || !hotspotsState[currentAccount?.solanaAddress] @@ -211,6 +220,7 @@ const useHotspots = (): { totalHotspots, pendingIotRewards, pendingMobileRewards, + pendingHntRewards, loading: false, hotspots: [], hotspotsWithMeta: [], @@ -226,6 +236,7 @@ const useHotspots = (): { totalHotspots, pendingIotRewards, pendingMobileRewards, + pendingHntRewards, hotspots, hotspotsWithMeta, loading: hotspotsState[currentAccount?.solanaAddress].loading, diff --git a/src/locales/en.ts b/src/locales/en.ts index d84d72352..ae3f5cd13 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -273,7 +273,7 @@ export default { manage: 'Manage', hotspotActions: 'Hotspot Actions', pendingRewards: '{{ amount }} {{ ticker }}', - claimAllRewards: 'Claim all Rewards', + claimAllRewards: 'Claim All Rewards', hotspotClaimMessage: 'Since your last claim, \nyour Hotspot has earned...', hotspotsClaimMessage: diff --git a/src/theme/theme.ts b/src/theme/theme.ts index a440f487f..0f41da099 100644 --- a/src/theme/theme.ts +++ b/src/theme/theme.ts @@ -119,6 +119,7 @@ const palette = { blue950: '#172554', blueBorder: 'rgba(59, 130, 246, 0.25)', hntBlue: '#2755F8', + hntDarkBlue: '#172554', mobileDarkBlue: '#00273D', mobileBlue: '#009EF8', iotDarkGreen: '#053919', diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 2aeff32b7..a08d7762a 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -26,6 +26,7 @@ export const MOBILE_LAZY_KEY = lazyDistributorKey( )[0] export const IOT_LAZY_KEY = lazyDistributorKey(new PublicKey(Mints.IOT))[0] +export const HNT_LAZY_KEY = lazyDistributorKey(new PublicKey(Mints.HNT))[0] export const DAO_KEY = daoKey(HNT_MINT)[0] export const IOT_SUB_DAO_KEY = subDaoKey(IOT_MINT)[0] export const MOBILE_SUB_DAO_KEY = subDaoKey(MOBILE_MINT)[0] diff --git a/src/utils/solanaUtils.ts b/src/utils/solanaUtils.ts index 116f73382..ac03bd296 100644 --- a/src/utils/solanaUtils.ts +++ b/src/utils/solanaUtils.ts @@ -121,7 +121,13 @@ import { } from '../types/solana' import { WrappedConnection } from './WrappedConnection' import { solAddressIsValid } from './accountUtils' -import { DAO_KEY, IOT_LAZY_KEY, MOBILE_LAZY_KEY, Mints } from './constants' +import { + DAO_KEY, + HNT_LAZY_KEY, + IOT_LAZY_KEY, + MOBILE_LAZY_KEY, + Mints, +} from './constants' import { decimalSeparator, groupSeparator } from './i18n' import * as Logger from './logger' import sleep from './sleep' @@ -1086,6 +1092,15 @@ export const getHotspotPendingRewards = async ( true, ) + const hntRewards = await getPendingRewards( + program, + HNT_LAZY_KEY, + dao, + entityKeys, + 'b58', + true, + ) + return hotspots.map((hotspot, index) => { const entityKey = entityKeys[index] @@ -1094,6 +1109,7 @@ export const getHotspotPendingRewards = async ( pendingRewards: { [Mints.MOBILE]: mobileRewards[entityKey], [Mints.IOT]: iotRewards[entityKey], + [Mints.HNT]: hntRewards[entityKey], }, } }) @@ -1113,13 +1129,19 @@ export const getHotspotRecipients = async ( const keyToAssets = hotspots.map((h) => keyToAssetForAsset(toAsset(h))) const ktaAccs = await getCachedKeyToAssets(hemProgram as any, keyToAssets) const assetKeys = ktaAccs.map((kta) => kta.asset) - const [mobileRecipientKeys, iotRecipientKeys] = assetKeys.reduce( - (acc: PublicKey[][], asset) => [ - [...(acc[0] || []), recipientKey(MOBILE_LAZY_KEY, asset)[0]], - [...(acc[1] || []), recipientKey(IOT_LAZY_KEY, asset)[0]], - ], - [], - ) + const [hntRecipientKeys, mobileRecipientKeys, iotRecipientKeys] = + assetKeys.reduce( + (acc: PublicKey[][], asset) => [ + [...(acc[0] || []), recipientKey(HNT_LAZY_KEY, asset)[0]], + [...(acc[1] || []), recipientKey(MOBILE_LAZY_KEY, asset)[0]], + [...(acc[2] || []), recipientKey(IOT_LAZY_KEY, asset)[0]], + ], + [], + ) + + const hntRecipients = + (await program.account.recipientV0.fetchMultiple(hntRecipientKeys || [])) || + [] const mobileRecipients = (await program.account.recipientV0.fetchMultiple( @@ -1136,6 +1158,9 @@ export const getHotspotRecipients = async ( return { id: hotspot.id, recipients: { + [Mints.HNT]: + (hntRecipients?.find((r) => r?.asset.equals(asset)) as RecipientV0) || + undefined, [Mints.MOBILE]: (mobileRecipients?.find((r) => r?.asset.equals(asset), @@ -1348,6 +1373,15 @@ export async function annotateWithPendingRewards( true, ) + const hntRewards = await getPendingRewards( + program, + HNT_LAZY_KEY, + dao, + entityKeys, + 'b58', + true, + ) + const rewardRecipients = await getHotspotRecipients(provider, hotspots) const rewardRecipientsById: { [key: string]: { [key: string]: RecipientV0 } @@ -1367,6 +1401,7 @@ export async function annotateWithPendingRewards( pendingRewards: { [Mints.MOBILE]: mobileRewards[entityKey], [Mints.IOT]: iotRewards[entityKey], + [Mints.HNT]: hntRewards[entityKey], }, rewardRecipients: rewardRecipientsById[hotspot.id] || {}, } as HotspotWithPendingRewards