@@ -192,6 +197,20 @@ const LiquidStakingPage: FC = () => {
);
})}
+
+ {/**
+ * TODO: Check what's the min. amount required to create a new pool. If the free balance doesn't meet the min, disable the button and show a tooltip with the reason.
+ */}
+
{/* Tabs Content */}
diff --git a/apps/tangle-dapp/components/AddressInput/AddressInput.tsx b/apps/tangle-dapp/components/AddressInput/AddressInput.tsx
index d1e403072..38ab6c1b6 100644
--- a/apps/tangle-dapp/components/AddressInput/AddressInput.tsx
+++ b/apps/tangle-dapp/components/AddressInput/AddressInput.tsx
@@ -17,6 +17,7 @@ export type AddressInputProps = {
id: string;
title: string;
placeholder?: string;
+ tooltip?: string;
type: AddressType;
showPasteButton?: boolean;
value: string;
@@ -29,6 +30,7 @@ export type AddressInputProps = {
const AddressInput: FC = ({
id,
title,
+ tooltip,
placeholder,
type,
value,
@@ -104,6 +106,7 @@ const AddressInput: FC = ({
= ({
setAmount,
min = null,
max = null,
- decimals = TANGLE_TOKEN_DECIMALS, // Default to the Tangle token decimals.
+ // Default to the Tangle token decimals.
+ decimals = TANGLE_TOKEN_DECIMALS,
minErrorMessage,
maxErrorMessage,
showMaxAction = true,
diff --git a/apps/tangle-dapp/components/LiquidStaking/ExternalLink.tsx b/apps/tangle-dapp/components/LiquidStaking/ExternalLink.tsx
index 6faf77969..c7b229aed 100644
--- a/apps/tangle-dapp/components/LiquidStaking/ExternalLink.tsx
+++ b/apps/tangle-dapp/components/LiquidStaking/ExternalLink.tsx
@@ -21,9 +21,7 @@ const ExternalLink: FC = ({
target="_blank"
size="sm"
variant="link"
- rightIcon={
-
- }
+ rightIcon={}
>
{children}
diff --git a/apps/tangle-dapp/components/LiquidStaking/LsMyPoolsTable.tsx b/apps/tangle-dapp/components/LiquidStaking/LsMyPoolsTable.tsx
index f4c91e85e..4dfab053a 100644
--- a/apps/tangle-dapp/components/LiquidStaking/LsMyPoolsTable.tsx
+++ b/apps/tangle-dapp/components/LiquidStaking/LsMyPoolsTable.tsx
@@ -243,6 +243,7 @@ const LsMyPoolsTable: FC = ({ pools, isShown }) => {
return (
= ({
title,
subtitle,
tooltip,
- largeSubtitle = false,
removeBorder = false,
}) => {
const className = cx('flex flex-col items-start justify-center px-3', {
@@ -26,13 +24,13 @@ const StatItem: FC = ({
return (
-
+
{title}
diff --git a/apps/tangle-dapp/constants/index.ts b/apps/tangle-dapp/constants/index.ts
index 2b6cb6ad0..fdc2fc7c8 100644
--- a/apps/tangle-dapp/constants/index.ts
+++ b/apps/tangle-dapp/constants/index.ts
@@ -63,6 +63,7 @@ export enum TxName {
LS_LIQUIFIER_WITHDRAW = 'liquifier withdraw',
LS_TANGLE_POOL_JOIN = 'join liquid staking pool',
LS_TANGLE_POOL_UNBOND = 'unbond from liquid staking pool',
+ LS_TANGLE_POOL_CREATE = 'create liquid staking pool',
}
export const PAYMENT_DESTINATION_OPTIONS: StakingRewardsDestinationDisplayText[] =
diff --git a/apps/tangle-dapp/containers/LsCreatePoolModal.tsx b/apps/tangle-dapp/containers/LsCreatePoolModal.tsx
new file mode 100644
index 000000000..d175787fd
--- /dev/null
+++ b/apps/tangle-dapp/containers/LsCreatePoolModal.tsx
@@ -0,0 +1,203 @@
+import { BN } from '@polkadot/util';
+import { TANGLE_TOKEN_DECIMALS } from '@webb-tools/dapp-config';
+import {
+ Alert,
+ Button,
+ Input,
+ Modal,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ TANGLE_DOCS_LS_CREATE_POOL_URL,
+} from '@webb-tools/webb-ui-components';
+import assert from 'assert';
+import { FC, useCallback, useState } from 'react';
+
+import AddressInput, {
+ AddressType,
+} from '../components/AddressInput/AddressInput';
+import AmountInput from '../components/AmountInput/AmountInput';
+import { LsNetworkId, LsProtocolId } from '../constants/liquidStaking/types';
+import useBalances from '../data/balances/useBalances';
+import useLsCreatePoolTx from '../data/liquidStaking/tangle/useLsCreatePoolTx';
+import { useLsStore } from '../data/liquidStaking/useLsStore';
+import useInputAmount from '../hooks/useInputAmount';
+import useSubstrateAddress from '../hooks/useSubstrateAddress';
+import { TxStatus } from '../hooks/useSubstrateTx';
+import { SubstrateAddress } from '../types/utils';
+import getLsNetwork from '../utils/liquidStaking/getLsNetwork';
+import getLsProtocolDef from '../utils/liquidStaking/getLsProtocolDef';
+
+export type LsCreatePoolModalProps = {
+ isOpen: boolean;
+ setIsOpen: (isOpen: boolean) => void;
+};
+
+const LsCreatePoolModal: FC = ({
+ isOpen,
+ setIsOpen,
+}) => {
+ const activeSubstrateAddress = useSubstrateAddress();
+ // TODO: Use form validation for the properties/inputs.
+ const [name, setName] = useState('');
+ const [rootAddress, setRootAddress] = useState(activeSubstrateAddress);
+ const { free: freeBalance } = useBalances();
+
+ const [nominatorAddress, setNominatorAddress] =
+ useState(activeSubstrateAddress);
+
+ const [bouncerAddress, setBouncerAddress] = useState(
+ activeSubstrateAddress,
+ );
+
+ const [initialBondAmount, setInitialBondAmount] = useState(null);
+ const [lsProtocolId, setLsProtocolId] = useState(null);
+ const { lsNetworkId } = useLsStore();
+
+ const lsProtocol =
+ lsProtocolId === null ? null : getLsProtocolDef(lsProtocolId);
+
+ const lsNetwork = getLsNetwork(lsNetworkId);
+
+ const { displayAmount, errorMessage } = useInputAmount({
+ amount: initialBondAmount,
+ setAmount: setInitialBondAmount,
+ // Default to TNT's decimals if the protocol hasn't been selected
+ // yet.
+ decimals: lsProtocol?.decimals ?? TANGLE_TOKEN_DECIMALS,
+ });
+
+ // TODO: Also add Restaking Parachain when its non-testnet version is available.
+ const isLiveNetwork = lsNetworkId === LsNetworkId.TANGLE_MAINNET;
+
+ const { execute, status } = useLsCreatePoolTx();
+
+ const handleCreatePoolClick = useCallback(async () => {
+ // TODO: Add form validation, then remove this check.
+ if (
+ initialBondAmount === null ||
+ rootAddress === null ||
+ nominatorAddress === null ||
+ bouncerAddress === null
+ ) {
+ return;
+ }
+
+ assert(
+ execute !== null,
+ 'Button should have been disabled if execute is null.',
+ );
+
+ await execute({
+ name,
+ initialBondAmount,
+ rootAddress,
+ nominatorAddress,
+ bouncerAddress,
+ });
+ }, [
+ bouncerAddress,
+ execute,
+ initialBondAmount,
+ name,
+ nominatorAddress,
+ rootAddress,
+ ]);
+
+ return (
+
+
+ setIsOpen(false)}>
+ Create a Liquid Staking Pool
+
+
+
+
+ {/**
+ * In case that a testnet is selected, it's helpful to let the users
+ * know that the pool will be created on the testnet, and that
+ * it won't be accessible on other networks.
+ */}
+ {!isLiveNetwork && (
+
+ )}
+
+
+
+ {/** TODO: Protocol selection dropdown. */}
+
+
+
+
+
+
+
+
+