Skip to content

Commit

Permalink
fix: [lw-11876]: show upgrade to lace in send flow in locked rewards …
Browse files Browse the repository at this point in the history
…available
  • Loading branch information
vetalcore committed Dec 2, 2024
1 parent 24a5a90 commit 0a17872
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 46 deletions.
6 changes: 3 additions & 3 deletions apps/browser-extension-wallet/src/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import * as ReactDOM from 'react-dom';
import { HashRouter } from 'react-router-dom';
import { PopupView } from '@routes';
import { PopupView, walletRoutePaths } from '@routes';
import { StoreProvider } from '@stores';
import { CurrencyStoreProvider } from '@providers/currency';
import { AppSettingsProvider, DatabaseProvider, ThemeProvider, AnalyticsProvider } from '@providers';
Expand Down Expand Up @@ -34,8 +34,8 @@ const App = (): React.ReactElement => {
const newModeValue = changes.BACKGROUND_STORAGE?.newValue?.namiMigration;
if (oldModeValue?.mode !== newModeValue?.mode) {
setMode(newModeValue);
// Force back to original routing
window.location.hash = '#';
// Force back to original routing unless it is staking route (see LW-11876)
if (window.location.hash.split('#')[1] !== walletRoutePaths.earn) window.location.hash = '#';
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { useDelegationStore } from '@src/features/delegation/stores';
import { useWalletStore } from '@stores';
import { withSignTxConfirmation } from '@lib/wallet-api-ui';
import { useSecrets } from '@lace/core';
import { useObservable } from '@lace/common';
import { Wallet } from '@lace/cardano';

interface UseRewardAccountsDataType {
accountsWithRegisteredStakeCredsWithoutVotingDelegation: Wallet.Cardano.RewardAccountInfo[];
accountsWithRegisteredStakeCreds: Wallet.Cardano.RewardAccountInfo[];
poolIdToRewardAccountMap: Map<string, Wallet.Cardano.RewardAccountInfo>;
lockedStakeRewards: bigint;
}

export const useDelegationTransaction = (): { signAndSubmitTransaction: () => Promise<void> } => {
const { password, clearSecrets } = useSecrets();
Expand All @@ -17,3 +26,54 @@ export const useDelegationTransaction = (): { signAndSubmitTransaction: () => Pr

return { signAndSubmitTransaction };
};

export const getPoolIdToRewardAccountMap = (
rewardAccounts: Wallet.Cardano.RewardAccountInfo[]
): UseRewardAccountsDataType['poolIdToRewardAccountMap'] =>
new Map(
rewardAccounts
?.map((rewardAccount): [string, Wallet.Cardano.RewardAccountInfo] => {
const { delegatee } = rewardAccount;
const delagationInfo = delegatee?.nextNextEpoch || delegatee?.nextEpoch || delegatee?.currentEpoch;

return [delagationInfo?.id.toString(), rewardAccount];
})
.filter(([poolId]) => !!poolId)
);

export const useRewardAccountsData = (): UseRewardAccountsDataType => {
const { inMemoryWallet } = useWalletStore();
const rewardAccounts = useObservable(inMemoryWallet.delegation.rewardAccounts$);
const accountsWithRegisteredStakeCreds = rewardAccounts?.filter(
({ credentialStatus }) => Wallet.Cardano.StakeCredentialStatus.Registered === credentialStatus
);

const accountsWithRegisteredStakeCredsWithoutVotingDelegation = useMemo(
() => accountsWithRegisteredStakeCreds?.filter(({ dRepDelegatee }) => !dRepDelegatee),
[accountsWithRegisteredStakeCreds]
);

const lockedStakeRewards = useMemo(
() =>
BigInt(
accountsWithRegisteredStakeCredsWithoutVotingDelegation
? Wallet.BigIntMath.sum(
accountsWithRegisteredStakeCredsWithoutVotingDelegation.map(({ rewardBalance }) => rewardBalance)
)
: 0
),
[accountsWithRegisteredStakeCredsWithoutVotingDelegation]
);

const poolIdToRewardAccountMap = useMemo(
() => getPoolIdToRewardAccountMap(accountsWithRegisteredStakeCreds),
[accountsWithRegisteredStakeCreds]
);

return {
accountsWithRegisteredStakeCreds,
accountsWithRegisteredStakeCredsWithoutVotingDelegation,
lockedStakeRewards,
poolIdToRewardAccountMap
};
};
14 changes: 11 additions & 3 deletions apps/browser-extension-wallet/src/views/nami-mode/NamiView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ import {
useWalletManager,
useBuildDelegation,
useBalances,
useHandleResolver
useHandleResolver,
useRedirection
} from '@hooks';
import { walletManager, withSignTxConfirmation } from '@lib/wallet-api-ui';
import { useAnalytics } from './hooks';
import { useDappContext, withDappContext } from '@src/features/dapp/context';
import { localDappService } from '../browser-view/features/dapp/components/DappList/localDappService';
import { isValidURL } from '@src/utils/is-valid-url';
import { CARDANO_COIN_SYMBOL } from './constants';
import { useDelegationTransaction } from '../browser-view/features/staking/hooks';
import { useDelegationTransaction, useRewardAccountsData } from '../browser-view/features/staking/hooks';
import { useSecrets } from '@lace/core';
import { useDelegationStore } from '@src/features/delegation/stores';
import { useStakePoolDetails } from '@src/features/stake-pool-details/store';
Expand All @@ -42,6 +43,7 @@ import { isKeyHashAddress } from '@cardano-sdk/wallet';
import { BackgroundStorage } from '@lib/scripts/types';
import { getWalletAccountsQtyString } from '@src/utils/get-wallet-count-string';
import { useNetworkError } from '@hooks/useNetworkError';
import { walletRoutePaths } from '@routes';

const { AVAILABLE_CHAINS, DEFAULT_SUBMIT_API } = config();

Expand Down Expand Up @@ -177,6 +179,10 @@ export const NamiView = withDappContext((): React.ReactElement => {
setDeletingWallet(false);
}, [analytics, deleteWallet, setDeletingWallet, walletRepository]);

const { lockedStakeRewards } = useRewardAccountsData();

const redirectToStaking = useRedirection(walletRoutePaths.earn);

return (
<OutsideHandlesProvider
{...{
Expand Down Expand Up @@ -235,7 +241,9 @@ export const NamiView = withDappContext((): React.ReactElement => {
setDeletingWallet,
chainHistoryProvider,
protocolParameters: walletState?.protocolParameters,
assetInfo: walletState?.assetInfo
assetInfo: walletState?.assetInfo,
lockedStakeRewards,
redirectToStaking
}}
>
<CommonOutsideHandlesProvider
Expand Down
2 changes: 2 additions & 0 deletions packages/nami/src/features/outside-handles-provider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,6 @@ export interface OutsideHandlesContextValue {
chainHistoryProvider: Wallet.ChainHistoryProvider;
protocolParameters: Wallet.Cardano.ProtocolParameters;
assetInfo: Wallet.Assets;
lockedStakeRewards: bigint;
redirectToStaking: () => void;
}
86 changes: 86 additions & 0 deletions packages/nami/src/ui/app/components/upgradeToLaceBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';

import { Box, Button, Text, Link, useColorModeValue } from '@chakra-ui/react';
import { AnimatePresence, motion } from 'framer-motion';

import { useOutsideHandles } from '../../../features/outside-handles-provider';

export const UpgradeToLaceBanner = ({
showSwitchToLaceBanner,
}: Readonly<{ showSwitchToLaceBanner: boolean }>) => {
const warningBackground = useColorModeValue('#fcf5e3', '#fcf5e3');
const { openExternalLink, switchWalletMode, redirectToStaking } =
useOutsideHandles();

return (
<AnimatePresence>
{showSwitchToLaceBanner && (
<motion.div
key="splashScreen"
initial={{
y: '-224px',
height: '0px',
marginBottom: 0,
}}
animate={{
y: '0px',
height: '224px',
marginBottom: '1.25rem',
}}
transition={{
all: { duration: 5, ease: 'easeInOut' },
}}
exit={{
y: '-224px',
height: '0px',
marginBottom: 0,
}}
>
<Box
display="flex"
alignItems="center"
justifyContent="flex-end"
flexDirection="column"
background={warningBackground}
rounded="xl"
padding="18"
gridGap="8px"
mb="4"
overflow="hidden"
>
<Text
color="gray.800"
fontSize="14"
fontWeight="500"
lineHeight="24px"
>
Your ADA balance includes Locked Stake Rewards that can only be
withdrawn or transacted after registering your voting power.
Upgrade to Lace to continue. For more information, visit our{' '}
<Link
isExternal
textDecoration="underline"
onClick={() => {
openExternalLink('https://www.lace.io/faq');
}}
>
FAQs.
</Link>
</Text>
<Button
height="36px"
width="100%"
colorScheme="teal"
onClick={async () => {
redirectToStaking();
await switchWalletMode();
}}
>
Upgrade to Lace
</Button>
</Box>
</motion.div>
)}
</AnimatePresence>
);
};
Loading

0 comments on commit 0a17872

Please sign in to comment.