diff --git a/public/images/check.svg b/public/images/check.svg
new file mode 100644
index 00000000..7478b634
--- /dev/null
+++ b/public/images/check.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/images/loader.svg b/public/images/loader.svg
new file mode 100644
index 00000000..ff798b1d
--- /dev/null
+++ b/public/images/loader.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/app/app.tsx b/src/app/app.tsx
index af4b38fd..d2f0d892 100644
--- a/src/app/app.tsx
+++ b/src/app/app.tsx
@@ -29,9 +29,9 @@ export function App(): React.JSX.Element {
-
-
-
+
+
+
@@ -51,9 +51,9 @@ export function App(): React.JSX.Element {
-
-
-
+
+
+
diff --git a/src/app/components/mint-unmint/components/burn-transaction-screen/burn-transaction-screen.tsx b/src/app/components/mint-unmint/components/burn-transaction-screen/burn-transaction-screen.tsx
index 1ca096ae..ba744f84 100644
--- a/src/app/components/mint-unmint/components/burn-transaction-screen/burn-transaction-screen.tsx
+++ b/src/app/components/mint-unmint/components/burn-transaction-screen/burn-transaction-screen.tsx
@@ -50,7 +50,6 @@ export function BurnTokenTransactionForm({
async function handleButtonClick(withdrawAmount: number): Promise {
if (!currentVault) return;
-
try {
const currentRisk = await fetchUserEthereumAddressRiskLevel();
if (currentRisk === 'High') throw new Error('Risk Level is too high');
@@ -92,10 +91,11 @@ export function BurnTokenTransactionForm({
return (
-
+
-
+
state.mintunmint);
const { risk, fetchUserAddressRisk, isLoading } = useRisk();
@@ -28,7 +23,7 @@ export function Mint(): React.JSX.Element {
{[0].includes(mintStep[0]) && }
- {[1].includes(mintStep[0]) && (
+ {[1, 2].includes(mintStep[0]) && (
)}
- {[2].includes(mintStep[0]) && (
-
- )}
);
diff --git a/src/app/components/mint-unmint/components/transaction-summary/components/transaction-summary-preview-card.tsx b/src/app/components/mint-unmint/components/transaction-summary/components/transaction-summary-preview-card.tsx
deleted file mode 100644
index adbaae36..00000000
--- a/src/app/components/mint-unmint/components/transaction-summary/components/transaction-summary-preview-card.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { HStack, Image, Text, VStack } from '@chakra-ui/react';
-
-const blockchainPreviewCardMap = {
- ethereum: {
- tokenName: 'dlcBTC',
- path: '/images/logos/dlc-btc-logo.svg',
- },
- bitcoin: {
- tokenName: 'BTC',
- path: '/images/logos/bitcoin-logo.svg',
- },
-};
-
-interface TransactionSummaryPreviewCardProps {
- blockchain: 'ethereum' | 'bitcoin';
- assetAmount?: number;
-}
-
-export function TransactionSummaryPreviewCard({
- blockchain,
- assetAmount,
-}: TransactionSummaryPreviewCardProps): React.JSX.Element {
- return (
-
-
-
-
- {assetAmount} {blockchainPreviewCardMap[blockchain].tokenName}
-
-
-
- );
-}
diff --git a/src/app/components/mint-unmint/components/transaction-summary/transaction-summary.tsx b/src/app/components/mint-unmint/components/transaction-summary/transaction-summary.tsx
deleted file mode 100644
index d333ceac..00000000
--- a/src/app/components/mint-unmint/components/transaction-summary/transaction-summary.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-import { useContext } from 'react';
-import { useDispatch } from 'react-redux';
-import { useNavigate } from 'react-router-dom';
-
-import { Button, HStack, Spinner, Stack, Text, VStack } from '@chakra-ui/react';
-import { Vault } from '@components/vault/vault';
-import { VaultContext } from '@providers/vault-context-provider';
-import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions';
-import Decimal from 'decimal.js';
-
-import { TransactionSummaryPreviewCard } from './components/transaction-summary-preview-card';
-
-interface FlowPropertyMap {
- [key: string]: {
- [key: number]: {
- title: string;
- subtitle?: string;
- };
- };
-}
-
-const flowPropertyMap: FlowPropertyMap = {
- mint: {
- 2: { title: 'a) Locking BTC in progress', subtitle: 'Minting dlcBTC' },
- 3: { title: 'Vault Updated' },
- },
- unmint: {
- 2: {
- title: 'a) Withdrawing from Vault in progress',
- subtitle: 'BTC is being unlocked',
- },
- 3: { title: 'Vault Updated' },
- },
-};
-
-interface TransactionSummaryProps {
- currentStep: [number, string];
- depositAmount?: number;
- flow: 'mint' | 'unmint';
- blockchain: 'ethereum' | 'bitcoin';
- width: string;
- handleClose?: () => void;
-}
-
-export function TransactionSummary({
- depositAmount,
- currentStep,
- flow,
- blockchain,
- width,
- handleClose,
-}: TransactionSummaryProps): React.JSX.Element {
- const navigate = useNavigate();
- const dispatch = useDispatch();
-
- const { allVaults } = useContext(VaultContext);
-
- const currentVault = allVaults.find(vault => vault.uuid === currentStep[1]);
-
- return (
-
-
- {currentStep[0] === 2 && }
- {flowPropertyMap[flow][currentStep[0]].title}:
-
- {currentVault && (
- <>
-
- {currentStep[0] === 2 && (
- <>
-
- b) {flowPropertyMap[flow][currentStep[0]].subtitle}:
-
-
- >
- )}
- >
- )}
-
-
- View vault statuses in the My Vaults tab.
-
-
-
-
- {((flow === 'mint' && currentStep[0] === 2) ||
- (flow === 'unmint' && currentStep[0] === 2)) && (
-
- )}
-
-
- );
-}
diff --git a/src/app/components/mint-unmint/components/unmint/components/unmint-vault-selector.tsx b/src/app/components/mint-unmint/components/unmint/components/unmint-vault-selector.tsx
index a10d8f65..63ae7a42 100644
--- a/src/app/components/mint-unmint/components/unmint/components/unmint-vault-selector.tsx
+++ b/src/app/components/mint-unmint/components/unmint/components/unmint-vault-selector.tsx
@@ -42,7 +42,7 @@ export function UnmintVaultSelector({
Select vault to withdraw Bitcoin:
-
+
diff --git a/src/app/components/mint-unmint/components/unmint/components/withdraw-screen.tsx b/src/app/components/mint-unmint/components/unmint/components/withdraw-screen.tsx
index d8d6c181..5de56280 100644
--- a/src/app/components/mint-unmint/components/unmint/components/withdraw-screen.tsx
+++ b/src/app/components/mint-unmint/components/unmint/components/withdraw-screen.tsx
@@ -67,10 +67,11 @@ export function WithdrawScreen({
return (
-
+
)}
- {[1].includes(unmintStep[0]) && (
+ {[1, 2].includes(unmintStep[0]) && (
)}
- {[2].includes(unmintStep[0]) && (
-
- )}
);
diff --git a/src/app/components/mint-unmint/components/walkthrough/components/walkthrough-header.tsx b/src/app/components/mint-unmint/components/walkthrough/components/walkthrough-header.tsx
index f6de8568..f6558adc 100644
--- a/src/app/components/mint-unmint/components/walkthrough/components/walkthrough-header.tsx
+++ b/src/app/components/mint-unmint/components/walkthrough/components/walkthrough-header.tsx
@@ -14,7 +14,7 @@ export function WalkthroughHeader({
title,
}: WalkthroughHeaderProps): React.JSX.Element {
return (
-
+
Step {currentStep !== undefined && currentStep + 1}
diff --git a/src/app/components/mint-unmint/components/walkthrough/components/walkthrough.layout.tsx b/src/app/components/mint-unmint/components/walkthrough/components/walkthrough.layout.tsx
index 6f92af33..1f747a03 100644
--- a/src/app/components/mint-unmint/components/walkthrough/components/walkthrough.layout.tsx
+++ b/src/app/components/mint-unmint/components/walkthrough/components/walkthrough.layout.tsx
@@ -3,7 +3,7 @@ import { HasChildren } from '@models/has-children';
export function WalkthroughLayout({ children }: HasChildren): React.JSX.Element {
return (
-
+
{children}
);
diff --git a/src/app/components/modals/components/modal-container.tsx b/src/app/components/modals/components/modal-container.tsx
index 990d8ad1..761fa989 100644
--- a/src/app/components/modals/components/modal-container.tsx
+++ b/src/app/components/modals/components/modal-container.tsx
@@ -35,9 +35,15 @@ export function ModalContainer(): React.JSX.Element {
/>
handleClosingModal(() =>
- modalActions.toggleSuccessfulFlowModalVisibility({ vaultUUID: '' })
+ modalActions.toggleSuccessfulFlowModalVisibility({
+ vaultUUID: '',
+ flow: 'mint',
+ assetAmount: 0,
+ })
)
}
vaultUUID={isSuccesfulFlowModalOpen[1] ? isSuccesfulFlowModalOpen[1] : ''}
diff --git a/src/app/components/modals/components/modal.vault.layout.tsx b/src/app/components/modals/components/modal.vault.layout.tsx
new file mode 100644
index 00000000..6fc6c3c3
--- /dev/null
+++ b/src/app/components/modals/components/modal.vault.layout.tsx
@@ -0,0 +1,35 @@
+import { ReactNode } from 'react';
+
+import {
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalHeader,
+ ModalOverlay,
+} from '@chakra-ui/react';
+
+interface ModalVaultLayoutProps {
+ title: string;
+ isOpen: boolean;
+ onClose: () => void;
+ children: ReactNode;
+}
+
+export function ModalVaultLayout({
+ title,
+ isOpen,
+ onClose,
+ children,
+}: ModalVaultLayoutProps): React.JSX.Element {
+ return (
+
+
+
+ {title}
+
+ {children}
+
+
+ );
+}
diff --git a/src/app/components/modals/successful-flow-modal/successful-flow-modal.tsx b/src/app/components/modals/successful-flow-modal/successful-flow-modal.tsx
index 87fac717..a267a37b 100644
--- a/src/app/components/modals/successful-flow-modal/successful-flow-modal.tsx
+++ b/src/app/components/modals/successful-flow-modal/successful-flow-modal.tsx
@@ -1,26 +1,49 @@
-import { TransactionSummary } from '@components/mint-unmint/components/transaction-summary/transaction-summary';
+import { useContext } from 'react';
+
+import { HStack, Text, VStack } from '@chakra-ui/react';
+import { TransactionFormNavigateButtonGroup } from '@components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button-group';
+import { Vault } from '@components/vault/vault';
+import { VaultContext } from '@providers/vault-context-provider';
import { ModalComponentProps } from '../components/modal-container';
-import { ModalLayout } from '../components/modal.layout';
+import { ModalVaultLayout } from '../components/modal.vault.layout';
interface SuccessfulFlowModalProps extends ModalComponentProps {
vaultUUID: string;
+ flow: 'mint' | 'burn';
+ assetAmount: number;
+}
+
+function getModalText(flow: 'mint' | 'burn', assetAmount?: number): string {
+ if (flow === 'mint') {
+ return `You have succesfully deposited ${assetAmount} BTC into your Vault, and minted ${assetAmount} dlcBTC to your address.`;
+ } else {
+ return `You have succesfully burned ${assetAmount} dlcBTC from your address, and withdraw ${assetAmount} BTC from your Vault.`;
+ }
}
export function SuccessfulFlowModal({
isOpen,
handleClose,
vaultUUID,
+ flow,
+ assetAmount,
}: SuccessfulFlowModalProps): React.JSX.Element {
+ const { allVaults } = useContext(VaultContext);
+
+ const currentVault = allVaults.find(vault => vault.uuid === vaultUUID);
+
return (
- handleClose()}>
- handleClose()}
- />
-
+ handleClose()}>
+
+
+
+ {getModalText(flow, assetAmount)}
+
+
+
+
+
+
);
}
diff --git a/src/app/components/my-vaults-small/components/my-vaults-small.layout.tsx b/src/app/components/my-vaults-small/components/my-vaults-small.layout.tsx
index 1a53bf9e..29e720e3 100644
--- a/src/app/components/my-vaults-small/components/my-vaults-small.layout.tsx
+++ b/src/app/components/my-vaults-small/components/my-vaults-small.layout.tsx
@@ -7,11 +7,11 @@ export function MyVaultsSmallLayout({ children }: HasChildren): React.JSX.Elemen
py={'2.5px'}
px={'25px'}
w={'31.5%'}
- h={'825px'}
+ h={'925px'}
bg={'background.container.01'}
border={'1px solid'}
borderRadius={'md'}
- borderColor={'border.lightBlue.01'}
+ borderColor={'white.03'}
>
{children}
diff --git a/src/app/components/my-vaults-small/my-vaults-small.tsx b/src/app/components/my-vaults-small/my-vaults-small.tsx
index 668d6147..54fbe30c 100644
--- a/src/app/components/my-vaults-small/my-vaults-small.tsx
+++ b/src/app/components/my-vaults-small/my-vaults-small.tsx
@@ -26,7 +26,7 @@ export function MyVaultsSmall(): React.JSX.Element {
0}
>
diff --git a/src/app/components/my-vaults/components/my-vaults-large.layout.tsx b/src/app/components/my-vaults/components/my-vaults-large.layout.tsx
index aded3873..e63719e8 100644
--- a/src/app/components/my-vaults/components/my-vaults-large.layout.tsx
+++ b/src/app/components/my-vaults/components/my-vaults-large.layout.tsx
@@ -10,7 +10,7 @@ export function MyVaultsLargeLayout({ children }: HasChildren): React.JSX.Elemen
bg={'background.container.01'}
border={'1px solid'}
borderRadius={'md'}
- borderColor={'border.lightBlue.01'}
+ borderColor={'white.03'}
>
{children}
diff --git a/src/app/components/tab-button/tab-button.tsx b/src/app/components/tab-button/tab-button.tsx
index a7766e76..34c7033d 100644
--- a/src/app/components/tab-button/tab-button.tsx
+++ b/src/app/components/tab-button/tab-button.tsx
@@ -8,7 +8,12 @@ interface TabButtonProps {
export function TabButton({ title, isActive, handleClick }: TabButtonProps): React.JSX.Element {
return (
-
+ )}
+
);
}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button-group.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button-group.tsx
new file mode 100644
index 00000000..fad3510d
--- /dev/null
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button-group.tsx
@@ -0,0 +1,41 @@
+import { useDispatch } from 'react-redux';
+import { useNavigate } from 'react-router-dom';
+
+import { ButtonGroup } from '@chakra-ui/react';
+import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions';
+
+import { TransactionFormNavigateButton } from './transaction-screen.transaction-form.navigate-button';
+
+interface TransactionFormNavigateButtonGroupProps {
+ flow: 'mint' | 'burn';
+}
+
+export function TransactionFormNavigateButtonGroup({
+ flow,
+}: TransactionFormNavigateButtonGroupProps): React.JSX.Element {
+ const navigate = useNavigate();
+ const dispatch = useDispatch();
+
+ function handleClick() {
+ if (flow === 'mint') {
+ dispatch(mintUnmintActions.setActiveTab(0));
+ dispatch(mintUnmintActions.setMintStep([0, '']));
+ } else {
+ dispatch(mintUnmintActions.setActiveTab(1));
+ dispatch(mintUnmintActions.setUnmintStep([0, '']));
+ }
+ }
+
+ return (
+
+ handleClick()}
+ />
+ navigate('/my-vaults')}
+ />
+
+ );
+}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button.tsx
new file mode 100644
index 00000000..8aec83d8
--- /dev/null
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.navigate-button.tsx
@@ -0,0 +1,26 @@
+import { Button } from '@chakra-ui/react';
+
+interface TransactionFormNavigateButtonProps {
+ label: string;
+ onClick: () => void;
+}
+
+export function TransactionFormNavigateButton({
+ label,
+ onClick,
+}: TransactionFormNavigateButtonProps): React.JSX.Element {
+ return (
+
+ {label}
+
+ );
+}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-stack/components/transaction-screen.transaction-form.progress-stack.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-stack/components/transaction-screen.transaction-form.progress-stack.tsx
new file mode 100644
index 00000000..358574bf
--- /dev/null
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-stack/components/transaction-screen.transaction-form.progress-stack.tsx
@@ -0,0 +1,154 @@
+import { HStack, VStack } from '@chakra-ui/react';
+import { VaultVerticalProgressBar } from '@components/vault/components/vault-vertical-progress-bar';
+import { TransactionFormAPI } from '@models/form.models';
+
+import { TransactionFormInputField } from '../../transaction-screen.transaction-form.input';
+import { TransactionFormProgressStackItem } from '../../transaction-screen.transaction-form.progress-step-stack-item';
+
+interface ProgressStackItemProps {
+ label: string;
+ assetLogo: string;
+ assetSymbol: string;
+}
+
+const componentsMap = {
+ mint: {
+ A: { label: 'Deposit', assetLogo: '/images/logos/bitcoin-logo.svg', assetSymbol: 'BTC' },
+ B: { label: 'Mint', assetLogo: '/images/logos/dlc-btc-logo.svg', assetSymbol: 'dlcBTC' },
+ },
+ burn: {
+ A: { label: 'Burn', assetLogo: '/images/logos/dlc-btc-logo.svg', assetSymbol: 'dlcBTC' },
+ B: { label: 'Withdraw', assetLogo: '/images/logos/bitcoin-logo.svg', assetSymbol: 'BTC' },
+ },
+};
+
+interface ProgressStackProps {
+ formAPI: TransactionFormAPI;
+ isIncludeForm: boolean;
+ flow: 'mint' | 'burn';
+ currentStep: number;
+ activeStackItem: 0 | 1;
+ currentBitcoinPrice: number;
+ components: { A: ProgressStackItemProps; B: ProgressStackItemProps };
+}
+
+const ProgressStack = ({
+ formAPI,
+ isIncludeForm,
+ flow,
+ currentStep,
+ activeStackItem,
+ currentBitcoinPrice,
+ components,
+}: ProgressStackProps): React.JSX.Element => {
+ const { A, B } = components;
+
+ return (
+
+ {isIncludeForm ? (
+ <>
+
+
+ >
+ ) : (
+ <>
+
+
+ >
+ )}
+
+ );
+};
+
+interface ProgressStackByFlowProps {
+ formAPI: TransactionFormAPI;
+ flow: 'mint' | 'burn';
+ currentStep: number;
+ confirmations?: number;
+ currentBitcoinPrice: number;
+}
+
+const ProgressStackByFlow = ({
+ formAPI,
+ flow,
+ currentStep,
+ confirmations = 0,
+ currentBitcoinPrice,
+}: ProgressStackByFlowProps): React.JSX.Element => {
+ const components = componentsMap[flow];
+ const isIncludeForm = flow === 'mint' ? currentStep === 1 : currentStep === 0;
+ const activeStackItem = isIncludeForm || (flow === 'mint' && confirmations < 6) ? 0 : 1;
+
+ return (
+
+ );
+};
+
+interface TransactionFormProgressStackBurnVariantAProps {
+ formAPI: TransactionFormAPI;
+ flow: 'mint' | 'burn';
+ currentBitcoinPrice: number;
+ currentStep: number;
+ confirmations?: number;
+}
+
+export const TransactionFormProgressStack = ({
+ formAPI,
+ flow,
+ currentStep,
+ confirmations = 0,
+ currentBitcoinPrice,
+}: TransactionFormProgressStackBurnVariantAProps): React.JSX.Element => {
+ return (
+
+
+
+
+ );
+};
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-step-stack-item.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-step-stack-item.tsx
new file mode 100644
index 00000000..c64267de
--- /dev/null
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.progress-step-stack-item.tsx
@@ -0,0 +1,39 @@
+import { HStack, Image, Stack, Text } from '@chakra-ui/react';
+
+interface TransactionFormProgressStackItemProps {
+ label: string;
+ assetLogo: string;
+ assetSymbol: string;
+ isActive: boolean;
+}
+
+export function TransactionFormProgressStackItem({
+ label,
+ assetLogo,
+ assetSymbol,
+ isActive,
+}: TransactionFormProgressStackItemProps): React.JSX.Element {
+ return (
+
+
+
+
+
+ {label}
+
+
+
+
+ {assetSymbol}
+
+
+ );
+}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.protocol-fee-box.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.protocol-fee-box.tsx
index 4814767e..83d75a06 100644
--- a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.protocol-fee-box.tsx
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.protocol-fee-box.tsx
@@ -1,9 +1,12 @@
import { HStack, Text, VStack } from '@chakra-ui/react';
+import { Vault } from '@models/vault';
import Decimal from 'decimal.js';
import { getFeeAmount } from 'dlc-btc-lib/bitcoin-functions';
interface TransactionFormProtocolFeeStackProps {
- formType: 'deposit' | 'withdraw' | 'burn';
+ flow: 'mint' | 'burn';
+ vault: Vault;
+ currentStep: number;
assetAmount?: number;
bitcoinPrice?: number;
protocolFeeBasisPoints?: number;
@@ -22,13 +25,20 @@ function calculateProtocolFeeInUSD(
}
export function TransactionFormProtocolFeeStack({
- formType,
+ flow,
+ vault,
+ currentStep,
assetAmount,
bitcoinPrice,
protocolFeeBasisPoints,
isBitcoinWalletLoading,
}: TransactionFormProtocolFeeStackProps): React.JSX.Element | false {
- if (isBitcoinWalletLoading[0] || formType === 'burn') return false;
+ if (isBitcoinWalletLoading[0] || [0, 2].includes(currentStep)) return false;
+
+ const amount =
+ flow === 'burn' && currentStep === 1
+ ? new Decimal(vault.valueLocked).minus(vault.valueMinted).toNumber()
+ : assetAmount;
return (
- {`${
- assetAmount && protocolFeeBasisPoints
- ? getFeeAmount(assetAmount, protocolFeeBasisPoints)
- : 0
- }
+ {`${amount && protocolFeeBasisPoints ? getFeeAmount(amount, protocolFeeBasisPoints) : 0}
BTC`}
{' '}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.submit-button-group.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.submit-button-group.tsx
new file mode 100644
index 00000000..c4604044
--- /dev/null
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screen.transaction-form.submit-button-group.tsx
@@ -0,0 +1,84 @@
+import { Button, VStack } from '@chakra-ui/react';
+import { TransactionFormAPI } from '@models/form.models';
+import { BitcoinWalletContextState } from '@providers/bitcoin-wallet-context-provider';
+
+import { getFormProperties } from './transaction-screen.transaction-form.input';
+
+function getButtonLabel(
+ flow: 'mint' | 'burn',
+ currentStep: number,
+ isSubmitting: boolean,
+ walletState: BitcoinWalletContextState
+): string {
+ if (isSubmitting) return 'Processing';
+
+ const isWalletReady = walletState === BitcoinWalletContextState.READY;
+ const isCurrentStepZero = currentStep === 0;
+
+ switch (flow) {
+ case 'burn':
+ return isCurrentStepZero
+ ? 'Sign Burn Transaction'
+ : isWalletReady
+ ? 'Sign Withdraw Transaction'
+ : 'Connect Wallet';
+
+ case 'mint':
+ return isWalletReady ? 'Sign Deposit Transaction' : 'Connect Wallet';
+ default:
+ throw new Error('Invalid Flow Type');
+ }
+}
+
+interface TransactionFormSubmitButtonGroupProps {
+ flow: 'mint' | 'burn';
+ formAPI: TransactionFormAPI;
+ currentStep: number;
+ userEthereumAddressRiskLevel: string;
+ bitcoinWalletContextState: any;
+ handleCancelButtonClick: () => void;
+}
+
+export function TransactionFormSubmitButtonGroup({
+ flow,
+ formAPI,
+ currentStep,
+ userEthereumAddressRiskLevel,
+ bitcoinWalletContextState,
+ handleCancelButtonClick,
+}: TransactionFormSubmitButtonGroupProps): React.JSX.Element {
+ const formProperties = getFormProperties(flow, currentStep);
+ return (
+
+ [state.canSubmit, state.isSubmitting]}
+ children={([canSubmit, isSubmitting]) => (
+
+ {getButtonLabel(flow, currentStep, isSubmitting, bitcoinWalletContextState)}
+
+ )}
+ />
+
+ Cancel
+
+
+ );
+}
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screent.transaction-form.transaction-information.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screent.transaction-form.transaction-information.tsx
index fc3ae77e..db73896d 100644
--- a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screent.transaction-form.transaction-information.tsx
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/components/transaction-screent.transaction-form.transaction-information.tsx
@@ -1,17 +1,28 @@
import { HStack, Text } from '@chakra-ui/react';
+import { Vault } from '@models/vault';
+import Decimal from 'decimal.js';
interface TransactionFormWarningProps {
- formType: 'deposit' | 'withdraw' | 'burn';
+ flow: 'mint' | 'burn';
+ vault: Vault;
+ currentStep: number;
assetAmount: number;
isBitcoinWalletLoading: [boolean, string];
}
export function TransactionFormTransactionInformation({
- formType,
+ flow,
+ vault,
+ currentStep,
assetAmount,
isBitcoinWalletLoading,
}: TransactionFormWarningProps): React.JSX.Element | false {
- if (isBitcoinWalletLoading[0] || formType === 'burn') return false;
+ if (isBitcoinWalletLoading[0] || [0, 2].includes(currentStep)) return false;
+
+ const amount =
+ flow === 'burn' && currentStep === 1
+ ? new Decimal(vault.valueLocked).minus(vault.valueMinted).toNumber()
+ : assetAmount;
return (
- Make sure you have {assetAmount} BTC + (fees)
+ Make sure you have {amount} BTC + (fees)
in your Bitcoin Wallet before proceeding to the next step.
diff --git a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/transaction-screen.transaction-form.tsx b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/transaction-screen.transaction-form.tsx
index 4e0d18ee..9b0a08b3 100644
--- a/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/transaction-screen.transaction-form.tsx
+++ b/src/app/components/transaction-screen/transaction-screen.transaction-form/components/transaction-screen.transaction-form/transaction-screen.transaction-form.tsx
@@ -1,15 +1,19 @@
-import { Button, Text, VStack } from '@chakra-ui/react';
+import React, { useContext, useState } from 'react';
+
+import { VStack } from '@chakra-ui/react';
import { RiskBox } from '@components/mint-unmint/components/risk-box/risk-box';
+import { TransactionFormAPI } from '@models/form.models';
import { Vault } from '@models/vault';
+import { BitcoinTransactionConfirmationsContext } from '@providers/bitcoin-query-provider';
import { BitcoinWalletContextState } from '@providers/bitcoin-wallet-context-provider';
import { useForm } from '@tanstack/react-form';
import Decimal from 'decimal.js';
-import { TransactionFormFieldInput } from './components/transaction-screen.transaction-form.input';
-import { TransactionFormInputUSDText } from './components/transaction-screen.transaction-form.input-usd-text';
+import { TransactionFormNavigateButtonGroup } from './components/transaction-screen.transaction-form.navigate-button-group';
+import { TransactionFormProgressStack } from './components/transaction-screen.transaction-form.progress-stack/components/transaction-screen.transaction-form.progress-stack';
import { TransactionFormProtocolFeeStack } from './components/transaction-screen.transaction-form.protocol-fee-box';
+import { TransactionFormSubmitButtonGroup } from './components/transaction-screen.transaction-form.submit-button-group';
import { TransactionScreenWalletInformation } from './components/transaction-screen.transaction-form.wallet-information';
-import { VaultTransactionFormWarning } from './components/transaction-screen.transaction-form.warning';
import { TransactionFormTransactionInformation } from './components/transaction-screent.transaction-form.transaction-information';
function validateDepositAmount(
@@ -28,7 +32,7 @@ function validateDepositAmount(
return error;
}
-function validateWithdrawAmount(value: number, valueMinted: number): string | undefined {
+function validateBurnAmount(value: number, valueMinted: number): string | undefined {
let error;
if (!value) {
@@ -41,7 +45,7 @@ function validateWithdrawAmount(value: number, valueMinted: number): string | un
function validateFormAmount(
value: number,
- type: 'deposit' | 'withdraw' | 'burn',
+ type: 'mint' | 'burn',
depositLimit?: { minimumDeposit: number; maximumDeposit: number },
vault?: Vault
): string | undefined {
@@ -52,61 +56,41 @@ function validateFormAmount(
}
switch (type) {
- case 'deposit':
+ case 'mint':
return validateDepositAmount(value, depositLimit);
- case 'withdraw':
- return validateWithdrawAmount(value, vault.valueMinted);
case 'burn':
- return undefined;
+ return validateBurnAmount(value, vault.valueMinted);
}
}
-function getButtonLabel(
- formType: 'deposit' | 'withdraw' | 'burn',
- isSubmitting: boolean,
- bitcoinWalletContextState: BitcoinWalletContextState
-): string {
- if (isSubmitting) {
- return 'Processing';
- } else if (formType === 'burn') {
- return 'Sign Burn Transaction';
- } else {
- if (bitcoinWalletContextState === BitcoinWalletContextState.READY) {
- switch (formType) {
- case 'deposit':
- return 'Sign Deposit Transaction';
- case 'withdraw':
- return 'Sign Withdraw Transaction';
- }
- } else {
- return 'Connect Wallet';
- }
- }
-}
+function getTransactionButtonGroup(
+ flow: 'mint' | 'burn',
+ currentStep: number,
+ formAPI: TransactionFormAPI,
+ userEthereumAddressRiskLevel: any,
+ bitcoinWalletContextState: BitcoinWalletContextState,
+ handleCancelButtonClick: () => void
+): React.JSX.Element | false {
+ const showSubmitButtonGroup =
+ (flow === 'mint' && currentStep === 1) || (flow === 'burn' && [0, 1].includes(currentStep));
-const formPropertyMap = {
- deposit: {
- label: 'Deposit BTC',
- logo: '/images/logos/bitcoin-logo.svg',
- symbol: 'BTC',
- color: 'orange.01',
- },
- withdraw: {
- label: 'Withdraw BTC',
- logo: '/images/logos/bitcoin-logo.svg',
- symbol: 'BTC',
- color: 'orange.01',
- },
- burn: {
- label: 'Burn dlcBTC',
- logo: '/images/logos/dlc-btc-logo.svg',
- symbol: 'dlcBTC',
- color: 'purple.01',
- },
-};
+ return showSubmitButtonGroup ? (
+
+ ) : (
+
+ );
+}
interface VaultTransactionFormProps {
- type: 'deposit' | 'withdraw' | 'burn';
+ flow: 'mint' | 'burn';
+ currentStep: number;
bitcoinWalletContextState: BitcoinWalletContextState;
isBitcoinWalletLoading: [boolean, string];
userEthereumAddressRiskLevel?: string;
@@ -119,7 +103,8 @@ interface VaultTransactionFormProps {
}
export function VaultTransactionForm({
- type,
+ flow,
+ currentStep,
bitcoinWalletContextState,
isBitcoinWalletLoading,
userEthereumAddressRiskLevel,
@@ -130,32 +115,33 @@ export function VaultTransactionForm({
currentBitcoinPrice,
depositLimit,
}: VaultTransactionFormProps): React.JSX.Element {
- const {
- Field,
- Subscribe,
- handleSubmit,
- state: {
- isSubmitting,
- values: { assetAmount },
- },
- } = useForm({
+ const [currentFieldValue, setCurrentFieldValue] = useState(depositLimit?.minimumDeposit!);
+
+ const confirmations = useContext(
+ BitcoinTransactionConfirmationsContext
+ ).bitcoinTransactionConfirmations.find(v => v[0] === vault.uuid)?.[1];
+
+ const form = useForm({
defaultValues: {
- assetAmount: '0.01',
+ assetAmount: depositLimit?.minimumDeposit!.toString()!,
},
onSubmit: async ({ value }) => {
- await handleButtonClick(
- type === 'withdraw'
- ? new Decimal(vault.valueLocked).minus(vault.valueMinted).toNumber()
- : new Decimal(value.assetAmount).toNumber()
- );
+ const assetAmount = new Decimal(value.assetAmount).toNumber();
+ const burnAmount = new Decimal(vault.valueLocked).minus(vault.valueMinted).toNumber();
+ const isWithdrawStep = flow === 'burn' && currentStep !== 0;
+
+ const amountToHandle = isWithdrawStep ? burnAmount : assetAmount;
+
+ await handleButtonClick(amountToHandle);
},
validators: {
onChange: ({ value }) => {
+ setCurrentFieldValue(new Decimal(value.assetAmount).toNumber());
return {
fields: {
assetAmount: validateFormAmount(
parseFloat(value.assetAmount),
- type,
+ flow,
depositLimit,
vault
),
@@ -170,49 +156,31 @@ export function VaultTransactionForm({
onSubmit={async e => {
e.preventDefault();
e.stopPropagation();
- await handleSubmit();
+ await form.handleSubmit();
}}
>
-
- {type !== 'withdraw' && (
-
- {field => (
-
-
- {formPropertyMap[type].label}
-
-
-
-
-
- )}
-
- )}
+
+
{isUserEthereumAddressRiskLevelLoading && userEthereumAddressRiskLevel && (
@@ -222,30 +190,14 @@ export function VaultTransactionForm({
/>
)}
- [state.canSubmit, state.isSubmitting]}
- children={([canSubmit, isSubmitting]) => (
-
- {getButtonLabel(type, isSubmitting, bitcoinWalletContextState)}
-
- )}
- />
-
- Cancel
-
+ {getTransactionButtonGroup(
+ flow,
+ currentStep,
+ form,
+ userEthereumAddressRiskLevel,
+ bitcoinWalletContextState,
+ handleCancelButtonClick
+ )}
);
diff --git a/src/app/components/vault/components/vault-vertical-progress-bar.tsx b/src/app/components/vault/components/vault-vertical-progress-bar.tsx
new file mode 100644
index 00000000..d97818c7
--- /dev/null
+++ b/src/app/components/vault/components/vault-vertical-progress-bar.tsx
@@ -0,0 +1,65 @@
+import { Divider, Image, Spinner, Stack, VStack } from '@chakra-ui/react';
+
+interface VaultVerticalProgressBarProps {
+ flow: 'mint' | 'burn';
+ currentStep: number;
+ confirmations?: number;
+ variant?: 'small';
+}
+
+const Status = {
+ ACTIVE: 'ACTIVE',
+ COMPLETED: 'COMPLETED',
+ INACTIVE: 'INACTIVE',
+};
+
+function getStatus(currentStep: number, stepIndex: number): string {
+ if (currentStep === stepIndex) {
+ return Status.ACTIVE;
+ } else if (currentStep > stepIndex) {
+ return Status.COMPLETED;
+ } else {
+ return Status.INACTIVE;
+ }
+}
+
+function getComponent(status: string): React.JSX.Element | false {
+ switch (status) {
+ case Status.ACTIVE:
+ return ;
+ case Status.COMPLETED:
+ return ;
+ case Status.INACTIVE:
+ return ;
+ default:
+ return false;
+ }
+}
+
+export function VaultVerticalProgressBar({
+ flow,
+ currentStep,
+ confirmations = 0,
+}: VaultVerticalProgressBarProps): React.JSX.Element {
+ const isMintFlow = flow === 'mint';
+ const isBurnFlow = flow === 'burn';
+
+ const activeStatus =
+ (isMintFlow && [1, 2].includes(currentStep) && confirmations < 6) ||
+ (isBurnFlow && currentStep === 0)
+ ? 0
+ : 1;
+
+ const height =
+ (isMintFlow && currentStep !== 1) || (isBurnFlow && currentStep !== 0) ? '125px' : '185px';
+
+ return (
+
+
+ {getComponent(getStatus(activeStatus, 0))}
+
+ {getComponent(getStatus(activeStatus, 1))}
+
+
+ );
+}
diff --git a/src/app/components/vault/components/vault.detaills/components/vault.details.button-group/components/vault.details.button-group.button.tsx b/src/app/components/vault/components/vault.detaills/components/vault.details.button-group/components/vault.details.button-group.button.tsx
index 756d683a..c6347241 100644
--- a/src/app/components/vault/components/vault.detaills/components/vault.details.button-group/components/vault.details.button-group.button.tsx
+++ b/src/app/components/vault/components/vault.detaills/components/vault.details.button-group/components/vault.details.button-group.button.tsx
@@ -13,7 +13,7 @@ export function VaultExpandedInformationButton({
}: VaultExpandedInformationButtonProps): React.JSX.Element {
return (
void;
handleWithdrawClick: () => void;
+ handleResumeClick: () => void;
}
export function VaultExpandedInformationButtonGroup({
+ variant,
vaultState,
vaultTotalLockedValue,
+ vaultTotalMintedValue,
handleDepositClick,
handleWithdrawClick,
-}: VaultExpandedInformationButtonGroupProps): React.JSX.Element {
- const isButtonDisabled = vaultState === VaultState.READY || vaultTotalLockedValue === 0;
+ handleResumeClick,
+}: VaultExpandedInformationButtonGroupProps): React.JSX.Element | false {
+ if (variant === 'selected') return false;
+
+ if (vaultState === VaultState.PENDING)
+ return (
+
+
+
+ );
+
+ const isWithdrawButtonDisabled = vaultState === VaultState.READY || vaultTotalLockedValue === 0;
+ const isDepositButtonDisabled = vaultTotalLockedValue !== vaultTotalMintedValue;
return (
-
+
diff --git a/src/app/components/vault/components/vault.detaills/vault.details.tsx b/src/app/components/vault/components/vault.detaills/vault.details.tsx
index 11fc8bca..23368793 100644
--- a/src/app/components/vault/components/vault.detaills/vault.details.tsx
+++ b/src/app/components/vault/components/vault.detaills/vault.details.tsx
@@ -35,7 +35,6 @@ export function VaultDetails({
function handleDepositClick() {
navigate('/mint-withdraw');
dispatch(mintUnmintActions.setMintStep([1, vaultUUID]));
- close();
}
function handleWithdrawClick() {
@@ -45,7 +44,15 @@ export function VaultDetails({
} else {
dispatch(mintUnmintActions.setUnmintStep([1, vaultUUID]));
}
- close();
+ }
+
+ function handleResumeClick() {
+ navigate('/mint-withdraw');
+ if (vaultTotalLockedValue === vaultTotalMintedValue) {
+ dispatch(mintUnmintActions.setMintStep([2, vaultUUID]));
+ } else {
+ dispatch(mintUnmintActions.setUnmintStep([2, vaultUUID]));
+ }
}
return (
@@ -58,14 +65,15 @@ export function VaultDetails({
vaultFundingTX={vaultFundingTX}
vaultWithdrawDepositTX={vaultWithdrawDepositTX}
/>
- {(vaultState !== VaultState.PENDING || variant !== 'selected') && (
-
- )}
+
diff --git a/src/app/components/vault/components/vault.main-stack/components/vault.main-stack.asset-information-stack/vault.main-stack.asset-information-stack.tsx b/src/app/components/vault/components/vault.main-stack/components/vault.main-stack.asset-information-stack/vault.main-stack.asset-information-stack.tsx
index 196600f8..813f466a 100644
--- a/src/app/components/vault/components/vault.main-stack/components/vault.main-stack.asset-information-stack/vault.main-stack.asset-information-stack.tsx
+++ b/src/app/components/vault/components/vault.main-stack/components/vault.main-stack.asset-information-stack/vault.main-stack.asset-information-stack.tsx
@@ -15,12 +15,12 @@ export function VaultAssetInformationStack({
);
diff --git a/src/app/components/vault/components/vault.progress-bar.tsx b/src/app/components/vault/components/vault.progress-bar.tsx
index 8ff912e0..ee0b0211 100644
--- a/src/app/components/vault/components/vault.progress-bar.tsx
+++ b/src/app/components/vault/components/vault.progress-bar.tsx
@@ -6,6 +6,8 @@ import { BITCOIN_BLOCK_CONFIRMATIONS } from '@shared/constants/bitcoin.constants
interface VaultProgressBarProps {
bitcoinTransactionConfirmations?: number;
vaultState: VaultState;
+ vaultTotalLockedValue: number;
+ vaultTotalMintedValue: number;
}
export function VaultProgressBar({
diff --git a/src/app/components/vault/vault.tsx b/src/app/components/vault/vault.tsx
index d81a72b9..07ae2bb1 100644
--- a/src/app/components/vault/vault.tsx
+++ b/src/app/components/vault/vault.tsx
@@ -44,6 +44,7 @@ export function Vault({ vault, variant }: VaultProps): React.JSX.Element {
handleButtonClick={handleMainButtonClick}
/>
-
+
);
}
diff --git a/src/app/hooks/use-ethereum-observer.ts b/src/app/hooks/use-ethereum-observer.ts
index e14995cf..7b629bd2 100644
--- a/src/app/hooks/use-ethereum-observer.ts
+++ b/src/app/hooks/use-ethereum-observer.ts
@@ -1,24 +1,39 @@
/* eslint-disable no-console */
-import { useContext, useEffect } from 'react';
+import { useContext, useEffect, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { getAndFormatVault } from '@functions/vault.functions';
+import { Vault } from '@models/vault';
import { EthereumNetworkConfigurationContext } from '@providers/ethereum-network-configuration.provider';
+import { VaultContext } from '@providers/vault-context-provider';
import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions';
import { modalActions } from '@store/slices/modal/modal.actions';
import { vaultActions } from '@store/slices/vault/vault.actions';
+import Decimal from 'decimal.js';
import { EthereumNetworkID } from 'dlc-btc-lib/models';
-import { delay } from 'dlc-btc-lib/utilities';
import { equals } from 'ramda';
import { useAccount } from 'wagmi';
export function useEthereumObserver(): void {
const dispatch = useDispatch();
+ const vaultContext = useContext(VaultContext);
+ const allVaults = useRef(vaultContext.allVaults);
+
+ useEffect(() => {
+ allVaults.current = vaultContext.allVaults;
+ }, [vaultContext.allVaults]);
+
const { address: ethereumUserAddress, chain } = useAccount();
const { ethereumNetworkConfiguration } = useContext(EthereumNetworkConfigurationContext);
+ function getCurrentVault(vaultUUID: string): Vault {
+ const currentVault = allVaults.current.find(vault => vault.uuid === vaultUUID);
+ if (!currentVault) throw new Error(`Vault ${vaultUUID} not found`);
+ return currentVault;
+ }
+
useEffect(() => {
if (!ethereumUserAddress) return;
@@ -27,7 +42,7 @@ export function useEthereumObserver(): void {
console.log(`Listening to [${chain?.name}]`);
console.log(`Listening to [${dlcManagerContract.address}]`);
- dlcManagerContract.on('CreateDLC', async (...args: any[]) => {
+ const handleCreateDLC = async (...args: any[]) => {
const vaultOwner: string = args[1];
if (!equals(vaultOwner, ethereumUserAddress)) return;
@@ -36,22 +51,20 @@ export function useEthereumObserver(): void {
console.log(`Vault ${vaultUUID} is ready`);
- await getAndFormatVault(vaultUUID, dlcManagerContract)
- .then(vault => {
- dispatch(
- vaultActions.swapVault({
- vaultUUID,
- updatedVault: vault,
- networkID: chain?.id.toString() as EthereumNetworkID,
- })
- );
+ const updatedVault = await getAndFormatVault(vaultUUID, dlcManagerContract);
+
+ dispatch(
+ vaultActions.swapVault({
+ vaultUUID,
+ updatedVault: updatedVault,
+ networkID: chain?.id.toString() as EthereumNetworkID,
})
- .then(() => {
- dispatch(mintUnmintActions.setMintStep([1, vaultUUID]));
- });
- });
+ );
+
+ dispatch(mintUnmintActions.setMintStep([1, vaultUUID]));
+ };
- dlcManagerContract.on('SetStatusFunded', async (...args: any[]) => {
+ const handleSetStatusFunded = async (...args: any[]) => {
const vaultOwner = args[2];
if (!equals(vaultOwner, ethereumUserAddress)) return;
@@ -60,29 +73,43 @@ export function useEthereumObserver(): void {
console.log(`Vault ${vaultUUID} is funded`);
- await getAndFormatVault(vaultUUID, dlcManagerContract)
- .then(vault => {
- dispatch(
- vaultActions.swapVault({
- vaultUUID,
- updatedVault: vault,
- networkID: chain?.id.toString() as EthereumNetworkID,
- })
- );
+ const currentVault = getCurrentVault(vaultUUID);
+ const updatedVault = await getAndFormatVault(vaultUUID, dlcManagerContract);
+
+ dispatch(
+ vaultActions.swapVault({
+ vaultUUID,
+ updatedVault: updatedVault,
+ networkID: chain?.id.toString() as EthereumNetworkID,
})
- .then(() => {
- dispatch(
- modalActions.toggleSuccessfulFlowModalVisibility({
- vaultUUID,
- })
- );
- void delay(2000).then(() => {
- dispatch(mintUnmintActions.setMintStep([0, '']));
- });
- });
- });
-
- dlcManagerContract.on('SetStatusPending', async (...args: any[]) => {
+ );
+
+ if (currentVault.valueMinted < currentVault.valueLocked) {
+ dispatch(
+ modalActions.toggleSuccessfulFlowModalVisibility({
+ vaultUUID,
+ flow: 'burn',
+ assetAmount: new Decimal(currentVault.valueLocked)
+ .minus(updatedVault.valueLocked)
+ .toNumber(),
+ })
+ );
+ dispatch(mintUnmintActions.setMintStep([0, '']));
+ } else {
+ dispatch(
+ modalActions.toggleSuccessfulFlowModalVisibility({
+ vaultUUID,
+ flow: 'mint',
+ assetAmount: new Decimal(updatedVault.valueLocked)
+ .minus(currentVault.valueLocked)
+ .toNumber(),
+ })
+ );
+ dispatch(mintUnmintActions.setMintStep([0, '']));
+ }
+ };
+
+ const handleSetStatusPending = async (...args: any[]) => {
const vaultOwner = args[2];
if (!equals(vaultOwner, ethereumUserAddress)) return;
@@ -91,25 +118,32 @@ export function useEthereumObserver(): void {
console.log(`Vault ${vaultUUID} is pending`);
- await getAndFormatVault(vaultUUID, dlcManagerContract)
- .then(vault => {
- dispatch(
- vaultActions.swapVault({
- vaultUUID,
- updatedVault: vault,
- networkID: chain?.id.toString() as EthereumNetworkID,
- })
- );
- return vault;
+ const updatedVault = await getAndFormatVault(vaultUUID, dlcManagerContract);
+
+ dispatch(
+ vaultActions.swapVault({
+ vaultUUID,
+ updatedVault: updatedVault,
+ networkID: chain?.id.toString() as EthereumNetworkID,
})
- .then(vault => {
- if (vault.valueLocked !== vault.valueMinted) {
- dispatch(mintUnmintActions.setUnmintStep([2, vaultUUID]));
- } else {
- dispatch(mintUnmintActions.setMintStep([2, vaultUUID]));
- }
- });
- });
+ );
+
+ if (updatedVault.valueLocked !== updatedVault.valueMinted) {
+ dispatch(mintUnmintActions.setUnmintStep([2, vaultUUID]));
+ } else {
+ dispatch(mintUnmintActions.setMintStep([2, vaultUUID]));
+ }
+ };
+
+ dlcManagerContract.on('CreateDLC', handleCreateDLC);
+ dlcManagerContract.on('SetStatusFunded', handleSetStatusFunded);
+ dlcManagerContract.on('SetStatusPending', handleSetStatusPending);
+
+ return () => {
+ dlcManagerContract.off('CreateDLC', handleCreateDLC);
+ dlcManagerContract.off('SetStatusFunded', handleSetStatusFunded);
+ dlcManagerContract.off('SetStatusPending', handleSetStatusPending);
+ };
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [ethereumNetworkConfiguration, ethereumUserAddress]);
+ }, [ethereumNetworkConfiguration, ethereumUserAddress, chain?.id]);
}
diff --git a/src/app/store/slices/modal/modal.slice.ts b/src/app/store/slices/modal/modal.slice.ts
index 090d04b5..31989030 100644
--- a/src/app/store/slices/modal/modal.slice.ts
+++ b/src/app/store/slices/modal/modal.slice.ts
@@ -2,14 +2,14 @@ import { createSlice } from '@reduxjs/toolkit';
interface ModalState {
isSelectWalletModalOpen: boolean;
- isSuccesfulFlowModalOpen: [boolean, string];
+ isSuccesfulFlowModalOpen: [boolean, string, string, number];
isSelectBitcoinWalletModalOpen: boolean;
isLedgerModalOpen: boolean;
}
const initialModalState: ModalState = {
isSelectWalletModalOpen: false,
- isSuccesfulFlowModalOpen: [false, ''],
+ isSuccesfulFlowModalOpen: [false, '', 'mint', 0],
isSelectBitcoinWalletModalOpen: false,
isLedgerModalOpen: false,
};
@@ -22,8 +22,13 @@ export const modalSlice = createSlice({
state.isSelectWalletModalOpen = !state.isSelectWalletModalOpen;
},
toggleSuccessfulFlowModalVisibility: (state, action) => {
- const { vaultUUID } = action.payload;
- state.isSuccesfulFlowModalOpen = [!state.isSuccesfulFlowModalOpen[0], vaultUUID];
+ const { vaultUUID, flow, assetAmount } = action.payload;
+ state.isSuccesfulFlowModalOpen = [
+ !state.isSuccesfulFlowModalOpen[0],
+ vaultUUID,
+ flow,
+ assetAmount,
+ ];
},
toggleSelectBitcoinWalletModalVisibility: state => {
state.isSelectBitcoinWalletModalOpen = !state.isSelectBitcoinWalletModalOpen;
diff --git a/src/shared/models/form.models.ts b/src/shared/models/form.models.ts
new file mode 100644
index 00000000..92b0dcd2
--- /dev/null
+++ b/src/shared/models/form.models.ts
@@ -0,0 +1,15 @@
+import { FormApi, ReactFormApi } from '@tanstack/react-form';
+
+export interface TransactionFormAPI
+ extends FormApi<
+ {
+ assetAmount: string;
+ },
+ undefined
+ >,
+ ReactFormApi<
+ {
+ assetAmount: string;
+ },
+ undefined
+ > {}
diff --git a/src/styles/button-theme.ts b/src/styles/button-theme.ts
index eb332b33..56c887a7 100644
--- a/src/styles/button-theme.ts
+++ b/src/styles/button-theme.ts
@@ -25,11 +25,11 @@ const navigate = defineStyle({
px: '25px',
h: '50px',
w: '100%',
- fontSize: 'lg',
+ fontSize: 'sm',
fontWeight: 600,
bg: 'none',
border: '1px solid',
- borderColor: 'accent.lightBlue.01',
+ borderColor: 'white.03',
_hover: {
bg: 'accent.lightBlue.01',
},
diff --git a/src/styles/menu-theme.ts b/src/styles/menu-theme.ts
index 0caa1bf0..f76b0c82 100644
--- a/src/styles/menu-theme.ts
+++ b/src/styles/menu-theme.ts
@@ -15,10 +15,10 @@ const account = defineStyle({
fontSize: 'lg',
fontWeight: 800,
color: 'white',
- bg: 'background.content.01',
+ bg: 'background.container.01',
border: '1px solid',
borderRadius: 'md',
- borderColor: 'border.lightBlue.01',
+ borderColor: 'white.03',
_hover: {
bg: 'accent.lightBlue.01',
},
@@ -55,10 +55,10 @@ const networkChange = defineStyle({
fontSize: 'sm',
fontWeight: 800,
color: 'white',
- bg: 'background.content.01',
+ bg: 'background.container.01',
border: '1px solid',
borderRadius: 'md',
- borderColor: 'border.lightBlue.01',
+ borderColor: 'white.03',
_hover: {
bg: 'accent.lightBlue.01',
},