From 0dfecdba149043d2ad8e0491efc60810b6a0368a Mon Sep 17 00:00:00 2001 From: yurixander <101931215+yurixander@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:00:19 -0400 Subject: [PATCH] feat(tangle-dapp): Create `useLsPoolJoinTx` hook --- .../ExchangeRateDetailItem.tsx | 6 +- .../stakeAndUnstake/LsAgnosticBalance.tsx | 13 ++--- .../stakeAndUnstake/LsStakeCard.tsx | 56 ++++++++++++++----- .../stakeAndUnstake/LsUnstakeCard.tsx | 9 +-- .../stakeAndUnstake/NetworkSelector.tsx | 5 +- .../stakeAndUnstake/TotalDetailItem.tsx | 1 - .../stakeAndUnstake/useLsAgnosticBalance.ts | 31 +++++----- .../stakeAndUnstake/useLsFeePercentage.ts | 2 +- .../stakeAndUnstake/useLsSpendingLimits.ts | 2 +- .../NetworkSelectorDropdown.tsx | 6 +- apps/tangle-dapp/constants/index.ts | 1 + .../{ => parachain}/useMintTx.ts | 6 +- .../{ => parachain}/useParachainBalances.ts | 8 +-- .../{ => parachain}/useParachainLsFees.ts | 4 +- .../{ => parachain}/useRedeemTx.ts | 6 +- .../liquidStaking/tangle/useLsPoolJoinTx.ts | 28 ++++++++++ .../data/liquidStaking/useLsExchangeRate.ts | 28 ++++++---- .../liquidStaking/useLsProtocolEntities.ts | 1 + apps/tangle-dapp/hooks/useApiRx.ts | 6 +- apps/tangle-dapp/hooks/useSubstrateTx.ts | 3 +- apps/tangle-dapp/hooks/useTxNotification.tsx | 1 + .../src/constants/networks.ts | 2 +- 22 files changed, 138 insertions(+), 87 deletions(-) rename apps/tangle-dapp/data/liquidStaking/{ => parachain}/useMintTx.ts (88%) rename apps/tangle-dapp/data/liquidStaking/{ => parachain}/useParachainBalances.ts (89%) rename apps/tangle-dapp/data/liquidStaking/{ => parachain}/useParachainLsFees.ts (85%) rename apps/tangle-dapp/data/liquidStaking/{ => parachain}/useRedeemTx.ts (87%) create mode 100644 apps/tangle-dapp/data/liquidStaking/tangle/useLsPoolJoinTx.ts diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/ExchangeRateDetailItem.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/ExchangeRateDetailItem.tsx index 6ebb815d8..fb1083c54 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/ExchangeRateDetailItem.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/ExchangeRateDetailItem.tsx @@ -3,7 +3,7 @@ import { FC } from 'react'; import { twMerge } from 'tailwind-merge'; import { LS_DERIVATIVE_TOKEN_PREFIX } from '../../../constants/liquidStaking/constants'; -import { LsProtocolId, LsToken } from '../../../constants/liquidStaking/types'; +import { LsToken } from '../../../constants/liquidStaking/types'; import { ExchangeRateType } from '../../../data/liquidStaking/useLsExchangeRate'; import useLsExchangeRate from '../../../data/liquidStaking/useLsExchangeRate'; import DetailItem from './DetailItem'; @@ -11,15 +11,13 @@ import DetailItem from './DetailItem'; export type ExchangeRateDetailItemProps = { type: ExchangeRateType; token: LsToken; - protocolId: LsProtocolId; }; const ExchangeRateDetailItem: FC = ({ type, token, - protocolId, }) => { - const { exchangeRate, isRefreshing } = useLsExchangeRate(type, protocolId); + const { exchangeRate, isRefreshing } = useLsExchangeRate(type); const exchangeRateElement = exchangeRate instanceof Error ? ( diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsAgnosticBalance.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsAgnosticBalance.tsx index f80d19203..a558975dc 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsAgnosticBalance.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsAgnosticBalance.tsx @@ -13,17 +13,14 @@ import { twMerge } from 'tailwind-merge'; import { EMPTY_VALUE_PLACEHOLDER } from '../../../constants'; import { LS_DERIVATIVE_TOKEN_PREFIX } from '../../../constants/liquidStaking/constants'; -import { - LsNetworkId, - LsProtocolId, -} from '../../../constants/liquidStaking/types'; +import { LsNetworkId } from '../../../constants/liquidStaking/types'; import formatBn from '../../../utils/formatBn'; import getLsProtocolDef from '../../../utils/liquidStaking/getLsProtocolDef'; import useLsAgnosticBalance from './useLsAgnosticBalance'; +import { useLsStore } from '../../../data/liquidStaking/useLsStore'; export type LsAgnosticBalanceProps = { isNative?: boolean; - protocolId: LsProtocolId; tooltip?: string; onlyShowTooltipWhenBalanceIsSet?: boolean; onClick?: () => void; @@ -31,14 +28,14 @@ export type LsAgnosticBalanceProps = { const LsAgnosticBalance: FC = ({ isNative = true, - protocolId, tooltip, onlyShowTooltipWhenBalanceIsSet = true, onClick, }) => { const [isHovering, setIsHovering] = useState(false); - const { balance, isRefreshing } = useLsAgnosticBalance(isNative, protocolId); - const protocol = getLsProtocolDef(protocolId); + const { balance, isRefreshing } = useLsAgnosticBalance(isNative); + const { selectedProtocolId } = useLsStore(); + const protocol = getLsProtocolDef(selectedProtocolId); // Special case for liquid tokens on the `TgToken.sol` contract. // See: https://github.com/webb-tools/tnt-core/blob/1f371959884352e7af68e6091c5bb330fcaa58b8/src/lst/liquidtoken/TgToken.sol#L26 diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsStakeCard.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsStakeCard.tsx index 47a9c5a35..15fa7e4cf 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsStakeCard.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsStakeCard.tsx @@ -22,11 +22,12 @@ import { LsProtocolId, LsSearchParamKey, } from '../../../constants/liquidStaking/types'; +import useLsPoolJoinTx from '../../../data/liquidStaking/tangle/useLsPoolJoinTx'; import useLsExchangeRate, { ExchangeRateType, } from '../../../data/liquidStaking/useLsExchangeRate'; import { useLsStore } from '../../../data/liquidStaking/useLsStore'; -import useMintTx from '../../../data/liquidStaking/useMintTx'; +import useMintTx from '../../../data/liquidStaking/parachain/useMintTx'; import useLiquifierDeposit from '../../../data/liquifier/useLiquifierDeposit'; import useActiveAccountAddress from '../../../hooks/useActiveAccountAddress'; import useSearchParamState from '../../../hooks/useSearchParamState'; @@ -51,10 +52,15 @@ const LsStakeCard: FC = () => { stringify: (value) => value?.toString(), }); - const { selectedProtocolId, setSelectedProtocolId, selectedNetworkId } = - useLsStore(); + const { + selectedProtocolId, + setSelectedProtocolId, + selectedNetworkId, + selectedPoolId, + } = useLsStore(); - const { execute: executeMintTx, status: mintTxStatus } = useMintTx(); + const { execute: executeTanglePoolJoinTx } = useLsPoolJoinTx(); + const { execute: executeParachainMintTx, status: mintTxStatus } = useMintTx(); const performLiquifierDeposit = useLiquifierDeposit(); const activeAccountAddress = useActiveAccountAddress(); @@ -86,15 +92,17 @@ const LsStakeCard: FC = () => { const { exchangeRate: exchangeRateOrError, isRefreshing: isRefreshingExchangeRate, - } = useLsExchangeRate( - ExchangeRateType.NativeToDerivative, - selectedProtocolId, - ); + } = useLsExchangeRate(ExchangeRateType.NativeToDerivative); // TODO: Properly handle the error state. const exchangeRate = exchangeRateOrError instanceof Error ? null : exchangeRateOrError; + const isTangleNetwork = + selectedNetworkId === LsNetworkId.TANGLE_LOCAL || + selectedNetworkId === LsNetworkId.TANGLE_MAINNET || + selectedNetworkId === LsNetworkId.TANGLE_TESTNET; + const handleStakeClick = useCallback(async () => { // Not ready yet; no amount given. if (fromAmount === null) { @@ -103,9 +111,9 @@ const LsStakeCard: FC = () => { if ( selectedProtocol.networkId === LsNetworkId.TANGLE_RESTAKING_PARACHAIN && - executeMintTx !== null + executeParachainMintTx !== null ) { - executeMintTx({ + executeParachainMintTx({ amount: fromAmount, currency: selectedProtocol.currency, }); @@ -114,8 +122,25 @@ const LsStakeCard: FC = () => { performLiquifierDeposit !== null ) { await performLiquifierDeposit(selectedProtocol.id, fromAmount); + } else if ( + isTangleNetwork && + executeTanglePoolJoinTx !== null && + selectedPoolId !== null + ) { + executeTanglePoolJoinTx({ + amount: fromAmount, + poolId: selectedPoolId, + }); } - }, [executeMintTx, fromAmount, performLiquifierDeposit, selectedProtocol]); + }, [ + executeParachainMintTx, + executeTanglePoolJoinTx, + fromAmount, + isTangleNetwork, + performLiquifierDeposit, + selectedProtocol, + selectedPoolId, + ]); const toAmount = useMemo(() => { if (fromAmount === null || exchangeRate === null) { @@ -128,13 +153,15 @@ const LsStakeCard: FC = () => { const canCallStake = (fromAmount !== null && selectedProtocol.networkId === LsNetworkId.TANGLE_RESTAKING_PARACHAIN && - executeMintTx !== null) || + executeParachainMintTx !== null) || (selectedProtocol.networkId === LsNetworkId.ETHEREUM_MAINNET_LIQUIFIER && - performLiquifierDeposit !== null); + performLiquifierDeposit !== null) || + (isTangleNetwork && + executeTanglePoolJoinTx !== null && + selectedPoolId !== null); const walletBalance = ( { if (maxSpendable !== null) { @@ -187,7 +214,6 @@ const LsStakeCard: FC = () => { diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsUnstakeCard.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsUnstakeCard.tsx index f1616327e..b37a5361a 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsUnstakeCard.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/LsUnstakeCard.tsx @@ -20,7 +20,7 @@ import useLsExchangeRate, { ExchangeRateType, } from '../../../data/liquidStaking/useLsExchangeRate'; import { useLsStore } from '../../../data/liquidStaking/useLsStore'; -import useRedeemTx from '../../../data/liquidStaking/useRedeemTx'; +import useRedeemTx from '../../../data/liquidStaking/parachain/useRedeemTx'; import useLiquifierUnlock from '../../../data/liquifier/useLiquifierUnlock'; import useActiveAccountAddress from '../../../hooks/useActiveAccountAddress'; import useSearchParamSync from '../../../hooks/useSearchParamSync'; @@ -80,10 +80,7 @@ const LsUnstakeCard: FC = () => { const { exchangeRate: exchangeRateOrError, isRefreshing: isRefreshingExchangeRate, - } = useLsExchangeRate( - ExchangeRateType.DerivativeToNative, - selectedProtocol.id, - ); + } = useLsExchangeRate(ExchangeRateType.DerivativeToNative); // TODO: Properly handle the error state. const exchangeRate = @@ -159,7 +156,6 @@ const LsUnstakeCard: FC = () => { const stakedWalletBalance = ( setFromAmount(maxSpendable)} /> @@ -213,7 +209,6 @@ const LsUnstakeCard: FC = () => { diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/NetworkSelector.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/NetworkSelector.tsx index d09eec2fb..3ff8d4a65 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/NetworkSelector.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/NetworkSelector.tsx @@ -52,10 +52,7 @@ const NetworkSelector: FC = ({ // Filter out networks that don't support liquid staking yet. const supportedLsNetworks = LS_NETWORKS.filter((network) => { - // TODO: Check whether the restaking parachain supports liquid staking instead of hardcoding it. - if (network.id === LsNetworkId.TANGLE_RESTAKING_PARACHAIN) { - return true; - } else if (network.id === LsNetworkId.ETHEREUM_MAINNET_LIQUIFIER) { + if (network.id === LsNetworkId.ETHEREUM_MAINNET_LIQUIFIER) { return true; } // Exclude the local Tangle network in production. diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/TotalDetailItem.tsx b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/TotalDetailItem.tsx index 31041abb7..86a19cff2 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/TotalDetailItem.tsx +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/TotalDetailItem.tsx @@ -30,7 +30,6 @@ const TotalDetailItem: FC = ({ isMinting ? ExchangeRateType.NativeToDerivative : ExchangeRateType.DerivativeToNative, - protocolId, ); const protocol = getLsProtocolDef(protocolId); diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsAgnosticBalance.ts b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsAgnosticBalance.ts index fe139a4ed..2a3045e03 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsAgnosticBalance.ts +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsAgnosticBalance.ts @@ -4,17 +4,15 @@ import { erc20Abi } from 'viem'; import { EMPTY_VALUE_PLACEHOLDER } from '../../../constants'; import LIQUIFIER_TG_TOKEN_ABI from '../../../constants/liquidStaking/liquifierTgTokenAbi'; -import { - LsNetworkId, - LsProtocolId, -} from '../../../constants/liquidStaking/types'; +import { LsNetworkId } from '../../../constants/liquidStaking/types'; import useBalances from '../../../data/balances/useBalances'; -import useParachainBalances from '../../../data/liquidStaking/useParachainBalances'; +import useParachainBalances from '../../../data/liquidStaking/parachain/useParachainBalances'; import usePolling from '../../../data/liquidStaking/usePolling'; import useContractReadOnce from '../../../data/liquifier/useContractReadOnce'; import useActiveAccountAddress from '../../../hooks/useActiveAccountAddress'; import useEvmAddress20 from '../../../hooks/useEvmAddress'; import getLsProtocolDef from '../../../utils/liquidStaking/getLsProtocolDef'; +import { useLsStore } from '../../../data/liquidStaking/useLsStore'; type BalanceUpdater = ( prevBalance: BN | null | typeof EMPTY_VALUE_PLACEHOLDER, @@ -47,11 +45,12 @@ const createBalanceStateUpdater = ( }; }; -const useLsAgnosticBalance = (isNative: boolean, protocolId: LsProtocolId) => { +const useLsAgnosticBalance = (isNative: boolean) => { const activeAccountAddress = useActiveAccountAddress(); const evmAddress20 = useEvmAddress20(); const { nativeBalances, liquidBalances } = useParachainBalances(); - const { free: tangleBalance } = useBalances(); + const { free: tangleFreeBalance } = useBalances(); + const { selectedProtocolId, selectedNetworkId } = useLsStore(); // TODO: Why not use the subscription hook variants (useContractRead) instead of manually utilizing usePolling? const readErc20 = useContractReadOnce(erc20Abi); @@ -63,7 +62,7 @@ const useLsAgnosticBalance = (isNative: boolean, protocolId: LsProtocolId) => { const parachainBalances = isNative ? nativeBalances : liquidBalances; const isAccountConnected = activeAccountAddress !== null; - const protocol = getLsProtocolDef(protocolId); + const protocol = getLsProtocolDef(selectedProtocolId); // Reset balance to a placeholder when the active account is // disconnected, and to a loading state once an account is @@ -77,7 +76,7 @@ const useLsAgnosticBalance = (isNative: boolean, protocolId: LsProtocolId) => { if (isAccountConnected) { setBalance(null); } - }, [isAccountConnected, isNative, protocolId]); + }, [isAccountConnected, isNative, selectedProtocolId]); const erc20BalanceFetcher = useCallback(() => { if ( @@ -132,18 +131,20 @@ const useLsAgnosticBalance = (isNative: boolean, protocolId: LsProtocolId) => { setBalance(createBalanceStateUpdater(newBalance)); }, [parachainBalances, protocol.token, protocol.networkId]); + const isLsTangleNetwork = + selectedNetworkId === LsNetworkId.TANGLE_LOCAL || + selectedNetworkId === LsNetworkId.TANGLE_MAINNET || + selectedNetworkId === LsNetworkId.TANGLE_TESTNET; + // Update the balance to the Tangle balance when the Tangle // network is the active network. useEffect(() => { - if ( - protocol.networkId !== LsNetworkId.TANGLE_MAINNET || - tangleBalance === null - ) { + if (!isLsTangleNetwork || tangleFreeBalance === null) { return; } - setBalance(createBalanceStateUpdater(tangleBalance)); - }, [protocol.networkId, tangleBalance]); + setBalance(createBalanceStateUpdater(tangleFreeBalance)); + }, [protocol.networkId, tangleFreeBalance, isLsTangleNetwork]); return { balance, isRefreshing }; }; diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsFeePercentage.ts b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsFeePercentage.ts index 397c3a40e..e7351fb7d 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsFeePercentage.ts +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsFeePercentage.ts @@ -6,7 +6,7 @@ import { LsNetworkId, LsProtocolId, } from '../../../constants/liquidStaking/types'; -import useParachainLsFees from '../../../data/liquidStaking/useParachainLsFees'; +import useParachainLsFees from '../../../data/liquidStaking/parachain/useParachainLsFees'; import useContractRead from '../../../data/liquifier/useContractRead'; import { ContractReadOptions } from '../../../data/liquifier/useContractReadOnce'; import getLsProtocolDef from '../../../utils/liquidStaking/getLsProtocolDef'; diff --git a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsSpendingLimits.ts b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsSpendingLimits.ts index efe9f2d75..ed3ef1933 100644 --- a/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsSpendingLimits.ts +++ b/apps/tangle-dapp/components/LiquidStaking/stakeAndUnstake/useLsSpendingLimits.ts @@ -20,7 +20,7 @@ const useLsSpendingLimits = ( isNative: boolean, protocolId: LsProtocolId, ): LsSpendingLimits => { - const { balance } = useLsAgnosticBalance(isNative, protocolId); + const { balance } = useLsAgnosticBalance(isNative); const { result: existentialDepositAmount } = useApi( useCallback((api) => api.consts.balances.existentialDeposit, []), diff --git a/apps/tangle-dapp/components/NetworkSelector/NetworkSelectorDropdown.tsx b/apps/tangle-dapp/components/NetworkSelector/NetworkSelectorDropdown.tsx index 6b12d7748..497ebdc04 100644 --- a/apps/tangle-dapp/components/NetworkSelector/NetworkSelectorDropdown.tsx +++ b/apps/tangle-dapp/components/NetworkSelector/NetworkSelectorDropdown.tsx @@ -30,14 +30,14 @@ export const NetworkSelectorDropdown: FC = ({ }) => { return (
- {/* Mainnet network */} + {/* Tangle Mainnet */} onNetworkChange(TANGLE_MAINNET_NETWORK)} /> - {/* Testnet network */} + {/* Tangle Testnet */} = ({
- {/* Local dev network */} + {/* Tangle Local Dev */} { const activeSubstrateAddress = useSubstrateAddress(); diff --git a/apps/tangle-dapp/data/liquidStaking/useParachainLsFees.ts b/apps/tangle-dapp/data/liquidStaking/parachain/useParachainLsFees.ts similarity index 85% rename from apps/tangle-dapp/data/liquidStaking/useParachainLsFees.ts rename to apps/tangle-dapp/data/liquidStaking/parachain/useParachainLsFees.ts index b82a6577b..24b0811b4 100644 --- a/apps/tangle-dapp/data/liquidStaking/useParachainLsFees.ts +++ b/apps/tangle-dapp/data/liquidStaking/parachain/useParachainLsFees.ts @@ -2,8 +2,8 @@ import { TANGLE_RESTAKING_PARACHAIN_LOCAL_DEV_NETWORK } from '@webb-tools/webb-u import { useCallback } from 'react'; import { map } from 'rxjs'; -import useApiRx from '../../hooks/useApiRx'; -import permillToPercentage from '../../utils/permillToPercentage'; +import useApiRx from '../../../hooks/useApiRx'; +import permillToPercentage from '../../../utils/permillToPercentage'; const useParachainLsFees = () => { return useApiRx( diff --git a/apps/tangle-dapp/data/liquidStaking/useRedeemTx.ts b/apps/tangle-dapp/data/liquidStaking/parachain/useRedeemTx.ts similarity index 87% rename from apps/tangle-dapp/data/liquidStaking/useRedeemTx.ts rename to apps/tangle-dapp/data/liquidStaking/parachain/useRedeemTx.ts index 9cfa6758f..8dbc610e6 100644 --- a/apps/tangle-dapp/data/liquidStaking/useRedeemTx.ts +++ b/apps/tangle-dapp/data/liquidStaking/parachain/useRedeemTx.ts @@ -5,12 +5,12 @@ import '@webb-tools/tangle-restaking-types'; import { BN } from '@polkadot/util'; import { TANGLE_RESTAKING_PARACHAIN_LOCAL_DEV_NETWORK } from '@webb-tools/webb-ui-components/constants/networks'; -import { TxName } from '../../constants'; +import { TxName } from '../../../constants'; import { LsParachainCurrencyKey, ParachainCurrency, -} from '../../constants/liquidStaking/types'; -import { useSubstrateTxWithNotification } from '../../hooks/useSubstrateTx'; +} from '../../../constants/liquidStaking/types'; +import { useSubstrateTxWithNotification } from '../../../hooks/useSubstrateTx'; export type RedeemTxContext = { amount: BN; diff --git a/apps/tangle-dapp/data/liquidStaking/tangle/useLsPoolJoinTx.ts b/apps/tangle-dapp/data/liquidStaking/tangle/useLsPoolJoinTx.ts new file mode 100644 index 000000000..5f7eb0bda --- /dev/null +++ b/apps/tangle-dapp/data/liquidStaking/tangle/useLsPoolJoinTx.ts @@ -0,0 +1,28 @@ +import { BN } from '@polkadot/util'; +import { useCallback } from 'react'; + +import { TxName } from '../../../constants'; +import { + SubstrateTxFactory, + useSubstrateTxWithNotification, +} from '../../../hooks/useSubstrateTx'; + +export type LsPoolJoinTxContext = { + poolId: number; + amount: BN; +}; + +const useLsPoolJoinTx = () => { + const substrateTxFactory: SubstrateTxFactory = + useCallback(async (api, _activeSubstrateAddress, { poolId, amount }) => { + return api.tx.lst.join(amount, poolId); + }, []); + + // TODO: Add EVM support once precompile(s) for the `lst` pallet are implemented on Tangle. + return useSubstrateTxWithNotification( + TxName.LS_TANGLE_POOL_JOIN, + substrateTxFactory, + ); +}; + +export default useLsPoolJoinTx; diff --git a/apps/tangle-dapp/data/liquidStaking/useLsExchangeRate.ts b/apps/tangle-dapp/data/liquidStaking/useLsExchangeRate.ts index 334434f8a..513ea30fe 100644 --- a/apps/tangle-dapp/data/liquidStaking/useLsExchangeRate.ts +++ b/apps/tangle-dapp/data/liquidStaking/useLsExchangeRate.ts @@ -8,7 +8,6 @@ import LIQUIFIER_TG_TOKEN_ABI from '../../constants/liquidStaking/liquifierTgTok import { LsNetworkId, LsParachainCurrencyKey, - LsProtocolId, } from '../../constants/liquidStaking/types'; import useApiRx from '../../hooks/useApiRx'; import calculateBnRatio from '../../utils/calculateBnRatio'; @@ -16,6 +15,7 @@ import getLsProtocolDef from '../../utils/liquidStaking/getLsProtocolDef'; import useContractRead from '../liquifier/useContractRead'; import { ContractReadOptions } from '../liquifier/useContractReadOnce'; import usePolling from './usePolling'; +import { useLsStore } from './useLsStore'; export enum ExchangeRateType { NativeToDerivative, @@ -47,13 +47,11 @@ const computeExchangeRate = ( const MAX_BN_OPERATION_NUMBER = 2 ** 26 - 1; -const useLsExchangeRate = ( - type: ExchangeRateType, - protocolId: LsProtocolId, -) => { +const useLsExchangeRate = (type: ExchangeRateType) => { const [exchangeRate, setExchangeRate] = useState(null); + const { selectedProtocolId, selectedNetworkId } = useLsStore(); - const protocol = getLsProtocolDef(protocolId); + const protocol = getLsProtocolDef(selectedProtocolId); const { result: tokenPoolAmount } = useApiRx((api) => { if (protocol.networkId !== LsNetworkId.TANGLE_RESTAKING_PARACHAIN) { @@ -144,10 +142,20 @@ const useLsExchangeRate = ( }, [liquifierTotalShares, tgTokenTotalSupply, type]); const fetch = useCallback(async () => { - const promise = - protocol.networkId === LsNetworkId.TANGLE_RESTAKING_PARACHAIN - ? parachainExchangeRate - : fetchLiquifierExchangeRate(); + let promise: Promise; + + switch (selectedNetworkId) { + case LsNetworkId.ETHEREUM_MAINNET_LIQUIFIER: + promise = fetchLiquifierExchangeRate(); + case LsNetworkId.TANGLE_RESTAKING_PARACHAIN: + promise = parachainExchangeRate; + // Tangle networks with the `lst` pallet have a fixed exchange + // rate of 1:1. + case LsNetworkId.TANGLE_LOCAL: + case LsNetworkId.TANGLE_MAINNET: + case LsNetworkId.TANGLE_TESTNET: + promise = Promise.resolve(1); + } const newExchangeRate = await promise; diff --git a/apps/tangle-dapp/data/liquidStaking/useLsProtocolEntities.ts b/apps/tangle-dapp/data/liquidStaking/useLsProtocolEntities.ts index b2ae069ab..fa02539dc 100644 --- a/apps/tangle-dapp/data/liquidStaking/useLsProtocolEntities.ts +++ b/apps/tangle-dapp/data/liquidStaking/useLsProtocolEntities.ts @@ -76,6 +76,7 @@ const getDataType = (chain: LsProtocolId): LiquidStakingItem | null => { case LsProtocolId.THE_GRAPH: case LsProtocolId.TANGLE_MAINNET: case LsProtocolId.TANGLE_TESTNET: + case LsProtocolId.TANGLE_LOCAL: return null; } }; diff --git a/apps/tangle-dapp/hooks/useApiRx.ts b/apps/tangle-dapp/hooks/useApiRx.ts index 45e66171a..dd2ecd3ff 100644 --- a/apps/tangle-dapp/hooks/useApiRx.ts +++ b/apps/tangle-dapp/hooks/useApiRx.ts @@ -32,7 +32,7 @@ export type ObservableFactory = (api: ApiRx) => Observable | null; */ function useApiRx( factory: ObservableFactory, - overrideRpcEndpoint?: string, + rpcEndpointOverride?: string, ) { const [result, setResult] = useState(null); const [isLoading, setLoading] = useState(true); @@ -43,8 +43,8 @@ function useApiRx( const { result: apiRx } = usePromise( useCallback( - () => getApiRx(overrideRpcEndpoint ?? rpcEndpoint), - [overrideRpcEndpoint, rpcEndpoint], + () => getApiRx(rpcEndpointOverride ?? rpcEndpoint), + [rpcEndpointOverride, rpcEndpoint], ), null, ); diff --git a/apps/tangle-dapp/hooks/useSubstrateTx.ts b/apps/tangle-dapp/hooks/useSubstrateTx.ts index 7e4a30b79..184478a43 100644 --- a/apps/tangle-dapp/hooks/useSubstrateTx.ts +++ b/apps/tangle-dapp/hooks/useSubstrateTx.ts @@ -232,8 +232,7 @@ export function useSubstrateTxWithNotification( overrideRpcEndpoint, ); - const { notifyProcessing, notifySuccess, notifyError } = - useTxNotification(txName); + const { notifyProcessing, notifySuccess, notifyError } = useTxNotification(); const execute = useCallback( (context: Context) => { diff --git a/apps/tangle-dapp/hooks/useTxNotification.tsx b/apps/tangle-dapp/hooks/useTxNotification.tsx index 109654034..6c05ff185 100644 --- a/apps/tangle-dapp/hooks/useTxNotification.tsx +++ b/apps/tangle-dapp/hooks/useTxNotification.tsx @@ -36,6 +36,7 @@ const SUCCESS_MESSAGES: Record = { [TxName.LS_LIQUIFIER_APPROVE]: 'Liquifier approval successful', [TxName.LS_LIQUIFIER_UNLOCK]: 'Liquifier unlock successful', [TxName.LS_LIQUIFIER_WITHDRAW]: 'Liquifier withdrawal successful', + [TxName.LS_TANGLE_POOL_JOIN]: 'Joined liquid staking pool', }; const makeKey = (txName: TxName): `${TxName}-tx-notification` => diff --git a/libs/webb-ui-components/src/constants/networks.ts b/libs/webb-ui-components/src/constants/networks.ts index b6f7db91c..9781dafa2 100644 --- a/libs/webb-ui-components/src/constants/networks.ts +++ b/libs/webb-ui-components/src/constants/networks.ts @@ -99,7 +99,7 @@ export const TANGLE_LOCAL_DEV_NETWORK = { id: NetworkId.TANGLE_LOCAL_DEV, substrateChainId: SubstrateChainId.TangleLocalNative, evmChainId: EVMChainId.TangleLocalEVM, - name: 'Local endpoint', + name: 'Tangle Local Dev', tokenSymbol: TANGLE_TESTNET_NATIVE_TOKEN_SYMBOL, nodeType: 'standalone', subqueryEndpoint: 'http://localhost:4000/graphql',