From 15200b5a2879d9cf8a50485668e9452fca4576bc Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Thu, 7 Dec 2023 12:51:09 +0100 Subject: [PATCH 1/2] feat: replaced mint/unmint flow, vault fetching by order with by uuid --- .../components/lock-screen/lock-screen.tsx | 40 +++++--- .../mint-unmint/components/mint/mint.tsx | 12 +-- .../transaction-summary.tsx | 93 +++++++------------ .../components/unmint-vault-selector.tsx | 2 +- .../mint-unmint/components/unmint/unmint.tsx | 8 +- .../modals/components/modal-container.tsx | 1 + .../successful-flow-modal.tsx | 4 +- src/app/components/vault/vault-card.tsx | 2 +- .../vaults-list-group-container.tsx | 4 +- .../components/vaults-list/vaults-list.tsx | 2 +- src/app/hooks/use-bitcoin.ts | 2 +- src/app/hooks/use-observer.ts | 18 ++-- src/app/hooks/use-vaults.ts | 57 +++++++----- src/app/providers/vault-context-provider.tsx | 1 + .../slices/mintunmint/mintunmint.slice.ts | 12 +-- src/app/store/slices/modal/modal.slice.ts | 6 +- 16 files changed, 130 insertions(+), 134 deletions(-) diff --git a/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx b/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx index 01fa4b25..9d97d030 100644 --- a/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx +++ b/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx @@ -6,34 +6,46 @@ import { useVaults } from "@hooks/use-vaults"; import { BlockchainContext } from "../../../../providers/blockchain-context-provider"; import { LockScreenProtocolFee } from "./components/protocol-fee"; +import { Vault } from "@models/vault"; -export function LockScreen(): React.JSX.Element { +interface LockScreenProps { + currentStep: [number, string]; +} + + +export function LockScreen({ currentStep }: LockScreenProps): React.JSX.Element { const { readyVaults } = useVaults(); const blockchainContext = useContext(BlockchainContext); const bitcoin = blockchainContext?.bitcoin; const [isSubmitting, setIsSubmitting] = useState(false); + const currentVault = readyVaults.find((vault) => vault.uuid === currentStep[1]); + + async function handleClick(currentVault?: Vault) { + if (!currentVault) return; + + try { + setIsSubmitting(true); + await bitcoin?.fetchBitcoinContractOfferAndSendToUserWallet( + currentVault, + ); + } catch (error) { + setIsSubmitting(false); + throw new Error("Error locking vault"); + } + } + return ( - + diff --git a/src/app/components/mint-unmint/components/mint/mint.tsx b/src/app/components/mint-unmint/components/mint/mint.tsx index 3f819369..fafd5e31 100644 --- a/src/app/components/mint-unmint/components/mint/mint.tsx +++ b/src/app/components/mint-unmint/components/mint/mint.tsx @@ -16,17 +16,17 @@ export function Mint(): React.JSX.Element { const { mintStep } = useSelector((state: RootState) => state.mintunmint); function handleRestart() { - dispatch(mintUnmintActions.setMintStep(0)); + dispatch(mintUnmintActions.setMintStep([0, ''])); } return ( - + - - {[0].includes(mintStep) && } - {[1].includes(mintStep) && } - {[2, 3].includes(mintStep) && ( + + {[0].includes(mintStep[0]) && } + {[1].includes(mintStep[0]) && } + {[2, 3].includes(mintStep[0]) && ( ( - getVault(flow, currentStep), - ); - - function getVault(flow: "mint" | "unmint", currentStep: number) { - if (flow === "mint") { - return currentStep === 2 ? fundingVaults[0] : fundedVaults[0]; - } else { - return currentStep === 1 ? closingVaults[0] : closedVaults[0]; - } - } + const { allVaults } = useVaults(); + const currentVault = allVaults.find(vault => vault.uuid === currentStep[1]); - useEffect(() => { - setCurrentVault(getVault(flow, currentStep)); - }, [flow, currentStep]); + const showProcessing = + (flow === 'mint' && currentStep[0] === 2) || (flow === 'unmint' && currentStep[0] === 1); return ( - - - {(flow === "mint" && currentStep === 2) || - (flow === "unmint" && currentStep === 1 && ( - - ))} - - {flowPropertyMap[flow][currentStep].title}: - + + + {showProcessing && } + {flowPropertyMap[flow][currentStep[0]].title}: - {(flow === "mint" && currentStep === 2) || - (flow === "unmint" && currentStep === 1) ? ( + {showProcessing && ( <> - - b) {flowPropertyMap[flow][currentStep].subtitle}: + + b) {flowPropertyMap[flow][currentStep[0]].subtitle}: - ) : ( - false )} - - You can check all of your vaults' status under{" "} - + + You can check all of your vaults' status under{' '} + My Vaults - {" "} + {' '} tab. 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 9ef4c8a5..e27459b8 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 @@ -66,7 +66,7 @@ export function UnmintVaultSelector(): React.JSX.Element { /> ) : ( - + - + - - {[0].includes(unmintStep) && } - {[1, 2].includes(unmintStep) && ( + + {[0].includes(unmintStep[0]) && } + {[1, 2].includes(unmintStep[0]) && ( ); 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 0baa2817..4a3dc5ab 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 @@ -5,12 +5,14 @@ import { ModalLayout } from "../components/modal.layout"; interface SuccessfulFlowModalProps extends ModalComponentProps { flow: "mint" | "unmint"; + vaultUUID: string; } export function SuccessfulFlowModal({ isOpen, handleClose, flow, + vaultUUID }: SuccessfulFlowModalProps): React.JSX.Element { return ( handleClose()} > diff --git a/src/app/components/vault/vault-card.tsx b/src/app/components/vault/vault-card.tsx index 6c1bea4a..bb9e528d 100644 --- a/src/app/components/vault/vault-card.tsx +++ b/src/app/components/vault/vault-card.tsx @@ -13,7 +13,7 @@ import { useToast } from "@chakra-ui/react"; import { BitcoinError } from "@models/error-types"; interface VaultCardProps { - vault: Vault; + vault?: Vault; isSelected?: boolean; isSelectable?: boolean; handleSelect?: () => void; diff --git a/src/app/components/vaults-list/components/vaults-list-group-container.tsx b/src/app/components/vaults-list/components/vaults-list-group-container.tsx index 0f1a00a4..f645f6a3 100644 --- a/src/app/components/vaults-list/components/vaults-list-group-container.tsx +++ b/src/app/components/vaults-list/components/vaults-list-group-container.tsx @@ -20,9 +20,9 @@ export function VaultsListGroupContainer({ if (vaults.length === 0) return false; return ( - + {label && ( - + {["Locking BTC in Progress", "Unlocking BTC in Progress"].includes( label, ) && } diff --git a/src/app/components/vaults-list/vaults-list.tsx b/src/app/components/vaults-list/vaults-list.tsx index 471ba8cb..02f4924c 100644 --- a/src/app/components/vaults-list/vaults-list.tsx +++ b/src/app/components/vaults-list/vaults-list.tsx @@ -19,7 +19,7 @@ export function VaultsList({ return ( {title && ( - + {title} )} diff --git a/src/app/hooks/use-bitcoin.ts b/src/app/hooks/use-bitcoin.ts index 073ba7be..150ed3c2 100644 --- a/src/app/hooks/use-bitcoin.ts +++ b/src/app/hooks/use-bitcoin.ts @@ -60,7 +60,7 @@ export function useBitcoin(): UseBitcoinReturnType { networkID: network.id, }), ); - dispatch(mintUnmintActions.setMintStep(2)); + dispatch(mintUnmintActions.setMintStep([2, vaultUUID])); } catch (error: any) { throw new BitcoinError( `Could not send contract offer for signing: ${error.error.message}`, diff --git a/src/app/hooks/use-observer.ts b/src/app/hooks/use-observer.ts index 3cea3a1e..860a9c3a 100644 --- a/src/app/hooks/use-observer.ts +++ b/src/app/hooks/use-observer.ts @@ -14,8 +14,6 @@ export function useObserver(ethereum: UseEthereumReturnType): void { protocolContract, dlcBTCContract, getVault, - getDLCBTCBalance, - getLockedBTCBalance, } = ethereum; useEffect(() => { @@ -35,7 +33,7 @@ export function useObserver(ethereum: UseEthereumReturnType): void { console.log(`Vault ${vaultUUID} is ready`); await getVault(vaultUUID, VaultState.READY).then(() => { - dispatch(mintUnmintActions.setMintStep(1)); + dispatch(mintUnmintActions.setMintStep([1, vaultUUID])); }); }); @@ -49,7 +47,7 @@ export function useObserver(ethereum: UseEthereumReturnType): void { console.log(`Vault ${vaultUUID} is closing`); await getVault(vaultUUID, VaultState.CLOSING).then(() => { - dispatch(mintUnmintActions.setUnmintStep(1)); + dispatch(mintUnmintActions.setUnmintStep([1, vaultUUID])); }); }); @@ -63,11 +61,9 @@ export function useObserver(ethereum: UseEthereumReturnType): void { console.log(`Vault ${vaultUUID} is minted`); await getVault(vaultUUID, VaultState.FUNDED).then(() => { - dispatch(mintUnmintActions.setMintStep(0)); - dispatch(modalActions.toggleSuccessfulFlowModalVisibility("mint")); + dispatch(mintUnmintActions.setMintStep([0, vaultUUID])); + dispatch(modalActions.toggleSuccessfulFlowModalVisibility({ flow: "mint", vaultUUID})); }); - await getDLCBTCBalance(); - await getLockedBTCBalance(); }); protocolContract.on("PostCloseDLCHandler", async (...args) => { @@ -80,11 +76,9 @@ export function useObserver(ethereum: UseEthereumReturnType): void { console.log(`Vault ${vaultUUID} is closed`); await getVault(vaultUUID, VaultState.CLOSED).then(() => { - dispatch(mintUnmintActions.setUnmintStep(0)); - dispatch(modalActions.toggleSuccessfulFlowModalVisibility("unmint")); + dispatch(mintUnmintActions.setUnmintStep([0, vaultUUID])); + dispatch(modalActions.toggleSuccessfulFlowModalVisibility({flow: "unmint", vaultUUID})); }); - await getDLCBTCBalance(); - await getLockedBTCBalance(); }); }, [protocolContract, dlcBTCContract, network]); } diff --git a/src/app/hooks/use-vaults.ts b/src/app/hooks/use-vaults.ts index 74f31275..ef8db224 100644 --- a/src/app/hooks/use-vaults.ts +++ b/src/app/hooks/use-vaults.ts @@ -1,12 +1,13 @@ -import { useEffect, useMemo, useState } from "react"; -import { useSelector } from "react-redux"; +import { useEffect, useMemo, useState } from 'react'; +import { useSelector } from 'react-redux'; -import { Vault, VaultState } from "@models/vault"; -import { RootState } from "@store/index"; +import { Vault, VaultState } from '@models/vault'; +import { RootState } from '@store/index'; -import { UseEthereumReturnType } from "./use-ethereum"; +import { UseEthereumReturnType } from './use-ethereum'; export interface UseVaultsReturnType { + allVaults: Vault[]; readyVaults: Vault[]; fundingVaults: Vault[]; fundedVaults: Vault[]; @@ -15,9 +16,7 @@ export interface UseVaultsReturnType { isLoading: boolean; } -export function useVaults( - ethereum?: UseEthereumReturnType, -): UseVaultsReturnType { +export function useVaults(ethereum?: UseEthereumReturnType): UseVaultsReturnType { const { vaults } = useSelector((state: RootState) => state.vault); const { address, network } = useSelector((state: RootState) => state.account); const [isLoading, setIsLoading] = useState(true); @@ -36,43 +35,55 @@ export function useVaults( fetchData(); }, [address, network, ethereum?.isLoaded]); + console.log('vaults', vaults); + console.log('network', network); + + const allVaults = useMemo( + () => + vaults[network ? network.id : '1'] + .filter(vault => vault.state !== VaultState.READY) + .sort((a, b) => b.timestamp - a.timestamp), + [vaults, network] + ); + const readyVaults = useMemo( () => - vaults[network ? network.id : "1"] - .filter((vault) => vault.state === VaultState.READY) + vaults[network ? network.id : '1'] + .filter(vault => vault.state === VaultState.READY) .sort((a, b) => b.timestamp - a.timestamp), - [vaults, network], + [vaults, network] ); const fundedVaults = useMemo( () => - vaults[network ? network.id : "1"] - .filter((vault) => vault.state === VaultState.FUNDED) + vaults[network ? network.id : '1'] + .filter(vault => vault.state === VaultState.FUNDED) .sort((a, b) => b.timestamp - a.timestamp), - [vaults, network], + [vaults, network] ); const fundingVaults = useMemo( () => - vaults[network ? network.id : "1"] - .filter((vault) => vault.state === VaultState.FUNDING) + vaults[network ? network.id : '1'] + .filter(vault => vault.state === VaultState.FUNDING) .sort((a, b) => b.timestamp - a.timestamp), - [vaults, network], + [vaults, network] ); const closingVaults = useMemo( () => - vaults[network ? network.id : "1"] - .filter((vault) => vault.state === VaultState.CLOSING) + vaults[network ? network.id : '1'] + .filter(vault => vault.state === VaultState.CLOSING) .sort((a, b) => b.timestamp - a.timestamp), - [vaults, network], + [vaults, network] ); const closedVaults = useMemo( () => - vaults[network ? network.id : "1"] - .filter((vault) => vault.state === VaultState.CLOSED) + vaults[network ? network.id : '1'] + .filter(vault => vault.state === VaultState.CLOSED) .sort((a, b) => b.timestamp - a.timestamp), - [vaults, network], + [vaults, network] ); return { + allVaults, readyVaults, fundingVaults, closingVaults, diff --git a/src/app/providers/vault-context-provider.tsx b/src/app/providers/vault-context-provider.tsx index 64bbfc7c..6502fe94 100644 --- a/src/app/providers/vault-context-provider.tsx +++ b/src/app/providers/vault-context-provider.tsx @@ -11,6 +11,7 @@ interface VaultContextType { export const VaultContext = createContext({ vaults: { + allVaults: [], readyVaults: [], fundingVaults: [], fundedVaults: [], diff --git a/src/app/store/slices/mintunmint/mintunmint.slice.ts b/src/app/store/slices/mintunmint/mintunmint.slice.ts index 9fad15b8..dbf1edee 100644 --- a/src/app/store/slices/mintunmint/mintunmint.slice.ts +++ b/src/app/store/slices/mintunmint/mintunmint.slice.ts @@ -1,13 +1,13 @@ import { createSlice } from "@reduxjs/toolkit"; interface MintUnmintState { - mintStep: number; - unmintStep: number; + mintStep: [number, string] + unmintStep: [number, string] } const initialMintUnmintState: MintUnmintState = { - mintStep: 0, - unmintStep: 0, + mintStep: [0, ''], + unmintStep: [0, ''], }; export const mintUnmintSlice = createSlice({ @@ -21,8 +21,8 @@ export const mintUnmintSlice = createSlice({ state.unmintStep = action.payload; }, resetMintUnmintState: (state) => { - state.mintStep = 0; - state.unmintStep = 0; + state.mintStep = [0, '']; + state.unmintStep = [0, '']; }, }, }); diff --git a/src/app/store/slices/modal/modal.slice.ts b/src/app/store/slices/modal/modal.slice.ts index 037d8f5d..c2290e56 100644 --- a/src/app/store/slices/modal/modal.slice.ts +++ b/src/app/store/slices/modal/modal.slice.ts @@ -2,7 +2,7 @@ import { createSlice } from "@reduxjs/toolkit"; interface ModalState { isSelectWalletModalOpen: boolean; - isSuccesfulFlowModalOpen: [boolean, "mint" | "unmint"]; + isSuccesfulFlowModalOpen: [boolean, "mint" | "unmint", string?]; } const initialModalState: ModalState = { @@ -18,9 +18,11 @@ export const modalSlice = createSlice({ state.isSelectWalletModalOpen = !state.isSelectWalletModalOpen; }, toggleSuccessfulFlowModalVisibility: (state, action) => { + const { flow, vaultUUID } = action.payload; state.isSuccesfulFlowModalOpen = [ !state.isSuccesfulFlowModalOpen[0], - action.payload, + flow, + vaultUUID, ]; }, }, From ebc4655316d89049c5635c44f301c64fca832419 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Thu, 7 Dec 2023 16:13:25 +0100 Subject: [PATCH 2/2] feat: modified lock button on vault card, modified mintunmint tabs --- .eslintrc.cjs | 8 + .prettiercc.js => .prettierrc.js | 0 src/app/app.tsx | 16 +- src/app/common/utilities.tsx | 8 +- src/app/components/account/account.tsx | 31 ++- .../account/components/account-menu.tsx | 35 +--- src/app/components/app.layout.tsx | 13 +- .../company-website-button.tsx | 17 +- .../custom-skeleton/custom-skeleton.tsx | 15 +- src/app/components/fade-layer/fade-layer.tsx | 21 +- .../header/components/header.layout.tsx | 6 +- src/app/components/header/components/tabs.tsx | 24 +-- src/app/components/header/header.tsx | 17 +- .../lock-screen/components/protocol-fee.tsx | 35 ++-- .../components/lock-screen/lock-screen.tsx | 29 ++- .../components/mint-unmint.layout.tsx | 18 +- .../mint/components/mint.layout.tsx | 18 +- .../mint-unmint/components/mint/mint.tsx | 35 ++-- .../components/progress-timeline-step.tsx | 38 ++-- .../progress-timeline/progress-timeline.tsx | 54 ++---- .../protocol-summary-stack.layout.tsx | 16 +- .../protocol-summary-stack.tsx | 33 ++-- .../setup-information-stack.layout.tsx | 16 +- .../setup-information-wallet-requirement.tsx | 18 +- .../setup-information-stack.tsx | 57 +++--- .../components/transaction-form-input.tsx | 46 ++--- .../components/transaction-form-warning.tsx | 20 +- .../transaction-form/transaction-form.tsx | 56 ++---- .../transaction-summary-preview-card.tsx | 42 ++-- .../components/unmint-vault-selector.tsx | 51 ++--- .../unmint/components/unmint.layout.tsx | 18 +- .../mint-unmint/components/unmint/unmint.tsx | 33 ++-- .../components/walkthrough-blockchain-tag.tsx | 22 +-- .../components/walkthrough-header.tsx | 12 +- .../components/walkthrough.layout.tsx | 10 +- .../components/walkthrough/walkthrough.tsx | 114 +++++------ .../components/mint-unmint/mint-unmint.tsx | 56 +++--- .../modals/components/modal-container.tsx | 24 +-- .../modals/components/modal.layout.tsx | 4 +- .../components/select-wallet-menu.tsx | 15 +- .../select-wallet-modal.tsx | 62 +++--- .../successful-flow-modal.tsx | 20 +- .../components/my-vaults-small.layout.tsx | 24 ++- .../my-vaults-small/my-vaults-small.tsx | 60 ++---- .../my-vaults-header-balance-info.tsx | 14 +- .../my-vaults-header/my-vaults-header.tsx | 35 ++-- .../components/my-vaults-large.layout.tsx | 22 +-- .../my-vaults-setup-information-stack.tsx | 27 ++- .../components/my-vaults/my-vaults-large.tsx | 63 ++---- .../select-network-button.tsx | 34 ++-- .../components/step-button/step-button.tsx | 18 +- src/app/components/tab-button/tab-button.tsx | 14 +- .../tutorial-video/tutorial-video.tsx | 36 ++-- .../vault/components/vault-card-blank.tsx | 18 +- .../vault/components/vault-card.layout.tsx | 26 +-- .../vault/components/vault-expand-button.tsx | 14 +- .../vault-expanded-information-row.tsx | 8 +- ...t-expanded-information-transaction-row.tsx | 24 ++- .../vault-expanded-information.tsx | 29 +-- .../vault/components/vault-information.tsx | 70 ++++--- .../vault/components/vault-progress-bar.tsx | 21 +- src/app/components/vault/vault-card.tsx | 58 ++---- .../vaults-list-group-blank-container.tsx | 8 +- .../vaults-list-group-container.tsx | 18 +- .../components/vaults-list/vaults-list.tsx | 22 +-- src/app/hooks/use-bitcoin.ts | 53 +++-- src/app/hooks/use-confirmation-checker.ts | 32 +--- src/app/hooks/use-endpoints.ts | 40 ++-- src/app/hooks/use-ethereum.ts | 181 +++++++----------- src/app/hooks/use-observer.ts | 37 ++-- src/app/hooks/use-vaults.ts | 8 +- src/app/pages/about/about.tsx | 6 +- src/app/pages/components/page.layout.tsx | 12 +- src/app/pages/dashboard/dashboard.tsx | 12 +- src/app/pages/my-vaults/my-vaults.tsx | 4 +- .../providers/balance-context-provider.tsx | 31 ++- .../providers/blockchain-context-provider.tsx | 19 +- src/app/providers/vault-context-provider.tsx | 16 +- src/app/store/index.ts | 29 ++- .../store/slices/account/account.actions.ts | 2 +- src/app/store/slices/account/account.slice.ts | 10 +- .../slices/mintunmint/mintunmint.actions.ts | 2 +- .../slices/mintunmint/mintunmint.slice.ts | 18 +- src/app/store/slices/modal/modal.actions.ts | 2 +- src/app/store/slices/modal/modal.slice.ts | 16 +- src/app/store/slices/vault/vault.actions.ts | 2 +- src/app/store/slices/vault/vault.slice.ts | 35 ++-- src/index.tsx | 26 +-- src/shared/models/error-types.ts | 4 +- src/shared/models/has-children.tsx | 2 +- src/shared/models/network.ts | 78 ++++---- src/shared/models/vault.tsx | 2 +- src/shared/models/wallet.ts | 8 +- src/styles/app-theme.ts | 49 +++-- src/styles/button-theme.ts | 99 +++++----- src/styles/css-styles.ts | 14 +- src/styles/divider-theme.ts | 14 +- src/styles/icon.tsx | 8 +- src/styles/menu-theme.ts | 111 +++++------ src/styles/modal-theme.ts | 25 ++- src/styles/select-theme.ts | 23 +-- src/styles/tabs-theme.ts | 27 +-- src/styles/text-theme.ts | 22 +-- tests/integration/example.spec.ts | 16 +- tests/unit/utilities.unit.test.ts | 10 +- 105 files changed, 1264 insertions(+), 1687 deletions(-) rename .prettiercc.js => .prettierrc.js (100%) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 1c841480..b78842ea 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -31,6 +31,14 @@ module.exports = { '@typescript-eslint/ban-types': ['error'], '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], '@typescript-eslint/array-type': ['error'], + '@typescript-eslint/quotes': [ + 'error', + 'single', + { + avoidEscape: true, + allowTemplateLiterals: true, + }, + ], 'deprecation/deprecation': ['warn'], diff --git a/.prettiercc.js b/.prettierrc.js similarity index 100% rename from .prettiercc.js rename to .prettierrc.js diff --git a/src/app/app.tsx b/src/app/app.tsx index a74083a7..6600bb51 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -1,13 +1,13 @@ -import { Route } from "react-router-dom"; +import { Route } from 'react-router-dom'; -import { AppLayout } from "@components/app.layout"; -import { MyVaults } from "@pages/my-vaults/my-vaults"; +import { AppLayout } from '@components/app.layout'; +import { MyVaults } from '@pages/my-vaults/my-vaults'; -import { About } from "./pages/about/about"; -import { Dashboard } from "./pages/dashboard/dashboard"; -import { BalanceContextProvider } from "./providers/balance-context-provider"; -import { BlockchainContextProvider } from "./providers/blockchain-context-provider"; -import { VaultContextProvider } from "./providers/vault-context-provider"; +import { About } from './pages/about/about'; +import { Dashboard } from './pages/dashboard/dashboard'; +import { BalanceContextProvider } from './providers/balance-context-provider'; +import { BlockchainContextProvider } from './providers/blockchain-context-provider'; +import { VaultContextProvider } from './providers/vault-context-provider'; export function App(): React.JSX.Element { return ( diff --git a/src/app/common/utilities.tsx b/src/app/common/utilities.tsx index 741d844d..41209106 100644 --- a/src/app/common/utilities.tsx +++ b/src/app/common/utilities.tsx @@ -1,4 +1,4 @@ -import Decimal from "decimal.js"; +import Decimal from 'decimal.js'; export function easyTruncateAddress(address: string): string { const truncationLength = 4; @@ -7,11 +7,7 @@ export function easyTruncateAddress(address: string): string { return `${prefix}...${suffix}`; } -export function customShiftValue( - value: number, - shift: number, - unshift: boolean, -): number { +export function customShiftValue(value: number, shift: number, unshift: boolean): number { const decimalPoweredShift = new Decimal(10 ** shift); const decimalValue = new Decimal(Number(value)); const decimalShiftedValue = unshift diff --git a/src/app/components/account/account.tsx b/src/app/components/account/account.tsx index 59c29efc..90ca5345 100644 --- a/src/app/components/account/account.tsx +++ b/src/app/components/account/account.tsx @@ -1,29 +1,26 @@ -import { useEffect, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; -import { Button, HStack } from "@chakra-ui/react"; -import { AccountMenu } from "@components/account/components/account-menu"; -import { Wallet, WalletType, ethereumWallets } from "@models/wallet"; -import { RootState } from "@store/index"; -import { accountActions } from "@store/slices/account/account.actions"; -import { modalActions } from "@store/slices/modal/modal.actions"; -import { mintUnmintActions } from "@store/slices/mintunmint/mintunmint.actions"; +import { Button, HStack } from '@chakra-ui/react'; +import { AccountMenu } from '@components/account/components/account-menu'; +import { Wallet, WalletType, ethereumWallets } from '@models/wallet'; +import { RootState } from '@store/index'; +import { accountActions } from '@store/slices/account/account.actions'; +import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions'; +import { modalActions } from '@store/slices/modal/modal.actions'; function findWalletById(walletType: WalletType): Wallet | undefined { - const wallet = ethereumWallets.find((wallet) => wallet.id === walletType); + const wallet = ethereumWallets.find(wallet => wallet.id === walletType); return wallet; } export function Account(): React.JSX.Element { const dispatch = useDispatch(); const [wallet, setWallet] = useState(undefined); - const { address, walletType } = useSelector( - (state: RootState) => state.account, - ); + const { address, walletType } = useSelector((state: RootState) => state.account); useEffect(() => { - const currentWallet = - walletType !== undefined && findWalletById(walletType); + const currentWallet = walletType !== undefined && findWalletById(walletType); if (currentWallet) setWallet(currentWallet); }, [walletType]); @@ -37,7 +34,7 @@ export function Account(): React.JSX.Element { } return ( - + {address !== undefined && wallet !== undefined ? ( onDisconnectWalletClick()} /> ) : ( - )} diff --git a/src/app/components/account/components/account-menu.tsx b/src/app/components/account/components/account-menu.tsx index a3e5c615..0b8d1a62 100644 --- a/src/app/components/account/components/account-menu.tsx +++ b/src/app/components/account/components/account-menu.tsx @@ -1,15 +1,7 @@ -import { ChevronDownIcon } from "@chakra-ui/icons"; -import { - HStack, - Image, - Menu, - MenuButton, - MenuItem, - MenuList, - Text, -} from "@chakra-ui/react"; -import { easyTruncateAddress } from "@common/utilities"; -import { Wallet } from "@models/wallet"; +import { ChevronDownIcon } from '@chakra-ui/icons'; +import { HStack, Image, Menu, MenuButton, MenuItem, MenuList, Text } from '@chakra-ui/react'; +import { easyTruncateAddress } from '@common/utilities'; +import { Wallet } from '@models/wallet'; interface AccountMenuProps { address: string; @@ -17,23 +9,14 @@ interface AccountMenuProps { handleClick: () => void; } -export function AccountMenu({ - address, - wallet, - handleClick, -}: AccountMenuProps): React.JSX.Element { +export function AccountMenu({ address, wallet, handleClick }: AccountMenuProps): React.JSX.Element { return ( - + - - {wallet?.name} + + {wallet?.name} {easyTruncateAddress(address)} - + diff --git a/src/app/components/app.layout.tsx b/src/app/components/app.layout.tsx index 49eaaa25..42593672 100644 --- a/src/app/components/app.layout.tsx +++ b/src/app/components/app.layout.tsx @@ -1,14 +1,15 @@ -import { BrowserRouter as Router, Routes } from "react-router-dom"; +import { BrowserRouter as Router, Routes } from 'react-router-dom'; -import { VStack } from "@chakra-ui/react"; -import { Header } from "@components/header/header"; -import { HasChildren } from "@models/has-children"; -import { ModalContainer } from "./modals/components/modal-container"; +import { VStack } from '@chakra-ui/react'; +import { Header } from '@components/header/header'; +import { HasChildren } from '@models/has-children'; + +import { ModalContainer } from './modals/components/modal-container'; export function AppLayout({ children }: HasChildren): React.JSX.Element { return ( - +
{children} diff --git a/src/app/components/company-website-button/company-website-button.tsx b/src/app/components/company-website-button/company-website-button.tsx index 8fd6aaf6..67b484be 100644 --- a/src/app/components/company-website-button/company-website-button.tsx +++ b/src/app/components/company-website-button/company-website-button.tsx @@ -1,18 +1,13 @@ -import { Button, Image } from "@chakra-ui/react"; +import { Button, Image } from '@chakra-ui/react'; export function CompanyWebsiteButton(): React.JSX.Element { - const companyWebsiteURL = "https://www.dlc.link/"; - const logoPath = "./images/logos/dlc-link-logo.svg"; - const altText = "DLC.Link Logo"; + const companyWebsiteURL = 'https://www.dlc.link/'; + const logoPath = './images/logos/dlc-link-logo.svg'; + const altText = 'DLC.Link Logo'; return ( - ); } diff --git a/src/app/components/custom-skeleton/custom-skeleton.tsx b/src/app/components/custom-skeleton/custom-skeleton.tsx index 97bbb27e..ce21e031 100644 --- a/src/app/components/custom-skeleton/custom-skeleton.tsx +++ b/src/app/components/custom-skeleton/custom-skeleton.tsx @@ -1,18 +1,9 @@ -import { Skeleton } from "@chakra-ui/react"; +import { Skeleton } from '@chakra-ui/react'; interface CustomSkeletonProps { height: string; } -export function CustomSkeleton({ - height, -}: CustomSkeletonProps): React.JSX.Element { - return ( - - ); +export function CustomSkeleton({ height }: CustomSkeletonProps): React.JSX.Element { + return ; } diff --git a/src/app/components/fade-layer/fade-layer.tsx b/src/app/components/fade-layer/fade-layer.tsx index eae81d31..309fb6c9 100644 --- a/src/app/components/fade-layer/fade-layer.tsx +++ b/src/app/components/fade-layer/fade-layer.tsx @@ -1,4 +1,4 @@ -import { VStack } from "@chakra-ui/react"; +import { VStack } from '@chakra-ui/react'; interface FadeLayerProps { children: React.ReactNode; @@ -6,30 +6,19 @@ interface FadeLayerProps { fadeHeight: string; } -export function FadeLayer({ - children, - height, - fadeHeight, -}: FadeLayerProps): React.JSX.Element { +export function FadeLayer({ children, height, fadeHeight }: FadeLayerProps): React.JSX.Element { const afterStyles = { content: '""', - position: "absolute", + position: 'absolute', bottom: 0, left: 0, right: 0, height: fadeHeight, - backgroundImage: - "linear-gradient(to top, background.container.01, transparent)", + backgroundImage: 'linear-gradient(to top, background.container.01, transparent)', }; return ( - + {children} ); diff --git a/src/app/components/header/components/header.layout.tsx b/src/app/components/header/components/header.layout.tsx index 4a37b698..f6990760 100644 --- a/src/app/components/header/components/header.layout.tsx +++ b/src/app/components/header/components/header.layout.tsx @@ -1,9 +1,9 @@ -import { HStack } from "@chakra-ui/react"; -import { HasChildren } from "@models/has-children"; +import { HStack } from '@chakra-ui/react'; +import { HasChildren } from '@models/has-children'; export function HeaderLayout({ children }: HasChildren): React.JSX.Element { return ( - + {children} ); diff --git a/src/app/components/header/components/tabs.tsx b/src/app/components/header/components/tabs.tsx index cedcad52..cfc24651 100644 --- a/src/app/components/header/components/tabs.tsx +++ b/src/app/components/header/components/tabs.tsx @@ -1,5 +1,5 @@ -import { HStack } from "@chakra-ui/react"; -import { TabButton } from "@components/tab-button/tab-button"; +import { HStack } from '@chakra-ui/react'; +import { TabButton } from '@components/tab-button/tab-button'; interface NavigationTabsProps { activeTab: string; @@ -11,21 +11,21 @@ export function NavigationTabs({ handleTabClick, }: NavigationTabsProps): React.JSX.Element { return ( - + handleTabClick("/")} + title={'Mint/Unmint dlcBTC'} + isActive={activeTab === '/'} + handleClick={() => handleTabClick('/')} /> handleTabClick("/my-vaults")} + title={'My Vaults'} + isActive={activeTab === '/my-vaults'} + handleClick={() => handleTabClick('/my-vaults')} /> handleTabClick("/how-it-works")} + title={'How It Works'} + isActive={activeTab === '/how-it-works'} + handleClick={() => handleTabClick('/how-it-works')} /> ); diff --git a/src/app/components/header/header.tsx b/src/app/components/header/header.tsx index 617b74f7..3d896f8f 100644 --- a/src/app/components/header/header.tsx +++ b/src/app/components/header/header.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { useLocation, useNavigate } from "react-router-dom"; +import React from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; -import { Account } from "@components/account/account"; -import { CompanyWebsiteButton } from "@components/company-website-button/company-website-button"; -import { HeaderLayout } from "@components/header/components/header.layout"; +import { Account } from '@components/account/account'; +import { CompanyWebsiteButton } from '@components/company-website-button/company-website-button'; +import { HeaderLayout } from '@components/header/components/header.layout'; -import { NavigationTabs } from "./components/tabs"; +import { NavigationTabs } from './components/tabs'; export function Header(): React.JSX.Element { const navigate = useNavigate(); @@ -18,10 +18,7 @@ export function Header(): React.JSX.Element { return ( - + ); diff --git a/src/app/components/mint-unmint/components/lock-screen/components/protocol-fee.tsx b/src/app/components/mint-unmint/components/lock-screen/components/protocol-fee.tsx index 41759eae..d36f27ac 100644 --- a/src/app/components/mint-unmint/components/lock-screen/components/protocol-fee.tsx +++ b/src/app/components/mint-unmint/components/lock-screen/components/protocol-fee.tsx @@ -1,21 +1,18 @@ -import { HStack, Text, VStack } from "@chakra-ui/react"; +import { HStack, Text, VStack } from '@chakra-ui/react'; interface LockScreenProtocolFeeProps { assetAmount?: number; bitcoinPrice?: number; } -function calculateProtocolFee( - amount: number, - protocolFeePercentage: number, -): string { +function calculateProtocolFee(amount: number, protocolFeePercentage: number): string { return (amount * protocolFeePercentage).toFixed(8); } function calculateProtocolFeeInUSD( assetAmount: number, usdPrice: number, - protocolFeePercentage: number, + protocolFeePercentage: number ): string { return (assetAmount * protocolFeePercentage * usdPrice).toFixed(8); } @@ -26,26 +23,26 @@ export function LockScreenProtocolFee({ }: LockScreenProtocolFeeProps): React.JSX.Element { return ( - - + + Protocol Fee - + {assetAmount && calculateProtocolFee(assetAmount, 0.0001)} BTC - {" "} + {' '} - - ={" "} + + ={' '} {assetAmount && bitcoinPrice && - calculateProtocolFeeInUSD(assetAmount, bitcoinPrice, 0.0001)}{" "} + calculateProtocolFeeInUSD(assetAmount, bitcoinPrice, 0.0001)}{' '} $ diff --git a/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx b/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx index 9d97d030..2ec84d86 100644 --- a/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx +++ b/src/app/components/mint-unmint/components/lock-screen/lock-screen.tsx @@ -1,42 +1,39 @@ -import { useContext, useState } from "react"; +import { useContext, useState } from 'react'; -import { Button, VStack } from "@chakra-ui/react"; -import { VaultCard } from "@components/vault/vault-card"; -import { useVaults } from "@hooks/use-vaults"; +import { Button, VStack } from '@chakra-ui/react'; +import { VaultCard } from '@components/vault/vault-card'; +import { useVaults } from '@hooks/use-vaults'; +import { Vault } from '@models/vault'; -import { BlockchainContext } from "../../../../providers/blockchain-context-provider"; -import { LockScreenProtocolFee } from "./components/protocol-fee"; -import { Vault } from "@models/vault"; +import { BlockchainContext } from '../../../../providers/blockchain-context-provider'; +import { LockScreenProtocolFee } from './components/protocol-fee'; interface LockScreenProps { currentStep: [number, string]; } - export function LockScreen({ currentStep }: LockScreenProps): React.JSX.Element { const { readyVaults } = useVaults(); const blockchainContext = useContext(BlockchainContext); const bitcoin = blockchainContext?.bitcoin; const [isSubmitting, setIsSubmitting] = useState(false); - const currentVault = readyVaults.find((vault) => vault.uuid === currentStep[1]); + const currentVault = readyVaults.find(vault => vault.uuid === currentStep[1]); async function handleClick(currentVault?: Vault) { if (!currentVault) return; - + try { setIsSubmitting(true); - await bitcoin?.fetchBitcoinContractOfferAndSendToUserWallet( - currentVault, - ); + await bitcoin?.fetchBitcoinContractOfferAndSendToUserWallet(currentVault); } catch (error) { setIsSubmitting(false); - throw new Error("Error locking vault"); + throw new Error('Error locking vault'); } } return ( - + diff --git a/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-input.tsx b/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-input.tsx index 2184c9f1..50b2836c 100644 --- a/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-input.tsx +++ b/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-input.tsx @@ -1,12 +1,12 @@ -import { HStack, Image, Input, Text, VStack } from "@chakra-ui/react"; -import { Field } from "formik"; +import { HStack, Image, Input, Text, VStack } from '@chakra-ui/react'; +import { Field } from 'formik'; -import { TransactionFormValues } from "../transaction-form"; +import { TransactionFormValues } from '../transaction-form'; function validateTokenAmount(value: number): string | undefined { let error; if (!value) { - error = "Please enter an amount of dlcBTC you would like to mint"; + error = 'Please enter an amount of dlcBTC you would like to mint'; } else if (value < 0.0001) { error = "You can't mint less than 0.0001 dlcBTC"; } @@ -24,38 +24,34 @@ export function TransactionFormInput({ }: TransactionFormInputProps): React.JSX.Element { return ( - {"dlcBTC"} + {'dlcBTC'} - dlcBTC + dlcBTC - + {bitcoinPrice && `= ~${(values.amount * bitcoinPrice).toFixed(4)}$`} diff --git a/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-warning.tsx b/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-warning.tsx index 46a2f212..4c696b42 100644 --- a/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-warning.tsx +++ b/src/app/components/mint-unmint/components/transaction-form/components/transaction-form-warning.tsx @@ -1,4 +1,4 @@ -import { HStack, Link, Text } from "@chakra-ui/react"; +import { HStack, Link, Text } from '@chakra-ui/react'; interface TransactionFormWarningProps { assetAmount: number; @@ -8,20 +8,18 @@ export function TransactionFormWarning({ assetAmount, }: TransactionFormWarningProps): React.JSX.Element { return ( - - - - Make sure you have {assetAmount} BTC + (fees){" "} - - in your{" "} + + + Make sure you have {assetAmount} BTC + (fees) + in your{' '} Leather Wallet - {" "} + {' '} before proceeding to the next step. diff --git a/src/app/components/mint-unmint/components/transaction-form/transaction-form.tsx b/src/app/components/mint-unmint/components/transaction-form/transaction-form.tsx index 97624c51..ac4fecf6 100644 --- a/src/app/components/mint-unmint/components/transaction-form/transaction-form.tsx +++ b/src/app/components/mint-unmint/components/transaction-form/transaction-form.tsx @@ -1,20 +1,13 @@ -import { useContext, useState } from "react"; +import { useContext, useState } from 'react'; -import { - Button, - FormControl, - FormErrorMessage, - Text, - VStack, - useToast, -} from "@chakra-ui/react"; -import { customShiftValue } from "@common/utilities"; -import { Form, Formik } from "formik"; +import { Button, FormControl, FormErrorMessage, Text, VStack, useToast } from '@chakra-ui/react'; +import { customShiftValue } from '@common/utilities'; +import { EthereumError } from '@models/error-types'; +import { Form, Formik } from 'formik'; -import { BlockchainContext } from "../../../../providers/blockchain-context-provider"; -import { TransactionFormInput } from "./components/transaction-form-input"; -import { TransactionFormWarning } from "./components/transaction-form-warning"; -import { EthereumError } from "@models/error-types"; +import { BlockchainContext } from '../../../../providers/blockchain-context-provider'; +import { TransactionFormInput } from './components/transaction-form-input'; +import { TransactionFormWarning } from './components/transaction-form-warning'; export interface TransactionFormValues { amount: number; @@ -32,18 +25,14 @@ export function TransactionForm(): React.JSX.Element { async function handleSetup(btcDepositAmount: number) { try { setIsSubmitting(true); - const shiftedBTCDepositAmount = customShiftValue( - btcDepositAmount, - 8, - false, - ); + const shiftedBTCDepositAmount = customShiftValue(btcDepositAmount, 8, false); await ethereum?.setupVault(shiftedBTCDepositAmount); } catch (error) { setIsSubmitting(false); toast({ - title: "Failed to create vault", - description: error instanceof EthereumError ? error.message : "", - status: "error", + title: 'Failed to create vault', + description: error instanceof EthereumError ? error.message : '', + status: 'error', duration: 9000, isClosable: true, }); @@ -51,32 +40,27 @@ export function TransactionForm(): React.JSX.Element { } return ( - + { + onSubmit={async values => { await handleSetup(values.amount); }} > {({ handleSubmit, errors, touched, values }) => (
- - + + Amount of dlcBTC you want to mint: - - - {errors.amount} - + + {errors.amount} @@ -118,26 +106,25 @@ export function Walkthrough({ ); } - case "unmint": + case 'unmint': switch (currentStep) { case 0: return ( - - Select the dlcBTC vault you would like to unmint. After a - successful unmint you will receive BTC in the same amount back - to your wallet. + + Select the dlcBTC vault you would like to unmint. After a successful unmint you will + receive BTC in the same amount back to your wallet. ); @@ -146,13 +133,12 @@ export function Walkthrough({ - - After a successful unmint ( - ~1 hour) your - will receive BTC in your bitcoin wallet. + + After a successful unmint (~1 hour) + your will receive BTC in your bitcoin wallet. ); @@ -161,8 +147,8 @@ export function Walkthrough({ ); diff --git a/src/app/components/mint-unmint/mint-unmint.tsx b/src/app/components/mint-unmint/mint-unmint.tsx index b1d6a01f..62b6fc12 100644 --- a/src/app/components/mint-unmint/mint-unmint.tsx +++ b/src/app/components/mint-unmint/mint-unmint.tsx @@ -1,3 +1,5 @@ +import { useDispatch, useSelector } from 'react-redux'; + import { Divider, Spacer, @@ -7,46 +9,50 @@ import { TabPanel, TabPanels, Tabs, -} from "@chakra-ui/react"; +} from '@chakra-ui/react'; +import { RootState } from '@store/index'; +import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions'; -import { MintUnmintLayout } from "./components/mint-unmint.layout"; -import { Mint } from "./components/mint/mint"; -import { ProtocolSummaryStack } from "./components/protocol-summary-stack/protocol-summary-stack"; -import { SetupInformationStack } from "./components/setup-information-stack/setup-information-stack"; -import { Unmint } from "./components/unmint/unmint"; +import { MintUnmintLayout } from './components/mint-unmint.layout'; +import { Mint } from './components/mint/mint'; +import { ProtocolSummaryStack } from './components/protocol-summary-stack/protocol-summary-stack'; +import { SetupInformationStack } from './components/setup-information-stack/setup-information-stack'; +import { Unmint } from './components/unmint/unmint'; interface MintUnmintContainerProps { address?: string; } -export function MintUnmint({ - address, -}: MintUnmintContainerProps): React.JSX.Element { +export function MintUnmint({ address }: MintUnmintContainerProps): React.JSX.Element { + const dispatch = useDispatch(); + + const { activeTab } = useSelector((state: RootState) => state.mintunmint); + + function handleTabsChange(index: number) { + dispatch(mintUnmintActions.setActiveTab(index)); + } + return ( - + Mint Unmint - + - {address ? ( - + + {address ? ( - - ) : ( - - - - - - )} + ) : ( + <> + + + + + )} + diff --git a/src/app/components/modals/components/modal-container.tsx b/src/app/components/modals/components/modal-container.tsx index 39b5d4ab..c36eb394 100644 --- a/src/app/components/modals/components/modal-container.tsx +++ b/src/app/components/modals/components/modal-container.tsx @@ -1,11 +1,11 @@ -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch, useSelector } from 'react-redux'; -import { SelectWalletModal } from "@components/modals/select-wallet-modal/select-wallet-modal"; -import { AnyAction } from "@reduxjs/toolkit"; -import { RootState } from "@store/index"; -import { modalActions } from "@store/slices/modal/modal.actions"; +import { SelectWalletModal } from '@components/modals/select-wallet-modal/select-wallet-modal'; +import { AnyAction } from '@reduxjs/toolkit'; +import { RootState } from '@store/index'; +import { modalActions } from '@store/slices/modal/modal.actions'; -import { SuccessfulFlowModal } from "../successful-flow-modal/successful-flow-modal"; +import { SuccessfulFlowModal } from '../successful-flow-modal/successful-flow-modal'; export interface ModalComponentProps { isOpen: boolean; @@ -15,7 +15,7 @@ export interface ModalComponentProps { export function ModalContainer(): React.JSX.Element { const dispatch = useDispatch(); const { isSelectWalletModalOpen, isSuccesfulFlowModalOpen } = useSelector( - (state: RootState) => state.modal, + (state: RootState) => state.modal ); const handleClosingModal = (actionCreator: () => AnyAction) => { @@ -26,19 +26,15 @@ export function ModalContainer(): React.JSX.Element { <> - handleClosingModal(modalActions.toggleSelectWalletModalVisibility) - } + handleClose={() => handleClosingModal(modalActions.toggleSelectWalletModalVisibility)} /> - handleClosingModal(() => - modalActions.toggleSuccessfulFlowModalVisibility("mint"), - ) + handleClosingModal(() => modalActions.toggleSuccessfulFlowModalVisibility('mint')) } flow={isSuccesfulFlowModalOpen[1]} - vaultUUID={isSuccesfulFlowModalOpen[2] ? isSuccesfulFlowModalOpen[2] : ""} + vaultUUID={isSuccesfulFlowModalOpen[2] ? isSuccesfulFlowModalOpen[2] : ''} /> ); diff --git a/src/app/components/modals/components/modal.layout.tsx b/src/app/components/modals/components/modal.layout.tsx index b720cbec..4db75fa2 100644 --- a/src/app/components/modals/components/modal.layout.tsx +++ b/src/app/components/modals/components/modal.layout.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from "react"; +import { ReactNode } from 'react'; import { Modal, @@ -7,7 +7,7 @@ import { ModalContent, ModalHeader, ModalOverlay, -} from "@chakra-ui/react"; +} from '@chakra-ui/react'; interface SelectWalletModalLayoutProps { title: string; diff --git a/src/app/components/modals/select-wallet-modal/components/select-wallet-menu.tsx b/src/app/components/modals/select-wallet-modal/components/select-wallet-menu.tsx index 00e912d2..f65d2537 100644 --- a/src/app/components/modals/select-wallet-modal/components/select-wallet-menu.tsx +++ b/src/app/components/modals/select-wallet-modal/components/select-wallet-menu.tsx @@ -1,5 +1,5 @@ -import { Button, HStack, Image, Text } from "@chakra-ui/react"; -import { Wallet, WalletType } from "@models/wallet"; +import { Button, HStack, Image, Text } from '@chakra-ui/react'; +import { Wallet, WalletType } from '@models/wallet'; interface SelectWalletMenuProps { wallet: Wallet; @@ -13,13 +13,10 @@ export function SelectWalletMenu({ const { logo, name } = wallet; return ( - ); diff --git a/src/app/components/modals/select-wallet-modal/select-wallet-modal.tsx b/src/app/components/modals/select-wallet-modal/select-wallet-modal.tsx index 04d47173..302f3f3a 100644 --- a/src/app/components/modals/select-wallet-modal/select-wallet-modal.tsx +++ b/src/app/components/modals/select-wallet-modal/select-wallet-modal.tsx @@ -1,28 +1,23 @@ -import { useContext, useState } from "react"; +import { useContext, useState } from 'react'; -import { CheckIcon } from "@chakra-ui/icons"; -import { HStack, ScaleFade, Text, VStack } from "@chakra-ui/react"; -import { ModalComponentProps } from "@components/modals/components/modal-container"; -import { ModalLayout } from "@components/modals/components/modal.layout"; -import { SelectWalletMenu } from "@components/modals/select-wallet-modal/components/select-wallet-menu"; -import { SelectNetworkButton } from "@components/select-network-button/select-network-button"; -import { Network } from "@models/network"; -import { WalletType, ethereumWallets } from "@models/wallet"; +import { CheckIcon } from '@chakra-ui/icons'; +import { HStack, ScaleFade, Text, VStack } from '@chakra-ui/react'; +import { ModalComponentProps } from '@components/modals/components/modal-container'; +import { ModalLayout } from '@components/modals/components/modal.layout'; +import { SelectWalletMenu } from '@components/modals/select-wallet-modal/components/select-wallet-menu'; +import { SelectNetworkButton } from '@components/select-network-button/select-network-button'; +import { Network } from '@models/network'; +import { WalletType, ethereumWallets } from '@models/wallet'; -import { BlockchainContext } from "../../../providers/blockchain-context-provider"; +import { BlockchainContext } from '../../../providers/blockchain-context-provider'; -export function SelectWalletModal({ - isOpen, - handleClose, -}: ModalComponentProps): React.JSX.Element { +export function SelectWalletModal({ isOpen, handleClose }: ModalComponentProps): React.JSX.Element { const blockchainContext = useContext(BlockchainContext); const ethereum = blockchainContext?.ethereum; - const [currentNetwork, setCurrentNetwork] = useState( - undefined, - ); + const [currentNetwork, setCurrentNetwork] = useState(undefined); async function handleLogin(walletType: WalletType) { - if (!currentNetwork) throw new Error("No network selected"); + if (!currentNetwork) throw new Error('No network selected'); await ethereum?.requestEthereumAccount(currentNetwork, walletType); setCurrentNetwork(undefined); handleClose(); @@ -33,32 +28,21 @@ export function SelectWalletModal({ }; return ( - handleClose()} - > - + handleClose()}> + {!currentNetwork ? ( - Select Network + Select Network ) : ( - Network Selected - + Network Selected + )} - - - - Select Wallet - {ethereumWallets.map((wallet) => ( + + + + Select Wallet + {ethereumWallets.map(wallet => ( handleClose()} - > + handleClose()}> ); 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 ad8c93ea..2674fdfb 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 @@ -1,19 +1,17 @@ -import { VStack } from "@chakra-ui/react"; -import { HasChildren } from "@models/has-children"; +import { VStack } from '@chakra-ui/react'; +import { HasChildren } from '@models/has-children'; -export function MyVaultsSmallLayout({ - children, -}: HasChildren): React.JSX.Element { +export function MyVaultsSmallLayout({ children }: HasChildren): React.JSX.Element { return ( {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 26af3d7e..476e596b 100644 --- a/src/app/components/my-vaults-small/my-vaults-small.tsx +++ b/src/app/components/my-vaults-small/my-vaults-small.tsx @@ -1,65 +1,41 @@ -import { useContext } from "react"; -import { useNavigate } from "react-router-dom"; +import { useContext } from 'react'; +import { useNavigate } from 'react-router-dom'; -import { Button, Skeleton } from "@chakra-ui/react"; -import { VaultsListGroupBlankContainer } from "@components/vaults-list/components/vaults-list-group-blank-container"; -import { VaultsList } from "@components/vaults-list/vaults-list"; +import { Button, Skeleton } from '@chakra-ui/react'; +import { VaultsListGroupBlankContainer } from '@components/vaults-list/components/vaults-list-group-blank-container'; +import { VaultsList } from '@components/vaults-list/vaults-list'; -import { VaultContext } from "../../providers/vault-context-provider"; -import { VaultsListGroupContainer } from "../vaults-list/components/vaults-list-group-container"; -import { MyVaultsSmallLayout } from "./components/my-vaults-small.layout"; +import { VaultContext } from '../../providers/vault-context-provider'; +import { VaultsListGroupContainer } from '../vaults-list/components/vaults-list-group-container'; +import { MyVaultsSmallLayout } from './components/my-vaults-small.layout'; interface MyVaultsSmallProps { address?: string; } -export function MyVaultsSmall({ - address, -}: MyVaultsSmallProps): React.JSX.Element { +export function MyVaultsSmall({ address }: MyVaultsSmallProps): React.JSX.Element { const navigate = useNavigate(); const vaultContext = useContext(VaultContext); - const { - readyVaults, - fundingVaults, - fundedVaults, - closingVaults, - closedVaults, - isLoading, - } = vaultContext.vaults; + const { readyVaults, fundingVaults, fundedVaults, closingVaults, closedVaults, isLoading } = + vaultContext.vaults; return ( - + {address ? ( - + - - - - + + + + ) : ( )} - diff --git a/src/app/components/my-vaults/components/my-vaults-header/components/my-vaults-header-balance-info.tsx b/src/app/components/my-vaults/components/my-vaults-header/components/my-vaults-header-balance-info.tsx index 7e99d44a..ff5119d6 100644 --- a/src/app/components/my-vaults/components/my-vaults-header/components/my-vaults-header-balance-info.tsx +++ b/src/app/components/my-vaults/components/my-vaults-header/components/my-vaults-header-balance-info.tsx @@ -1,4 +1,4 @@ -import { HStack, Image, Skeleton, Text, VStack } from "@chakra-ui/react"; +import { HStack, Image, Skeleton, Text, VStack } from '@chakra-ui/react'; interface MyVaultsHeaderBalanceInfoProps { title: string; @@ -16,15 +16,15 @@ export function MyVaultsHeaderBalanceInfo({ showNone, }: MyVaultsHeaderBalanceInfoProps): React.JSX.Element { return ( - - + + {title} - + - {altText} - - {showNone ? "-" : assetAmount} + {altText} + + {showNone ? '-' : assetAmount} diff --git a/src/app/components/my-vaults/components/my-vaults-header/my-vaults-header.tsx b/src/app/components/my-vaults/components/my-vaults-header/my-vaults-header.tsx index 8aeaf0b0..cf0b1f83 100644 --- a/src/app/components/my-vaults/components/my-vaults-header/my-vaults-header.tsx +++ b/src/app/components/my-vaults/components/my-vaults-header/my-vaults-header.tsx @@ -1,6 +1,6 @@ -import { Divider, HStack, Text, VStack } from "@chakra-ui/react"; +import { Divider, HStack, Text, VStack } from '@chakra-ui/react'; -import { MyVaultsHeaderBalanceInfo } from "./components/my-vaults-header-balance-info"; +import { MyVaultsHeaderBalanceInfo } from './components/my-vaults-header-balance-info'; interface MyVaultsLargeHeaderProps { address?: string; @@ -14,36 +14,31 @@ export function MyVaultsLargeHeader({ lockedBTCBalance, }: MyVaultsLargeHeaderProps): React.JSX.Element { return ( - - - + + + My Vaults - - + + - + - + ); } 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 d1b7688f..954ae806 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 @@ -1,18 +1,16 @@ -import { VStack } from "@chakra-ui/react"; -import { HasChildren } from "@models/has-children"; +import { VStack } from '@chakra-ui/react'; +import { HasChildren } from '@models/has-children'; -export function MyVaultsLargeLayout({ - children, -}: HasChildren): React.JSX.Element { +export function MyVaultsLargeLayout({ children }: HasChildren): React.JSX.Element { return ( {children} diff --git a/src/app/components/my-vaults/components/my-vaults-setup-information-stack.tsx b/src/app/components/my-vaults/components/my-vaults-setup-information-stack.tsx index 7db2eecd..e244567a 100644 --- a/src/app/components/my-vaults/components/my-vaults-setup-information-stack.tsx +++ b/src/app/components/my-vaults/components/my-vaults-setup-information-stack.tsx @@ -1,36 +1,31 @@ -import { useDispatch } from "react-redux"; -import { useNavigate } from "react-router-dom"; +import { useDispatch } from 'react-redux'; +import { useNavigate } from 'react-router-dom'; -import { Button, Text, VStack } from "@chakra-ui/react"; -import { modalActions } from "@store/slices/modal/modal.actions"; +import { Button, Text, VStack } from '@chakra-ui/react'; +import { modalActions } from '@store/slices/modal/modal.actions'; export function MyVaultsSetupInformationStack(): React.JSX.Element { const dispatch = useDispatch(); const navigate = useNavigate(); - const header = "Connect your\n Ethereum Wallet"; - const link = "Which wallets are supported?"; + const header = 'Connect your\n Ethereum Wallet'; + const link = 'Which wallets are supported?'; function onConnectWalletClick(): void { dispatch(modalActions.toggleSelectWalletModalVisibility()); } return ( - - - + + + {header} - navigate("/how-it-works")}> + navigate('/how-it-works')}> {link} - diff --git a/src/app/components/my-vaults/my-vaults-large.tsx b/src/app/components/my-vaults/my-vaults-large.tsx index 63d877e0..0c61d9b8 100644 --- a/src/app/components/my-vaults/my-vaults-large.tsx +++ b/src/app/components/my-vaults/my-vaults-large.tsx @@ -1,29 +1,24 @@ -import { useContext } from "react"; -import { useSelector } from "react-redux"; +import { useContext } from 'react'; +import { useSelector } from 'react-redux'; -import { HStack } from "@chakra-ui/react"; -import { VaultsListGroupBlankContainer } from "@components/vaults-list/components/vaults-list-group-blank-container"; -import { VaultsListGroupContainer } from "@components/vaults-list/components/vaults-list-group-container"; -import { VaultsList } from "@components/vaults-list/vaults-list"; -import { RootState } from "@store/index"; +import { HStack } from '@chakra-ui/react'; +import { VaultsListGroupBlankContainer } from '@components/vaults-list/components/vaults-list-group-blank-container'; +import { VaultsListGroupContainer } from '@components/vaults-list/components/vaults-list-group-container'; +import { VaultsList } from '@components/vaults-list/vaults-list'; +import { RootState } from '@store/index'; -import { VaultContext } from "../../providers/vault-context-provider"; -import { MyVaultsLargeHeader } from "./components/my-vaults-header/my-vaults-header"; -import { MyVaultsLargeLayout } from "./components/my-vaults-large.layout"; -import { MyVaultsSetupInformationStack } from "./components/my-vaults-setup-information-stack"; -import { BalanceContext } from "../../providers/balance-context-provider"; +import { BalanceContext } from '../../providers/balance-context-provider'; +import { VaultContext } from '../../providers/vault-context-provider'; +import { MyVaultsLargeHeader } from './components/my-vaults-header/my-vaults-header'; +import { MyVaultsLargeLayout } from './components/my-vaults-large.layout'; +import { MyVaultsSetupInformationStack } from './components/my-vaults-setup-information-stack'; export function MyVaultsLarge(): React.JSX.Element { const { address } = useSelector((state: RootState) => state.account); const { dlcBTCBalance, lockedBTCBalance } = useContext(BalanceContext); const vaultContext = useContext(VaultContext); - const { - readyVaults, - fundingVaults, - fundedVaults, - closingVaults, - closedVaults, - } = vaultContext.vaults; + const { readyVaults, fundingVaults, fundedVaults, closingVaults, closedVaults } = + vaultContext.vaults; return ( @@ -32,42 +27,24 @@ export function MyVaultsLarge(): React.JSX.Element { dlcBTCBalance={dlcBTCBalance} lockedBTCBalance={lockedBTCBalance} /> - + {address ? ( - + - - + + ) : ( )} - + {address ? ( ) : ( )} - + {address ? ( ) : ( diff --git a/src/app/components/select-network-button/select-network-button.tsx b/src/app/components/select-network-button/select-network-button.tsx index aa3acb3d..4f2caea2 100644 --- a/src/app/components/select-network-button/select-network-button.tsx +++ b/src/app/components/select-network-button/select-network-button.tsx @@ -1,13 +1,6 @@ -import { ChevronDownIcon } from "@chakra-ui/icons"; -import { - HStack, - Menu, - MenuButton, - MenuItem, - MenuList, - Text, -} from "@chakra-ui/react"; -import { Network, ethereumNetworks } from "@models/network"; +import { ChevronDownIcon } from '@chakra-ui/icons'; +import { HStack, Menu, MenuButton, MenuItem, MenuList, Text } from '@chakra-ui/react'; +import { Network, ethereumNetworks } from '@models/network'; interface SelectNetworkButtonProps { handleClick: (network: Network) => void; @@ -18,28 +11,23 @@ export function SelectNetworkButton({ handleClick, currentNetwork, }: SelectNetworkButtonProps): React.JSX.Element { - const enabledEthereumNetworkIDs = - import.meta.env.VITE_ENABLED_ETHEREUM_NETWORKS.split(","); - const enabledEthereumNetworks = ethereumNetworks.filter((network) => - enabledEthereumNetworkIDs.includes(network.id), + const enabledEthereumNetworkIDs = import.meta.env.VITE_ENABLED_ETHEREUM_NETWORKS.split(','); + const enabledEthereumNetworks = ethereumNetworks.filter(network => + enabledEthereumNetworkIDs.includes(network.id) ); return ( - + - - {currentNetwork ? currentNetwork.name : "SELECT NETWORK"} - + + {currentNetwork ? currentNetwork.name : 'SELECT NETWORK'} + {enabledEthereumNetworks.map((network, id) => { return ( - handleClick(network)} - > + handleClick(network)}> {network.name} ); diff --git a/src/app/components/step-button/step-button.tsx b/src/app/components/step-button/step-button.tsx index df6c5afd..43a803ac 100644 --- a/src/app/components/step-button/step-button.tsx +++ b/src/app/components/step-button/step-button.tsx @@ -1,20 +1,18 @@ -import { Button } from "@chakra-ui/react"; +import { Button } from '@chakra-ui/react'; interface StepButtonProps { handleClick: () => void; } -export function StepButton({ - handleClick, -}: StepButtonProps): React.JSX.Element { +export function StepButton({ handleClick }: StepButtonProps): React.JSX.Element { return ( ); diff --git a/src/app/components/tutorial-video/tutorial-video.tsx b/src/app/components/tutorial-video/tutorial-video.tsx index efffbe57..874a55f4 100644 --- a/src/app/components/tutorial-video/tutorial-video.tsx +++ b/src/app/components/tutorial-video/tutorial-video.tsx @@ -1,18 +1,18 @@ -import { useState } from "react"; -import YouTube, { YouTubeProps } from "react-youtube"; +import { useState } from 'react'; +import YouTube, { YouTubeProps } from 'react-youtube'; -import { Skeleton, Text, VStack } from "@chakra-ui/react"; +import { Skeleton, Text, VStack } from '@chakra-ui/react'; export function TutorialVideo(): React.JSX.Element { const [isLoading, setIsLoading] = useState(true); - const onPlayerReady: YouTubeProps["onReady"] = (event) => { + const onPlayerReady: YouTubeProps['onReady'] = event => { event.target.pauseVideo(); setIsLoading(false); }; - const opts: YouTubeProps["opts"] = { - height: "100", - width: "200", + const opts: YouTubeProps['opts'] = { + height: '100', + width: '200', playerVars: { autoplay: 0, controls: 1, @@ -20,23 +20,23 @@ export function TutorialVideo(): React.JSX.Element { }; return ( - - + + Watch explainer video: diff --git a/src/app/components/vault/components/vault-card-blank.tsx b/src/app/components/vault/components/vault-card-blank.tsx index 3a75d582..1007e8ee 100644 --- a/src/app/components/vault/components/vault-card-blank.tsx +++ b/src/app/components/vault/components/vault-card-blank.tsx @@ -1,17 +1,17 @@ -import { Text, VStack } from "@chakra-ui/react"; +import { Text, VStack } from '@chakra-ui/react'; export function VaultCardBlank(): React.JSX.Element { return ( - + Connect Your Ethereum Wallet diff --git a/src/app/components/vault/components/vault-card.layout.tsx b/src/app/components/vault/components/vault-card.layout.tsx index c1672d2f..1afdc698 100644 --- a/src/app/components/vault/components/vault-card.layout.tsx +++ b/src/app/components/vault/components/vault-card.layout.tsx @@ -1,6 +1,6 @@ -import { ReactNode } from "react"; +import { ReactNode } from 'react'; -import { VStack } from "@chakra-ui/react"; +import { VStack } from '@chakra-ui/react'; interface VaultCardLayoutProps { children: ReactNode; @@ -15,17 +15,17 @@ export function VaultCardLayout({ }: VaultCardLayoutProps): React.JSX.Element { return ( {}} > {children} diff --git a/src/app/components/vault/components/vault-expand-button.tsx b/src/app/components/vault/components/vault-expand-button.tsx index 7b12e68c..9b6fa91f 100644 --- a/src/app/components/vault/components/vault-expand-button.tsx +++ b/src/app/components/vault/components/vault-expand-button.tsx @@ -1,5 +1,5 @@ -import { ChevronDownIcon, ChevronUpIcon } from "@chakra-ui/icons"; -import { Button, Text } from "@chakra-ui/react"; +import { ChevronDownIcon, ChevronUpIcon } from '@chakra-ui/icons'; +import { Button, Text } from '@chakra-ui/react'; interface VaultExpandButtonProps { isExpanded: boolean; @@ -11,14 +11,14 @@ export function VaultExpandButton({ handleClick, }: VaultExpandButtonProps): React.JSX.Element { return ( - ); diff --git a/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-row.tsx b/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-row.tsx index d9f85b8c..9936d68f 100644 --- a/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-row.tsx +++ b/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-row.tsx @@ -1,4 +1,4 @@ -import { HStack, Text } from "@chakra-ui/react"; +import { HStack, Text } from '@chakra-ui/react'; interface VaultExpandedInformationRowProps { label: string; @@ -10,11 +10,11 @@ export function VaultExpandedInformationRow({ value, }: VaultExpandedInformationRowProps): React.JSX.Element { return ( - - + + {label} - + {value} diff --git a/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-transaction-row.tsx b/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-transaction-row.tsx index 29099b0a..8292f9ed 100644 --- a/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-transaction-row.tsx +++ b/src/app/components/vault/components/vault-expanded-information/components/vault-expanded-information-transaction-row.tsx @@ -1,5 +1,5 @@ -import { HStack, Text } from "@chakra-ui/react"; -import { useEndpoints } from "@hooks/use-endpoints"; +import { HStack, Text } from '@chakra-ui/react'; +import { useEndpoints } from '@hooks/use-endpoints'; interface VaultExpandedInformationTransactionRowProps { label: string; @@ -13,20 +13,18 @@ export function VaultExpandedInformationTransactionRow({ const { bitcoinExplorerAPIURL } = useEndpoints(); return ( - - + + {label} - window.open(`${bitcoinExplorerAPIURL}${value}`, "_blank") - } - _hover={{ cursor: "pointer" }} + textAlign={'right'} + w={'75%'} + color={'accent.cyan.01'} + fontSize={'xs'} + textDecoration={'underline'} + onClick={() => window.open(`${bitcoinExplorerAPIURL}${value}`, '_blank')} + _hover={{ cursor: 'pointer' }} > View in TX explorer diff --git a/src/app/components/vault/components/vault-expanded-information/vault-expanded-information.tsx b/src/app/components/vault/components/vault-expanded-information/vault-expanded-information.tsx index 579936ca..7f65b0b6 100644 --- a/src/app/components/vault/components/vault-expanded-information/vault-expanded-information.tsx +++ b/src/app/components/vault/components/vault-expanded-information/vault-expanded-information.tsx @@ -1,8 +1,8 @@ -import { Divider, ScaleFade, Stack, VStack } from "@chakra-ui/react"; -import { easyTruncateAddress } from "@common/utilities"; +import { Divider, ScaleFade, Stack, VStack } from '@chakra-ui/react'; +import { easyTruncateAddress } from '@common/utilities'; -import { VaultExpandedInformationRow } from "./components/vault-expanded-information-row"; -import { VaultExpandedInformationTransactionRow } from "./components/vault-expanded-information-transaction-row"; +import { VaultExpandedInformationRow } from './components/vault-expanded-information-row'; +import { VaultExpandedInformationTransactionRow } from './components/vault-expanded-information-transaction-row'; interface VaultExpandedInformationProps { uuid: string; @@ -18,26 +18,17 @@ export function VaultExpandedInformation({ isExpanded, }: VaultExpandedInformationProps): React.JSX.Element { return ( - + - - - + + + {Boolean(fundingTX) && ( - + )} {Boolean(closingTX) && ( - + )} diff --git a/src/app/components/vault/components/vault-information.tsx b/src/app/components/vault/components/vault-information.tsx index 0ec93577..77add8cc 100644 --- a/src/app/components/vault/components/vault-information.tsx +++ b/src/app/components/vault/components/vault-information.tsx @@ -1,82 +1,76 @@ -import { CheckIcon } from "@chakra-ui/icons"; -import { Button, HStack, Image, Text, VStack } from "@chakra-ui/react"; -import { VaultState } from "@models/vault"; +import { useDispatch } from 'react-redux'; -import { VaultExpandButton } from "./vault-expand-button"; +import { CheckIcon } from '@chakra-ui/icons'; +import { Button, HStack, Image, Text, VStack } from '@chakra-ui/react'; +import { VaultState } from '@models/vault'; +import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions'; + +import { VaultExpandButton } from './vault-expand-button'; const getAssetLogo = (state: VaultState) => { - return [VaultState.FUNDED, VaultState.CLOSING, VaultState.CLOSED].includes( - state, - ) - ? "/images/logos/dlc-btc-logo.svg" - : "/images/logos/bitcoin-logo.svg"; + return [VaultState.FUNDED, VaultState.CLOSING, VaultState.CLOSED].includes(state) + ? '/images/logos/dlc-btc-logo.svg' + : '/images/logos/bitcoin-logo.svg'; }; interface VaultInformationProps { + uuid: string; collateral: number; state: VaultState; timestamp: number; isExpanded: boolean; isSelectable?: boolean; isSelected?: boolean; - isSubmitting: boolean; handleClick: () => void; - handleLock: () => void; } export function VaultInformation({ + uuid, state, collateral, timestamp, isExpanded, isSelectable, isSelected, - isSubmitting, handleClick, - handleLock, }: VaultInformationProps): React.JSX.Element { - const date = new Date(timestamp * 1000).toLocaleDateString("en-US"); + const dispatch = useDispatch(); + const date = new Date(timestamp * 1000).toLocaleDateString('en-US'); return ( - - - - {"Icon"} - + + + + {'Icon'} + {collateral} - + {date} {isSelectable ? ( - {isSelected && ( - - )} + {isSelected && } - ) : state === VaultState.READY ? ( + ) : state === VaultState.READY && !isSelected ? ( ) : ( - handleClick()} - /> + handleClick()} /> )} ); diff --git a/src/app/components/vault/components/vault-progress-bar.tsx b/src/app/components/vault/components/vault-progress-bar.tsx index 36c1465e..b04bb113 100644 --- a/src/app/components/vault/components/vault-progress-bar.tsx +++ b/src/app/components/vault/components/vault-progress-bar.tsx @@ -1,5 +1,5 @@ -import { Box, Progress, Text, VStack } from "@chakra-ui/react"; -import { VaultState } from "@models/vault"; +import { Box, Progress, Text, VStack } from '@chakra-ui/react'; +import { VaultState } from '@models/vault'; interface VaultProgressBarProps { confirmedBlocks: number; @@ -10,19 +10,18 @@ export function VaultProgressBar({ confirmedBlocks, vaultState, }: VaultProgressBarProps): React.JSX.Element | boolean { - const shouldBeIndeterminate = - confirmedBlocks > 6 || Number.isNaN(confirmedBlocks); + const shouldBeIndeterminate = confirmedBlocks > 6 || Number.isNaN(confirmedBlocks); if (vaultState === VaultState.CLOSED && confirmedBlocks > 6) return false; return ( - + - - {shouldBeIndeterminate - ? "PROCESSING" - : `WAITING FOR CONFIRMATIONS: ${confirmedBlocks}/6`} + + {shouldBeIndeterminate ? 'PROCESSING' : `WAITING FOR CONFIRMATIONS: ${confirmedBlocks}/6`} diff --git a/src/app/components/vault/vault-card.tsx b/src/app/components/vault/vault-card.tsx index bb9e528d..fbf56e0f 100644 --- a/src/app/components/vault/vault-card.tsx +++ b/src/app/components/vault/vault-card.tsx @@ -1,16 +1,13 @@ -import React, { useContext, useState } from "react"; +import React, { useState } from 'react'; -import { CustomSkeleton } from "@components/custom-skeleton/custom-skeleton"; -import { useConfirmationChecker } from "@hooks/use-confirmation-checker"; -import { Vault, VaultState } from "@models/vault"; +import { CustomSkeleton } from '@components/custom-skeleton/custom-skeleton'; +import { useConfirmationChecker } from '@hooks/use-confirmation-checker'; +import { Vault, VaultState } from '@models/vault'; -import { BlockchainContext } from "../../providers/blockchain-context-provider"; -import { VaultCardLayout } from "./components/vault-card.layout"; -import { VaultExpandedInformation } from "./components/vault-expanded-information/vault-expanded-information"; -import { VaultInformation } from "./components/vault-information"; -import { VaultProgressBar } from "./components/vault-progress-bar"; -import { useToast } from "@chakra-ui/react"; -import { BitcoinError } from "@models/error-types"; +import { VaultCardLayout } from './components/vault-card.layout'; +import { VaultExpandedInformation } from './components/vault-expanded-information/vault-expanded-information'; +import { VaultInformation } from './components/vault-information'; +import { VaultProgressBar } from './components/vault-progress-bar'; interface VaultCardProps { vault?: Vault; @@ -25,52 +22,26 @@ export function VaultCard({ isSelectable = false, handleSelect, }: VaultCardProps): React.JSX.Element { - const toast = useToast(); - const blockchainContext = useContext(BlockchainContext); - const bitcoin = blockchainContext?.bitcoin; - - const [isSubmitting, setIsSubmitting] = useState(false); const [isExpanded, setIsExpanded] = useState(isSelected ? true : false); - async function handleLock(): Promise { - if (!vault) return; - setIsSubmitting(true); - try { - await bitcoin?.fetchBitcoinContractOfferAndSendToUserWallet(vault); - } catch (error) { - setIsSubmitting(false); - toast({ - title: "Failed to lock Bitcoin", - description: error instanceof BitcoinError ? error.message : "", - status: "error", - duration: 9000, - isClosable: true, - }); - } - } - const confirmations = useConfirmationChecker( vault?.state === VaultState.FUNDING ? vault?.fundingTX : vault?.closingTX, - vault?.state, + vault?.state ); - if (!vault) return ; + if (!vault) return ; return ( - handleSelect && handleSelect()} - > + handleSelect && handleSelect()}> setIsExpanded(!isExpanded)} - handleLock={handleLock} /> {isExpanded && ( )} {[VaultState.FUNDING, VaultState.CLOSED].includes(vault.state) && ( - + )} ); diff --git a/src/app/components/vaults-list/components/vaults-list-group-blank-container.tsx b/src/app/components/vaults-list/components/vaults-list-group-blank-container.tsx index 1db448f4..ee02dd57 100644 --- a/src/app/components/vaults-list/components/vaults-list-group-blank-container.tsx +++ b/src/app/components/vaults-list/components/vaults-list-group-blank-container.tsx @@ -1,10 +1,10 @@ -import { VStack } from "@chakra-ui/react"; -import { VaultCardBlank } from "@components/vault/components/vault-card-blank"; -import { blankArray } from "@models/blank-array"; +import { VStack } from '@chakra-ui/react'; +import { VaultCardBlank } from '@components/vault/components/vault-card-blank'; +import { blankArray } from '@models/blank-array'; export function VaultsListGroupBlankContainer(): React.JSX.Element { return ( - + {blankArray.map((_, index) => ( ))} diff --git a/src/app/components/vaults-list/components/vaults-list-group-container.tsx b/src/app/components/vaults-list/components/vaults-list-group-container.tsx index f645f6a3..fda50a16 100644 --- a/src/app/components/vaults-list/components/vaults-list-group-container.tsx +++ b/src/app/components/vaults-list/components/vaults-list-group-container.tsx @@ -1,6 +1,6 @@ -import { HStack, Spinner, Text, VStack } from "@chakra-ui/react"; -import { VaultCard } from "@components/vault/vault-card"; -import { Vault } from "@models/vault"; +import { HStack, Spinner, Text, VStack } from '@chakra-ui/react'; +import { VaultCard } from '@components/vault/vault-card'; +import { Vault } from '@models/vault'; interface VaultsListGroupContainerProps { label?: string; @@ -20,13 +20,13 @@ export function VaultsListGroupContainer({ if (vaults.length === 0) return false; return ( - + {label && ( - - {["Locking BTC in Progress", "Unlocking BTC in Progress"].includes( - label, - ) && } - {label} + + {['Locking BTC in Progress', 'Unlocking BTC in Progress'].includes(label) && ( + + )} + {label} )} {vaults.map((vault, index) => ( diff --git a/src/app/components/vaults-list/vaults-list.tsx b/src/app/components/vaults-list/vaults-list.tsx index 02f4924c..63a8a4c4 100644 --- a/src/app/components/vaults-list/vaults-list.tsx +++ b/src/app/components/vaults-list/vaults-list.tsx @@ -1,7 +1,7 @@ -import { Text, VStack } from "@chakra-ui/react"; -import { FadeLayer } from "@components/fade-layer/fade-layer"; +import { Text, VStack } from '@chakra-ui/react'; +import { FadeLayer } from '@components/fade-layer/fade-layer'; -import { scrollBarCSS } from "../../../styles/css-styles"; +import { scrollBarCSS } from '../../../styles/css-styles'; interface VaultsListProps { title?: string; @@ -17,19 +17,19 @@ export function VaultsList({ children, }: VaultsListProps): React.JSX.Element { return ( - + {title && ( - + {title} )} {children} diff --git a/src/app/hooks/use-bitcoin.ts b/src/app/hooks/use-bitcoin.ts index 150ed3c2..c9503cbc 100644 --- a/src/app/hooks/use-bitcoin.ts +++ b/src/app/hooks/use-bitcoin.ts @@ -1,13 +1,13 @@ -import { useDispatch, useSelector } from "react-redux"; +import { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; -import { BitcoinError } from "@models/error-types"; -import { Vault } from "@models/vault"; -import { mintUnmintActions } from "@store/slices/mintunmint/mintunmint.actions"; -import { vaultActions } from "@store/slices/vault/vault.actions"; +import { BitcoinError } from '@models/error-types'; +import { Vault } from '@models/vault'; +import { RootState } from '@store/index'; +import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions'; +import { vaultActions } from '@store/slices/vault/vault.actions'; -import { useEndpoints } from "./use-endpoints"; -import { RootState } from "@store/index"; -import { useEffect, useState } from "react"; +import { useEndpoints } from './use-endpoints'; export interface UseBitcoinReturnType { fetchBitcoinContractOfferAndSendToUserWallet: (vault: Vault) => Promise; @@ -29,18 +29,18 @@ export function useBitcoin(): UseBitcoinReturnType { function createURLParams(bitcoinContractOffer: any) { if (!routerWalletURL) { - throw new BitcoinError("Router wallet URL is undefined"); + throw new BitcoinError('Router wallet URL is undefined'); } const counterPartyWalletDetails = { counterpartyWalletURL: routerWalletURL, - counterpartyWalletName: "DLC.Link", + counterpartyWalletName: 'DLC.Link', counterpartyWalletIcon: - "https://dlc-public-assets.s3.amazonaws.com/DLC.Link_logo_icon_color.svg", + 'https://dlc-public-assets.s3.amazonaws.com/DLC.Link_logo_icon_color.svg', }; const urlParams = { bitcoinContractOffer: JSON.stringify(bitcoinContractOffer), - bitcoinNetwork: JSON.stringify("regtest"), + bitcoinNetwork: JSON.stringify('regtest'), counterpartyWalletDetails: JSON.stringify(counterPartyWalletDetails), }; return urlParams; @@ -48,31 +48,26 @@ export function useBitcoin(): UseBitcoinReturnType { async function sendOfferForSigning(urlParams: any, vaultUUID: string) { try { - const response = await window.btc.request( - "acceptBitcoinContractOffer", - urlParams, - ); + const response = await window.btc.request('acceptBitcoinContractOffer', urlParams); if (!network) return; dispatch( vaultActions.setVaultToFunding({ vaultUUID, fundingTX: response.result.txId, networkID: network.id, - }), + }) ); dispatch(mintUnmintActions.setMintStep([2, vaultUUID])); } catch (error: any) { - throw new BitcoinError( - `Could not send contract offer for signing: ${error.error.message}`, - ); + throw new BitcoinError(`Could not send contract offer for signing: ${error.error.message}`); } } async function fetchBitcoinContractOfferFromCounterpartyWallet(vault: Vault) { try { const response = await fetch(`${routerWalletURL}/offer`, { - method: "POST", - headers: { "Content-Type": "application/json" }, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uuid: vault.uuid, }), @@ -84,14 +79,13 @@ export function useBitcoin(): UseBitcoinReturnType { return responseStream; } catch (error: any) { throw new BitcoinError( - `Could not fetch contract offer from counterparty wallet: ${error.message}`, + `Could not fetch contract offer from counterparty wallet: ${error.message}` ); } } async function fetchBitcoinContractOfferAndSendToUserWallet(vault: Vault) { - const bitcoinContractOffer = - await fetchBitcoinContractOfferFromCounterpartyWallet(vault); + const bitcoinContractOffer = await fetchBitcoinContractOfferFromCounterpartyWallet(vault); if (!bitcoinContractOffer) return; const urlParams = createURLParams(bitcoinContractOffer); await sendOfferForSigning(urlParams, vault.uuid); @@ -99,12 +93,9 @@ export function useBitcoin(): UseBitcoinReturnType { async function fetchBitcoinPrice() { try { - const response = await fetch( - "https://api.coindesk.com/v1/bpi/currentprice.json", - { - headers: { Accept: "application/json" }, - }, - ); + const response = await fetch('https://api.coindesk.com/v1/bpi/currentprice.json', { + headers: { Accept: 'application/json' }, + }); const message = await response.json(); const bitcoinUSDPrice = message.bpi.USD.rate_float; setBitcoinPrice(bitcoinUSDPrice); diff --git a/src/app/hooks/use-confirmation-checker.ts b/src/app/hooks/use-confirmation-checker.ts index d0f88a9d..0f114bde 100644 --- a/src/app/hooks/use-confirmation-checker.ts +++ b/src/app/hooks/use-confirmation-checker.ts @@ -1,10 +1,10 @@ -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; -import { VaultState } from "@models/vault"; +import { VaultState } from '@models/vault'; export function useConfirmationChecker( txID: string | undefined, - vaultState: VaultState | undefined, + vaultState: VaultState | undefined ): number { const bitcoinExplorerTXURL = `https://devnet.dlc.link/electrs/tx/${txID}`; const bitcoinExplorerHeightURL = `https://devnet.dlc.link/electrs/blocks/tip/height`; @@ -12,17 +12,10 @@ export function useConfirmationChecker( const [transactionProgress, setTransactionProgress] = useState(0); - const memoizedTransactionProgress = useMemo( - () => transactionProgress, - [transactionProgress], - ); + const memoizedTransactionProgress = useMemo(() => transactionProgress, [transactionProgress]); const fetchTransactionDetails = async () => { - if ( - !txID || - (vaultState && - ![VaultState.FUNDING, VaultState.CLOSED].includes(vaultState)) - ) { + if (!txID || (vaultState && ![VaultState.FUNDING, VaultState.CLOSED].includes(vaultState))) { clearInterval(fetchInterval.current); return; } @@ -30,7 +23,7 @@ export function useConfirmationChecker( let bitcoinCurrentBlockHeight; try { const response = await fetch(bitcoinExplorerHeightURL, { - headers: { Accept: "application/json" }, + headers: { Accept: 'application/json' }, }); bitcoinCurrentBlockHeight = await response.json(); } catch (error) { @@ -41,17 +34,15 @@ export function useConfirmationChecker( try { const response = await fetch(bitcoinExplorerTXURL, { - headers: { Accept: "application/json" }, + headers: { Accept: 'application/json' }, }); const bitcoinTransactionDetails = await response.json(); - bitcoinTransactionBlockHeight = - bitcoinTransactionDetails.status.block_height; + bitcoinTransactionBlockHeight = bitcoinTransactionDetails.status.block_height; } catch (error) { console.error(error); } - const difference = - bitcoinCurrentBlockHeight - bitcoinTransactionBlockHeight; + const difference = bitcoinCurrentBlockHeight - bitcoinTransactionBlockHeight; setTransactionProgress(difference); @@ -63,10 +54,7 @@ export function useConfirmationChecker( fetchTransactionDetails(); useEffect(() => { - fetchInterval.current = setInterval( - fetchTransactionDetails, - 10000, - ) as unknown as number; // Cleanup the interval when the component unmounts + fetchInterval.current = setInterval(fetchTransactionDetails, 10000) as unknown as number; // Cleanup the interval when the component unmounts return () => clearInterval(fetchInterval.current); }, [vaultState, txID]); diff --git a/src/app/hooks/use-endpoints.ts b/src/app/hooks/use-endpoints.ts index 02fee5b9..54de45af 100644 --- a/src/app/hooks/use-endpoints.ts +++ b/src/app/hooks/use-endpoints.ts @@ -1,8 +1,8 @@ -import { useEffect, useState } from "react"; -import { useSelector } from "react-redux"; +import { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; -import { EthereumNetwork } from "@models/network"; -import { RootState } from "@store/index"; +import { EthereumNetwork } from '@models/network'; +import { RootState } from '@store/index'; interface UseEndpointsReturnType { routerWalletURL: string | undefined; @@ -13,20 +13,16 @@ interface UseEndpointsReturnType { export function useEndpoints(): UseEndpointsReturnType { const { network } = useSelector((state: RootState) => state.account); - const [routerWalletURL, setRouterWalletURL] = useState( - undefined, + const [routerWalletURL, setRouterWalletURL] = useState(undefined); + const [ethereumExplorerAPIURL, setEthereumExplorerAPIURL] = useState( + undefined ); - const [ethereumExplorerAPIURL, setEthereumExplorerAPIURL] = useState< - string | undefined - >(undefined); - const [bitcoinExplorerAPIURL, setBitcoinExplorerAPIURL] = - useState(""); + const [bitcoinExplorerAPIURL, setBitcoinExplorerAPIURL] = useState(''); useEffect(() => { if (!network) return; - const { routerWalletURL, ethereumExplorerAPIURL, bitcoinExplorerAPIURL } = - getEndpoints(); + const { routerWalletURL, ethereumExplorerAPIURL, bitcoinExplorerAPIURL } = getEndpoints(); setRouterWalletURL(routerWalletURL); setEthereumExplorerAPIURL(ethereumExplorerAPIURL); @@ -41,21 +37,21 @@ export function useEndpoints(): UseEndpointsReturnType { switch (network?.id) { case EthereumNetwork.Sepolia: return { - routerWalletURL: "https://devnet.dlc.link/eth-wallet", - ethereumExplorerAPIURL: "https://sepolia.etherscan.io/tx/", - bitcoinExplorerAPIURL: "http://devnet.dlc.link/electrs/tx/", + routerWalletURL: 'https://devnet.dlc.link/eth-wallet', + ethereumExplorerAPIURL: 'https://sepolia.etherscan.io/tx/', + bitcoinExplorerAPIURL: 'http://devnet.dlc.link/electrs/tx/', }; case EthereumNetwork.Goerli: return { - routerWalletURL: "https://testnet.dlc.link/eth-wallet", - ethereumExplorerAPIURL: "https://goerli.etherscan.io/tx/", - bitcoinExplorerAPIURL: "https://blockstream.info/testnet/tx/", + routerWalletURL: 'https://testnet.dlc.link/eth-wallet', + ethereumExplorerAPIURL: 'https://goerli.etherscan.io/tx/', + bitcoinExplorerAPIURL: 'https://blockstream.info/testnet/tx/', }; case EthereumNetwork.X1Testnet: return { - routerWalletURL: "https://devnet.dlc.link/okx-wallet", - ethereumExplorerAPIURL: "https://www.oklink.com/x1-test/tx/", - bitcoinExplorerAPIURL: "http://devnet.dlc.link/electrs/tx/", + routerWalletURL: 'https://devnet.dlc.link/okx-wallet', + ethereumExplorerAPIURL: 'https://www.oklink.com/x1-test/tx/', + bitcoinExplorerAPIURL: 'http://devnet.dlc.link/electrs/tx/', }; default: throw new Error(`Unsupported network: ${network?.name}`); diff --git a/src/app/hooks/use-ethereum.ts b/src/app/hooks/use-ethereum.ts index 502180c0..28740c5c 100644 --- a/src/app/hooks/use-ethereum.ts +++ b/src/app/hooks/use-ethereum.ts @@ -1,25 +1,25 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { useEffect, useState } from "react"; -import { useSelector } from "react-redux"; +import { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; -import { customShiftValue } from "@common/utilities"; -import { EthereumError } from "@models/error-types"; +import { customShiftValue } from '@common/utilities'; +import { EthereumError } from '@models/error-types'; import { EthereumNetwork, Network, addNetworkParams, ethereumNetworks, hexChainIDs, -} from "@models/network"; -import { RawVault, Vault, VaultState } from "@models/vault"; -import { RootState, store } from "@store/index"; -import { accountActions } from "@store/slices/account/account.actions"; -import { vaultActions } from "@store/slices/vault/vault.actions"; -import { Contract, Signer, ethers } from "ethers"; -import { Logger } from "ethers/lib/utils"; +} from '@models/network'; +import { RawVault, Vault, VaultState } from '@models/vault'; +import { WalletType } from '@models/wallet'; +import { RootState, store } from '@store/index'; +import { accountActions } from '@store/slices/account/account.actions'; +import { vaultActions } from '@store/slices/vault/vault.actions'; +import { Contract, Signer, ethers } from 'ethers'; +import { Logger } from 'ethers/lib/utils'; -import { WalletType } from "@models/wallet"; -import { useVaults } from "./use-vaults"; +import { useVaults } from './use-vaults'; export interface UseEthereumReturnType { protocolContract: Contract | undefined; @@ -28,10 +28,7 @@ export interface UseEthereumReturnType { getDLCBTCBalance: () => Promise; getLockedBTCBalance: () => Promise; totalSupply: number | undefined; - requestEthereumAccount: ( - network: Network, - walletType: WalletType, - ) => Promise; + requestEthereumAccount: (network: Network, walletType: WalletType) => Promise; getAllVaults: () => Promise; getVault: (vaultUUID: string, vaultState: VaultState) => Promise; setupVault: (btcDepositAmount: number) => Promise; @@ -43,9 +40,7 @@ export interface UseEthereumReturnType { function throwEthereumError(message: string, error: any): void { if (error.code === Logger.errors.CALL_EXCEPTION) { throw new EthereumError( - `${message}${ - error instanceof Error && "errorName" in error ? error.errorName : error - }`, + `${message}${error instanceof Error && 'errorName' in error ? error.errorName : error}` ); } else { throw new EthereumError(`${message}${error.code}`); @@ -62,15 +57,9 @@ export function useEthereum(): UseEthereumReturnType { const [isLoaded, setIsLoaded] = useState(false); - const [protocolContract, setProtocolContract] = useState< - Contract | undefined - >(undefined); - const [dlcManagerContract, setDlcManagerContract] = useState< - Contract | undefined - >(undefined); - const [dlcBTCContract, setDlcBTCContract] = useState( - undefined, - ); + const [protocolContract, setProtocolContract] = useState(undefined); + const [dlcManagerContract, setDlcManagerContract] = useState(undefined); + const [dlcBTCContract, setDlcBTCContract] = useState(undefined); const [totalSupply, setTotalSupply] = useState(undefined); @@ -106,10 +95,8 @@ export function useEthereum(): UseEthereumReturnType { } function getProvider(ethereum: any, walletType: WalletType): any { - if ("providers" in ethereum) { - return ethereum.providers.find( - (provider: any) => provider[`is${walletType}`], - ); + if ('providers' in ethereum) { + return ethereum.providers.find((provider: any) => provider[`is${walletType}`]); } return ethereum[`is${walletType}`] ? ethereum : undefined; } @@ -127,8 +114,8 @@ export function useEthereum(): UseEthereumReturnType { const { ethereum } = window; if (!ethereum) { - alert("Install MetaMask!"); - throw new EthereumError("No ethereum wallet found"); + alert('Install MetaMask!'); + throw new EthereumError('No ethereum wallet found'); } return checkWalletProvider(ethereum, walletType); @@ -136,7 +123,7 @@ export function useEthereum(): UseEthereumReturnType { async function getTotalSupply() { const provider = ethers.providers.getDefaultProvider( - "https://ethereum-sepolia.publicnode.com/", + 'https://ethereum-sepolia.publicnode.com/' ); const branchName = import.meta.env.VITE_ETHEREUM_DEPLOYMENT_BRANCH; const contractVersion = import.meta.env.VITE_ETHEREUM_DEPLOYMENT_VERSION; @@ -148,7 +135,7 @@ export function useEthereum(): UseEthereumReturnType { const protocolContract = new ethers.Contract( contractData.contract.address, contractData.contract.abi, - provider, + provider ); const totalSupply = await protocolContract.totalSupply(); setTotalSupply(customShiftValue(parseInt(totalSupply), 8, true)); @@ -159,13 +146,13 @@ export function useEthereum(): UseEthereumReturnType { async function addEthereumNetwork( newEthereumNetwork: EthereumNetwork, - walletType: WalletType, + walletType: WalletType ): Promise { const walletProvider = getWalletProvider(walletType); try { await walletProvider.request({ - method: "wallet_addEthereumChain", + method: 'wallet_addEthereumChain', params: addNetworkParams[newEthereumNetwork], }); } catch (error: any) { @@ -175,13 +162,13 @@ export function useEthereum(): UseEthereumReturnType { async function switchEthereumNetwork( newEthereumNetwork: EthereumNetwork, - walletType: WalletType, + walletType: WalletType ): Promise { const walletProvider = getWalletProvider(walletType); try { await walletProvider.request({ - method: "wallet_switchEthereumChain", + method: 'wallet_switchEthereumChain', params: [{ chainId: hexChainIDs[newEthereumNetwork] }], }); } catch (error: any) { @@ -195,17 +182,15 @@ export function useEthereum(): UseEthereumReturnType { async function setupEthereumConfiguration( network: Network, - walletType: WalletType, + walletType: WalletType ): Promise { const ethereumProvider = await getEthereumProvider(network, walletType); if (!ethereumProvider) { - throw new EthereumError("Failed to get Ethereum provider"); + throw new EthereumError('Failed to get Ethereum provider'); } const { walletNetworkChainID, signer } = ethereumProvider; if (!walletNetworkChainID || !signer) { - throw new EthereumError( - "Failed to get wallet network chain ID or signer", - ); + throw new EthereumError('Failed to get wallet network chain ID or signer'); } await getEthereumContracts(walletNetworkChainID, signer); } @@ -214,10 +199,7 @@ export function useEthereum(): UseEthereumReturnType { try { const walletProvider = getWalletProvider(walletType); - const browserProvider = new ethers.providers.Web3Provider( - walletProvider, - "any", - ); + const browserProvider = new ethers.providers.Web3Provider(walletProvider, 'any'); const signer = browserProvider.getSigner(); const walletNetwork = await browserProvider.getNetwork(); @@ -233,60 +215,45 @@ export function useEthereum(): UseEthereumReturnType { } } - async function getEthereumContracts( - chainName: string, - ethereumSigner: Signer, - ): Promise { + async function getEthereumContracts(chainName: string, ethereumSigner: Signer): Promise { if (!protocolContract) { - const protocolContractData = await fetchEthereumDeploymentPlan( - "TokenManager", - chainName, - ); + const protocolContractData = await fetchEthereumDeploymentPlan('TokenManager', chainName); const protocolContract = new ethers.Contract( protocolContractData.contract.address, protocolContractData.contract.abi, - ethereumSigner, + ethereumSigner ); setProtocolContract(protocolContract); } if (!dlcManagerContract) { - const dlcManagerContractData = await fetchEthereumDeploymentPlan( - "DLCManager", - chainName, - ); + const dlcManagerContractData = await fetchEthereumDeploymentPlan('DLCManager', chainName); const dlcManagerContract = new ethers.Contract( dlcManagerContractData.contract.address, dlcManagerContractData.contract.abi, - ethereumSigner, + ethereumSigner ); setDlcManagerContract(dlcManagerContract); } if (!dlcBTCContract) { - const dlcBTCContractData = await fetchEthereumDeploymentPlan( - "DLCBTC", - chainName, - ); + const dlcBTCContractData = await fetchEthereumDeploymentPlan('DLCBTC', chainName); const dlcBTCContract = new ethers.Contract( dlcBTCContractData.contract.address, dlcBTCContractData.contract.abi, - ethereumSigner, + ethereumSigner ); setDlcBTCContract(dlcBTCContract); } } - async function requestEthereumAccount( - network: Network, - walletType: WalletType, - ) { + async function requestEthereumAccount(network: Network, walletType: WalletType) { try { - if (!walletType) throw new Error("Wallet not initialized"); + if (!walletType) throw new Error('Wallet not initialized'); const walletProvider = getWalletProvider(walletType); const ethereumAccounts = await walletProvider.request({ - method: "eth_requestAccounts", + method: 'eth_requestAccounts', }); const accountInformation = { @@ -305,18 +272,15 @@ export function useEthereum(): UseEthereumReturnType { } } - async function fetchEthereumDeploymentPlan( - contractName: string, - chainID: string, - ) { - const network = ethereumNetworks.find((network) => network.id === chainID); + async function fetchEthereumDeploymentPlan(contractName: string, chainID: string) { + const network = ethereumNetworks.find(network => network.id === chainID); const branchName = import.meta.env.VITE_ETHEREUM_DEPLOYMENT_BRANCH; const contractVersion = import.meta.env.VITE_ETHEREUM_DEPLOYMENT_VERSION; const deploymentPlanURL = `https://raw.githubusercontent.com/DLC-link/dlc-solidity/${branchName}/deploymentFiles/${network?.name.toLowerCase()}/v${contractVersion}/${contractName}.json`; console.log( - `Fetching deployment info for ${contractName} on ${network?.name} from dlc-solidity/${branchName}`, + `Fetching deployment info for ${contractName} on ${network?.name} from dlc-solidity/${branchName}` ); try { @@ -325,7 +289,7 @@ export function useEthereum(): UseEthereumReturnType { return contractData; } catch (error) { throw new EthereumError( - `Could not fetch deployment info for ${contractName} on ${network?.name}`, + `Could not fetch deployment info for ${contractName} on ${network?.name}` ); } } @@ -334,7 +298,7 @@ export function useEthereum(): UseEthereumReturnType { try { const totalCollateral = fundedVaults.reduce( (sum: number, vault: Vault) => sum + vault.collateral, - 0, + 0 ); return Number(totalCollateral.toFixed(5)); } catch (error) { @@ -344,12 +308,12 @@ export function useEthereum(): UseEthereumReturnType { async function getDLCBTCBalance(): Promise { try { - if (!dlcBTCContract) throw new Error("Protocol contract not initialized"); + if (!dlcBTCContract) throw new Error('Protocol contract not initialized'); await dlcBTCContract.callStatic.balanceOf(address); const dlcBTCBalance = customShiftValue( parseInt(await dlcBTCContract.balanceOf(address)), 8, - true, + true ); return dlcBTCBalance; } catch (error) { @@ -359,18 +323,16 @@ export function useEthereum(): UseEthereumReturnType { async function getAllVaults(): Promise { try { - if (!protocolContract) - throw new Error("Protocol contract not initialized"); + if (!protocolContract) throw new Error('Protocol contract not initialized'); await protocolContract.callStatic.getAllVaultsForAddress(address); - const vaults: RawVault[] = - await protocolContract.getAllVaultsForAddress(address); + const vaults: RawVault[] = await protocolContract.getAllVaultsForAddress(address); const formattedVaults: Vault[] = vaults.map(formatVault); if (!network) return; store.dispatch( vaultActions.setVaults({ newVaults: formattedVaults, networkID: network?.id, - }), + }) ); } catch (error) { throwEthereumError(`Could not fetch vaults: `, error); @@ -381,16 +343,14 @@ export function useEthereum(): UseEthereumReturnType { vaultUUID: string, vaultState: VaultState, retryInterval = 5000, - maxRetries = 10, + maxRetries = 10 ): Promise { for (let i = 0; i < maxRetries; i++) { try { - if (!protocolContract) - throw new Error("Protocol contract not initialized"); + if (!protocolContract) throw new Error('Protocol contract not initialized'); const vault: RawVault = await protocolContract.getVault(vaultUUID); - if (!vault) throw new Error("Vault is undefined"); - if (vault.status !== vaultState) - throw new Error("Vault is not in the correct state"); + if (!vault) throw new Error('Vault is undefined'); + if (vault.status !== vaultState) throw new Error('Vault is not in the correct state'); const formattedVault: Vault = formatVault(vault); if (!network) return; store.dispatch( @@ -398,23 +358,20 @@ export function useEthereum(): UseEthereumReturnType { vaultUUID, updatedVault: formattedVault, networkID: network?.id, - }), + }) ); return; } catch (error) { console.log(`Error fetching vault ${vaultUUID}. Retrying...`); } - await new Promise((resolve) => setTimeout(resolve, retryInterval)); + await new Promise(resolve => setTimeout(resolve, retryInterval)); } - throw new EthereumError( - `Failed to fetch vault ${vaultUUID} after ${maxRetries} retries`, - ); + throw new EthereumError(`Failed to fetch vault ${vaultUUID} after ${maxRetries} retries`); } async function setupVault(btcDepositAmount: number): Promise { try { - if (!protocolContract) - throw new Error("Protocol contract not initialized"); + if (!protocolContract) throw new Error('Protocol contract not initialized'); await protocolContract.callStatic.setupVault(btcDepositAmount); await protocolContract.setupVault(btcDepositAmount); } catch (error: any) { @@ -424,8 +381,7 @@ export function useEthereum(): UseEthereumReturnType { async function closeVault(vaultUUID: string) { try { - if (!protocolContract) - throw new Error("Protocol contract not initialized"); + if (!protocolContract) throw new Error('Protocol contract not initialized'); await protocolContract.callStatic.closeVault(vaultUUID); await protocolContract.closeVault(vaultUUID); } catch (error) { @@ -435,29 +391,26 @@ export function useEthereum(): UseEthereumReturnType { async function recommendTokenToMetamask(): Promise { try { - if (!currentWalletType) throw new Error("Wallet not initialized"); + if (!currentWalletType) throw new Error('Wallet not initialized'); const walletProvider = getWalletProvider(currentWalletType); const response = await walletProvider.request({ - method: "wallet_watchAsset", + method: 'wallet_watchAsset', params: { - type: "ERC20", + type: 'ERC20', options: { address: dlcBTCContract?.address, - symbol: "dlcBTC", + symbol: 'dlcBTC', decimals: 8, image: - "https://cdn.discordapp.com/attachments/994505799902691348/1035507437748367360/DLC.Link_Emoji.png", + 'https://cdn.discordapp.com/attachments/994505799902691348/1035507437748367360/DLC.Link_Emoji.png', }, }, }); await response.wait(); return response; } catch (error) { - throwEthereumError( - `Could not recommend dlcBTC token to MetaMask: `, - error, - ); + throwEthereumError(`Could not recommend dlcBTC token to MetaMask: `, error); return false; } } diff --git a/src/app/hooks/use-observer.ts b/src/app/hooks/use-observer.ts index 5b00e3d8..0b3bb9d0 100644 --- a/src/app/hooks/use-observer.ts +++ b/src/app/hooks/use-observer.ts @@ -1,11 +1,12 @@ -import { useEffect } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; -import { VaultState } from "@models/vault"; -import { RootState } from "@store/index"; -import { mintUnmintActions } from "@store/slices/mintunmint/mintunmint.actions"; -import { modalActions } from "@store/slices/modal/modal.actions"; -import { UseEthereumReturnType } from "./use-ethereum"; +import { VaultState } from '@models/vault'; +import { RootState } from '@store/index'; +import { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions'; +import { modalActions } from '@store/slices/modal/modal.actions'; + +import { UseEthereumReturnType } from './use-ethereum'; export function useObserver(ethereum: UseEthereumReturnType): void { const dispatch = useDispatch(); @@ -19,7 +20,7 @@ export function useObserver(ethereum: UseEthereumReturnType): void { console.log(`Listening to [${protocolContract.address}]`); console.log(`Listening to [${dlcBTCContract.address}]`); - protocolContract.on("SetupVault", async (...args) => { + protocolContract.on('SetupVault', async (...args) => { const vaultOwner: string = args[2]; if (vaultOwner.toLowerCase() !== address) return; @@ -33,7 +34,7 @@ export function useObserver(ethereum: UseEthereumReturnType): void { }); }); - protocolContract.on("CloseVault", async (...args) => { + protocolContract.on('CloseVault', async (...args) => { const vaultOwner: string = args[2]; if (vaultOwner.toLowerCase() !== address) return; @@ -47,7 +48,7 @@ export function useObserver(ethereum: UseEthereumReturnType): void { }); }); - protocolContract.on("SetStatusFunded", async (...args) => { + protocolContract.on('SetStatusFunded', async (...args) => { const vaultOwner = args[2]; if (vaultOwner.toLowerCase() !== address) return; @@ -58,11 +59,16 @@ export function useObserver(ethereum: UseEthereumReturnType): void { await getVault(vaultUUID, VaultState.FUNDED).then(() => { dispatch(mintUnmintActions.setMintStep([0, vaultUUID])); - dispatch(modalActions.toggleSuccessfulFlowModalVisibility({ flow: "mint", vaultUUID})); + dispatch( + modalActions.toggleSuccessfulFlowModalVisibility({ + flow: 'mint', + vaultUUID, + }) + ); }); }); - protocolContract.on("PostCloseDLCHandler", async (...args) => { + protocolContract.on('PostCloseDLCHandler', async (...args) => { const vaultOwner = args[2]; if (vaultOwner.toLowerCase() !== address) return; @@ -73,7 +79,12 @@ export function useObserver(ethereum: UseEthereumReturnType): void { await getVault(vaultUUID, VaultState.CLOSED).then(() => { dispatch(mintUnmintActions.setUnmintStep([0, vaultUUID])); - dispatch(modalActions.toggleSuccessfulFlowModalVisibility({flow: "unmint", vaultUUID})); + dispatch( + modalActions.toggleSuccessfulFlowModalVisibility({ + flow: 'unmint', + vaultUUID, + }) + ); }); }); }, [protocolContract, dlcBTCContract, network]); diff --git a/src/app/hooks/use-vaults.ts b/src/app/hooks/use-vaults.ts index ef8db224..f6f5b046 100644 --- a/src/app/hooks/use-vaults.ts +++ b/src/app/hooks/use-vaults.ts @@ -35,14 +35,8 @@ export function useVaults(ethereum?: UseEthereumReturnType): UseVaultsReturnType fetchData(); }, [address, network, ethereum?.isLoaded]); - console.log('vaults', vaults); - console.log('network', network); - const allVaults = useMemo( - () => - vaults[network ? network.id : '1'] - .filter(vault => vault.state !== VaultState.READY) - .sort((a, b) => b.timestamp - a.timestamp), + () => [...vaults[network ? network.id : '1']].sort((a, b) => b.timestamp - a.timestamp), [vaults, network] ); diff --git a/src/app/pages/about/about.tsx b/src/app/pages/about/about.tsx index af326d74..53eb99b7 100644 --- a/src/app/pages/about/about.tsx +++ b/src/app/pages/about/about.tsx @@ -1,9 +1,9 @@ -import { Text, VStack } from "@chakra-ui/react"; +import { Text, VStack } from '@chakra-ui/react'; export function About(): React.JSX.Element { return ( - - About + + About ); } diff --git a/src/app/pages/components/page.layout.tsx b/src/app/pages/components/page.layout.tsx index ea3c6697..d7bde416 100644 --- a/src/app/pages/components/page.layout.tsx +++ b/src/app/pages/components/page.layout.tsx @@ -1,15 +1,9 @@ -import { HStack } from "@chakra-ui/react"; -import { HasChildren } from "@models/has-children"; +import { HStack } from '@chakra-ui/react'; +import { HasChildren } from '@models/has-children'; export function PageLayout({ children }: HasChildren): React.JSX.Element { return ( - + {children} ); diff --git a/src/app/pages/dashboard/dashboard.tsx b/src/app/pages/dashboard/dashboard.tsx index 67509e8b..27ae46fb 100644 --- a/src/app/pages/dashboard/dashboard.tsx +++ b/src/app/pages/dashboard/dashboard.tsx @@ -1,10 +1,10 @@ -import React from "react"; -import { useSelector } from "react-redux"; +import React from 'react'; +import { useSelector } from 'react-redux'; -import { MintUnmint } from "@components/mint-unmint/mint-unmint"; -import { MyVaultsSmall } from "@components/my-vaults-small/my-vaults-small"; -import { PageLayout } from "@pages/components/page.layout"; -import { RootState } from "@store/index"; +import { MintUnmint } from '@components/mint-unmint/mint-unmint'; +import { MyVaultsSmall } from '@components/my-vaults-small/my-vaults-small'; +import { PageLayout } from '@pages/components/page.layout'; +import { RootState } from '@store/index'; export function Dashboard(): React.JSX.Element { const { address } = useSelector((state: RootState) => state.account); diff --git a/src/app/pages/my-vaults/my-vaults.tsx b/src/app/pages/my-vaults/my-vaults.tsx index d7c68049..208f2d66 100644 --- a/src/app/pages/my-vaults/my-vaults.tsx +++ b/src/app/pages/my-vaults/my-vaults.tsx @@ -1,5 +1,5 @@ -import { MyVaultsLarge } from "@components/my-vaults/my-vaults-large"; -import { PageLayout } from "@pages/components/page.layout"; +import { MyVaultsLarge } from '@components/my-vaults/my-vaults-large'; +import { PageLayout } from '@pages/components/page.layout'; export function MyVaults(): React.JSX.Element { return ( diff --git a/src/app/providers/balance-context-provider.tsx b/src/app/providers/balance-context-provider.tsx index 95a8cd1b..8c2e87d0 100644 --- a/src/app/providers/balance-context-provider.tsx +++ b/src/app/providers/balance-context-provider.tsx @@ -1,11 +1,11 @@ -import { createContext, useContext, useEffect, useState } from "react"; -import { useSelector } from "react-redux"; +import { createContext, useContext, useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; -import { HasChildren } from "@models/has-children"; -import { RootState } from "@store/index"; +import { HasChildren } from '@models/has-children'; +import { RootState } from '@store/index'; -import { BlockchainContext } from "./blockchain-context-provider"; -import { VaultContext } from "./vault-context-provider"; +import { BlockchainContext } from './blockchain-context-provider'; +import { VaultContext } from './vault-context-provider'; interface VaultContextType { dlcBTCBalance: number | undefined; @@ -17,9 +17,7 @@ export const BalanceContext = createContext({ lockedBTCBalance: undefined, }); -export function BalanceContextProvider({ - children, -}: HasChildren): React.JSX.Element { +export function BalanceContextProvider({ children }: HasChildren): React.JSX.Element { const { address } = useSelector((state: RootState) => state.account); const blockchainContext = useContext(BlockchainContext); @@ -27,17 +25,16 @@ export function BalanceContextProvider({ const ethereum = blockchainContext?.ethereum; - const [dlcBTCBalance, setDLCBTCBalance] = useState( - undefined, - ); - const [lockedBTCBalance, setLockedBTCBalance] = useState( - undefined, - ); + const [dlcBTCBalance, setDLCBTCBalance] = useState(undefined); + const [lockedBTCBalance, setLockedBTCBalance] = useState(undefined); useEffect(() => { if (!ethereum || !address) return; - const { getDLCBTCBalance, getLockedBTCBalance } = ethereum; + const { getDLCBTCBalance, getLockedBTCBalance, isLoaded } = ethereum; + + if (!isLoaded) return; + const fetchData = async () => { const currentTokenBalance = await getDLCBTCBalance(); if (currentTokenBalance !== dlcBTCBalance) { @@ -49,7 +46,7 @@ export function BalanceContextProvider({ } }; fetchData(); - }, [address, vaults]); + }, [address, vaults, ethereum?.isLoaded]); return ( diff --git a/src/app/providers/blockchain-context-provider.tsx b/src/app/providers/blockchain-context-provider.tsx index 3cf42318..31ffc59d 100644 --- a/src/app/providers/blockchain-context-provider.tsx +++ b/src/app/providers/blockchain-context-provider.tsx @@ -1,21 +1,18 @@ -import React, { createContext } from "react"; +import React, { createContext } from 'react'; + +import { UseBitcoinReturnType, useBitcoin } from '@hooks/use-bitcoin'; +import { UseEthereumReturnType, useEthereum } from '@hooks/use-ethereum'; +import { useObserver } from '@hooks/use-observer'; +import { HasChildren } from '@models/has-children'; -import { UseBitcoinReturnType, useBitcoin } from "@hooks/use-bitcoin"; -import { UseEthereumReturnType, useEthereum } from "@hooks/use-ethereum"; -import { useObserver } from "@hooks/use-observer"; -import { HasChildren } from "@models/has-children"; interface BlockchainContextType { ethereum: UseEthereumReturnType; bitcoin: UseBitcoinReturnType; } -export const BlockchainContext = createContext( - null, -); +export const BlockchainContext = createContext(null); -export function BlockchainContextProvider({ - children, -}: HasChildren): React.JSX.Element { +export function BlockchainContextProvider({ children }: HasChildren): React.JSX.Element { const ethereum = useEthereum(); const bitcoin = useBitcoin(); diff --git a/src/app/providers/vault-context-provider.tsx b/src/app/providers/vault-context-provider.tsx index 6502fe94..f40b1261 100644 --- a/src/app/providers/vault-context-provider.tsx +++ b/src/app/providers/vault-context-provider.tsx @@ -1,9 +1,9 @@ -import { createContext, useContext } from "react"; +import { createContext, useContext } from 'react'; -import { UseVaultsReturnType, useVaults } from "@hooks/use-vaults"; -import { HasChildren } from "@models/has-children"; +import { UseVaultsReturnType, useVaults } from '@hooks/use-vaults'; +import { HasChildren } from '@models/has-children'; -import { BlockchainContext } from "./blockchain-context-provider"; +import { BlockchainContext } from './blockchain-context-provider'; interface VaultContextType { vaults: UseVaultsReturnType; @@ -21,13 +21,9 @@ export const VaultContext = createContext({ }, }); -export function VaultContextProvider({ - children, -}: HasChildren): React.JSX.Element { +export function VaultContextProvider({ children }: HasChildren): React.JSX.Element { const blockchainContext = useContext(BlockchainContext); const vaults = useVaults(blockchainContext?.ethereum); - return ( - {children} - ); + return {children}; } diff --git a/src/app/store/index.ts b/src/app/store/index.ts index 4efaeded..4b716bc0 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -1,10 +1,7 @@ -import { combineReducers, configureStore } from "@reduxjs/toolkit"; -import { - accountSlice, - initialAccountState, -} from "@store/slices/account/account.slice"; -import { modalSlice } from "@store/slices/modal/modal.slice"; -import { vaultSlice } from "@store/slices/vault/vault.slice"; +import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import { accountSlice, initialAccountState } from '@store/slices/account/account.slice'; +import { modalSlice } from '@store/slices/modal/modal.slice'; +import { vaultSlice } from '@store/slices/vault/vault.slice'; import { FLUSH, PAUSE, @@ -15,11 +12,11 @@ import { REHYDRATE, persistReducer, persistStore, -} from "redux-persist"; -import expireReducer from "redux-persist-expire"; -import storage from "redux-persist/lib/storage"; +} from 'redux-persist'; +import expireReducer from 'redux-persist-expire'; +import storage from 'redux-persist/lib/storage'; -import { mintUnmintSlice } from "./slices/mintunmint/mintunmint.slice"; +import { mintUnmintSlice } from './slices/mintunmint/mintunmint.slice'; export interface RootState { account: ReturnType; @@ -36,12 +33,12 @@ const rootReducer = combineReducers({ }); const persistConfig: PersistConfig = { - key: "root", + key: 'root', storage: storage, - whitelist: ["account", "vault"], + whitelist: ['account', 'vault'], transforms: [ - expireReducer("account", { - persistedAtKey: "loadedAt", + expireReducer('account', { + persistedAtKey: 'loadedAt', expireSeconds: 3600, expiredState: initialAccountState, }), @@ -52,7 +49,7 @@ const persistedReducer = persistReducer(persistConfig, rootReducer); export const store = configureStore({ reducer: persistedReducer, - middleware: (getDefaultMiddleware) => + middleware: getDefaultMiddleware => getDefaultMiddleware({ serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], diff --git a/src/app/store/slices/account/account.actions.ts b/src/app/store/slices/account/account.actions.ts index 808e4b37..acd68cc3 100644 --- a/src/app/store/slices/account/account.actions.ts +++ b/src/app/store/slices/account/account.actions.ts @@ -1,3 +1,3 @@ -import { accountSlice } from "@store/slices/account/account.slice"; +import { accountSlice } from '@store/slices/account/account.slice'; export const accountActions = accountSlice.actions; diff --git a/src/app/store/slices/account/account.slice.ts b/src/app/store/slices/account/account.slice.ts index c76f73fe..4505470d 100644 --- a/src/app/store/slices/account/account.slice.ts +++ b/src/app/store/slices/account/account.slice.ts @@ -1,6 +1,6 @@ -import { Network } from "@models/network"; -import { WalletType } from "@models/wallet"; -import { createSlice } from "@reduxjs/toolkit"; +import { Network } from '@models/network'; +import { WalletType } from '@models/wallet'; +import { createSlice } from '@reduxjs/toolkit'; interface AccountState { address: string | undefined; @@ -21,7 +21,7 @@ export const initialAccountState: AccountState = { }; export const accountSlice = createSlice({ - name: "account", + name: 'account', initialState: initialAccountState, reducers: { login: (state, action) => { @@ -30,7 +30,7 @@ export const accountSlice = createSlice({ state.network = action.payload.network; state.loadedAt = new Date().toJSON(); }, - logout: (state) => { + logout: state => { state.address = undefined; state.walletType = undefined; state.dlcBTCBalance = 0; diff --git a/src/app/store/slices/mintunmint/mintunmint.actions.ts b/src/app/store/slices/mintunmint/mintunmint.actions.ts index b716d2a9..b10d86ae 100644 --- a/src/app/store/slices/mintunmint/mintunmint.actions.ts +++ b/src/app/store/slices/mintunmint/mintunmint.actions.ts @@ -1,3 +1,3 @@ -import { mintUnmintSlice } from "./mintunmint.slice"; +import { mintUnmintSlice } from './mintunmint.slice'; export const mintUnmintActions = mintUnmintSlice.actions; diff --git a/src/app/store/slices/mintunmint/mintunmint.slice.ts b/src/app/store/slices/mintunmint/mintunmint.slice.ts index dbf1edee..df846a2f 100644 --- a/src/app/store/slices/mintunmint/mintunmint.slice.ts +++ b/src/app/store/slices/mintunmint/mintunmint.slice.ts @@ -1,28 +1,36 @@ -import { createSlice } from "@reduxjs/toolkit"; +import { createSlice } from '@reduxjs/toolkit'; interface MintUnmintState { - mintStep: [number, string] - unmintStep: [number, string] + mintStep: [number, string]; + unmintStep: [number, string]; + activeTab: 0 | 1; } const initialMintUnmintState: MintUnmintState = { mintStep: [0, ''], unmintStep: [0, ''], + activeTab: 0, }; export const mintUnmintSlice = createSlice({ - name: "mintunmint", + name: 'mintunmint', initialState: initialMintUnmintState, reducers: { setMintStep: (state, action) => { state.mintStep = action.payload; + state.activeTab = 0; }, setUnmintStep: (state, action) => { state.unmintStep = action.payload; + state.activeTab = 1; }, - resetMintUnmintState: (state) => { + setActiveTab: (state, action) => { + state.activeTab = action.payload; + }, + resetMintUnmintState: state => { state.mintStep = [0, '']; state.unmintStep = [0, '']; + state.activeTab = 0; }, }, }); diff --git a/src/app/store/slices/modal/modal.actions.ts b/src/app/store/slices/modal/modal.actions.ts index 5fd8b70d..590a1d11 100644 --- a/src/app/store/slices/modal/modal.actions.ts +++ b/src/app/store/slices/modal/modal.actions.ts @@ -1,3 +1,3 @@ -import { modalSlice } from "@store/slices/modal/modal.slice"; +import { modalSlice } from '@store/slices/modal/modal.slice'; export const modalActions = modalSlice.actions; diff --git a/src/app/store/slices/modal/modal.slice.ts b/src/app/store/slices/modal/modal.slice.ts index c2290e56..bebfebd7 100644 --- a/src/app/store/slices/modal/modal.slice.ts +++ b/src/app/store/slices/modal/modal.slice.ts @@ -1,29 +1,25 @@ -import { createSlice } from "@reduxjs/toolkit"; +import { createSlice } from '@reduxjs/toolkit'; interface ModalState { isSelectWalletModalOpen: boolean; - isSuccesfulFlowModalOpen: [boolean, "mint" | "unmint", string?]; + isSuccesfulFlowModalOpen: [boolean, 'mint' | 'unmint', string?]; } const initialModalState: ModalState = { isSelectWalletModalOpen: false, - isSuccesfulFlowModalOpen: [false, "mint"], + isSuccesfulFlowModalOpen: [false, 'mint'], }; export const modalSlice = createSlice({ - name: "modal", + name: 'modal', initialState: initialModalState, reducers: { - toggleSelectWalletModalVisibility: (state) => { + toggleSelectWalletModalVisibility: state => { state.isSelectWalletModalOpen = !state.isSelectWalletModalOpen; }, toggleSuccessfulFlowModalVisibility: (state, action) => { const { flow, vaultUUID } = action.payload; - state.isSuccesfulFlowModalOpen = [ - !state.isSuccesfulFlowModalOpen[0], - flow, - vaultUUID, - ]; + state.isSuccesfulFlowModalOpen = [!state.isSuccesfulFlowModalOpen[0], flow, vaultUUID]; }, }, }); diff --git a/src/app/store/slices/vault/vault.actions.ts b/src/app/store/slices/vault/vault.actions.ts index 869f42e7..d32454dc 100644 --- a/src/app/store/slices/vault/vault.actions.ts +++ b/src/app/store/slices/vault/vault.actions.ts @@ -1,3 +1,3 @@ -import { vaultSlice } from "@store/slices/vault/vault.slice"; +import { vaultSlice } from '@store/slices/vault/vault.slice'; export const vaultActions = vaultSlice.actions; diff --git a/src/app/store/slices/vault/vault.slice.ts b/src/app/store/slices/vault/vault.slice.ts index ad7ab206..db59cf7a 100644 --- a/src/app/store/slices/vault/vault.slice.ts +++ b/src/app/store/slices/vault/vault.slice.ts @@ -1,6 +1,6 @@ -import { EthereumNetwork } from "@models/network"; -import { Vault, VaultState } from "@models/vault"; -import { PayloadAction, createSlice } from "@reduxjs/toolkit"; +import { EthereumNetwork } from '@models/network'; +import { Vault, VaultState } from '@models/vault'; +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; interface VaultSliceState { vaults: { [key in EthereumNetwork]: Vault[] }; @@ -15,22 +15,20 @@ const initialVaultState: VaultSliceState = { [EthereumNetwork.Sepolia]: [], [EthereumNetwork.X1Testnet]: [], }, - status: "idle", + status: 'idle', error: null, }; export const vaultSlice = createSlice({ - name: "vault", + name: 'vault', initialState: initialVaultState, reducers: { setVaults: ( state, - action: PayloadAction<{ newVaults: Vault[]; networkID: EthereumNetwork }>, + action: PayloadAction<{ newVaults: Vault[]; networkID: EthereumNetwork }> ) => { const { newVaults, networkID } = action.payload; - const vaultMap = new Map( - state.vaults[networkID].map((vault) => [vault.uuid, vault]), - ); + const vaultMap = new Map(state.vaults[networkID].map(vault => [vault.uuid, vault])); state.vaults[networkID] = newVaults.map((newVault: Vault) => { const existingVault = vaultMap.get(newVault.uuid); @@ -39,11 +37,8 @@ export const vaultSlice = createSlice({ return newVault; } else { const shouldUpdate = - existingVault.state !== VaultState.FUNDING || - newVault.state === VaultState.FUNDED; - return shouldUpdate - ? { ...existingVault, ...newVault } - : existingVault; + existingVault.state !== VaultState.FUNDING || newVault.state === VaultState.FUNDED; + return shouldUpdate ? { ...existingVault, ...newVault } : existingVault; } }); }, @@ -53,12 +48,10 @@ export const vaultSlice = createSlice({ vaultUUID: string; updatedVault: Vault; networkID: EthereumNetwork; - }>, + }> ) => { const { vaultUUID, updatedVault, networkID } = action.payload; - const vaultIndex = state.vaults[networkID].findIndex( - (vault) => vault.uuid === vaultUUID, - ); + const vaultIndex = state.vaults[networkID].findIndex(vault => vault.uuid === vaultUUID); if (vaultIndex === -1) { state.vaults[networkID].push(updatedVault); @@ -72,13 +65,11 @@ export const vaultSlice = createSlice({ vaultUUID: string; fundingTX: string; networkID: EthereumNetwork; - }>, + }> ) => { const { vaultUUID, fundingTX, networkID } = action.payload; - const vaultIndex = state.vaults[networkID].findIndex( - (vault) => vault.uuid === vaultUUID, - ); + const vaultIndex = state.vaults[networkID].findIndex(vault => vault.uuid === vaultUUID); if (vaultIndex === -1) return; diff --git a/src/index.tsx b/src/index.tsx index 3acc8012..823ea303 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,17 +1,17 @@ -import ReactDOM from "react-dom/client"; -import { Provider as ReduxProvider } from "react-redux"; +import ReactDOM from 'react-dom/client'; +import { Provider as ReduxProvider } from 'react-redux'; -import { ChakraProvider } from "@chakra-ui/react"; -import "@fontsource/poppins"; -import "@fontsource/poppins/600.css"; -import "@fontsource/poppins/800.css"; -import { PersistGate } from "redux-persist/integration/react"; +import { ChakraProvider } from '@chakra-ui/react'; +import '@fontsource/poppins'; +import '@fontsource/poppins/600.css'; +import '@fontsource/poppins/800.css'; +import { PersistGate } from 'redux-persist/integration/react'; -import { App } from "./app/app"; -import { persistor, store } from "./app/store"; -import { appTheme } from "./styles/app-theme"; +import { App } from './app/app'; +import { persistor, store } from './app/store'; +import { appTheme } from './styles/app-theme'; -ReactDOM.createRoot(document.getElementById("root")!).render( +ReactDOM.createRoot(document.getElementById('root')!).render( - , + ); diff --git a/src/shared/models/error-types.ts b/src/shared/models/error-types.ts index 9254f4e7..437e013d 100644 --- a/src/shared/models/error-types.ts +++ b/src/shared/models/error-types.ts @@ -1,13 +1,13 @@ export class BitcoinError extends Error { constructor(message: string) { super(message); - this.name = "BitcoinError"; + this.name = 'BitcoinError'; } } export class EthereumError extends Error { constructor(message: string) { super(message); - this.name = "EthereumError"; + this.name = 'EthereumError'; } } diff --git a/src/shared/models/has-children.tsx b/src/shared/models/has-children.tsx index 035a5573..cbaf7c24 100644 --- a/src/shared/models/has-children.tsx +++ b/src/shared/models/has-children.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from "react"; +import { ReactNode } from 'react'; export interface HasChildren { children: ReactNode; diff --git a/src/shared/models/network.ts b/src/shared/models/network.ts index 84b9394f..dadcad12 100644 --- a/src/shared/models/network.ts +++ b/src/shared/models/network.ts @@ -4,29 +4,29 @@ export interface Network { } export enum EthereumNetwork { - Mainnet = "1", - Goerli = "5", - Sepolia = "11155111", - X1Testnet = "195", + Mainnet = '1', + Goerli = '5', + Sepolia = '11155111', + X1Testnet = '195', } const ethereumOKXTestnet: Network = { - name: "X1Test", + name: 'X1Test', id: EthereumNetwork.X1Testnet, }; const ethereumMainnet: Network = { - name: "Mainnet", + name: 'Mainnet', id: EthereumNetwork.Mainnet, }; const ethereumGoerli: Network = { - name: "Goerli", + name: 'Goerli', id: EthereumNetwork.Goerli, }; const ethereumSepolia: Network = { - name: "Sepolia", + name: 'Sepolia', id: EthereumNetwork.Sepolia, }; @@ -38,69 +38,63 @@ export const ethereumNetworks: Network[] = [ ]; export const hexChainIDs: { [key in EthereumNetwork]: string } = { - [EthereumNetwork.Mainnet]: "0x1", - [EthereumNetwork.Goerli]: "0x5", - [EthereumNetwork.Sepolia]: "0xAA36A7", - [EthereumNetwork.X1Testnet]: "0x3C", + [EthereumNetwork.Mainnet]: '0x1', + [EthereumNetwork.Goerli]: '0x5', + [EthereumNetwork.Sepolia]: '0xAA36A7', + [EthereumNetwork.X1Testnet]: '0x3C', }; export const addNetworkParams = { [EthereumNetwork.X1Testnet]: [ { - chainId: "0xC3", - rpcUrls: ["https://testrpc.x1.tech", "https://x1testrpc.okx.com/"], - chainName: "X1 testnet", + chainId: '0xC3', + rpcUrls: ['https://testrpc.x1.tech', 'https://x1testrpc.okx.com/'], + chainName: 'X1 testnet', nativeCurrency: { - name: "OKB", - symbol: "OKB", + name: 'OKB', + symbol: 'OKB', decimals: 18, }, - blockExplorerUrls: ["https://www.oklink.com/x1-test"], + blockExplorerUrls: ['https://www.oklink.com/x1-test'], }, ], [EthereumNetwork.Sepolia]: [ { - chainId: "11155111", - rpcUrls: [ - "https://ethereum-sepolia.publicnode.com/", - "https://sepolia.infura.io/v3/", - ], - chainName: "Sepolia Testnet", + chainId: '11155111', + rpcUrls: ['https://ethereum-sepolia.publicnode.com/', 'https://sepolia.infura.io/v3/'], + chainName: 'Sepolia Testnet', nativeCurrency: { - name: "SepoliaETH", - symbol: "SepoliaETH", + name: 'SepoliaETH', + symbol: 'SepoliaETH', decimals: 18, }, - blockExplorerUrls: ["https://sepolia.etherscan.io/"], + blockExplorerUrls: ['https://sepolia.etherscan.io/'], }, ], [EthereumNetwork.Goerli]: [ { - chainId: "5", - rpcUrls: [ - "https://ethereum-goerli.publicnode.com", - "https://goerli.infura.io/v3/", - ], - chainName: "Goerli Testnet", + chainId: '5', + rpcUrls: ['https://ethereum-goerli.publicnode.com', 'https://goerli.infura.io/v3/'], + chainName: 'Goerli Testnet', nativeCurrency: { - name: "GoerliETH", - symbol: "GoerliETH", + name: 'GoerliETH', + symbol: 'GoerliETH', decimals: 18, }, - blockExplorerUrls: ["https://goerli.etherscan.io/"], + blockExplorerUrls: ['https://goerli.etherscan.io/'], }, ], [EthereumNetwork.Mainnet]: [ { - chainId: "1", - rpcUrls: ["https://mainnet.infura.io/v3/"], - chainName: "Ethereum Mainnet", + chainId: '1', + rpcUrls: ['https://mainnet.infura.io/v3/'], + chainName: 'Ethereum Mainnet', nativeCurrency: { - name: "ETH", - symbol: "ETH", + name: 'ETH', + symbol: 'ETH', decimals: 18, }, - blockExplorerUrls: ["https://etherscan.io/"], + blockExplorerUrls: ['https://etherscan.io/'], }, ], }; diff --git a/src/shared/models/vault.tsx b/src/shared/models/vault.tsx index 2c245682..198659d8 100644 --- a/src/shared/models/vault.tsx +++ b/src/shared/models/vault.tsx @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber } from 'ethers'; export enum VaultState { READY = 0, diff --git a/src/shared/models/wallet.ts b/src/shared/models/wallet.ts index a7d2cb4f..d20102c8 100644 --- a/src/shared/models/wallet.ts +++ b/src/shared/models/wallet.ts @@ -1,6 +1,6 @@ export enum WalletType { - Metamask = "MetaMask", - Coinbase = "CoinbaseWallet", + Metamask = 'MetaMask', + Coinbase = 'CoinbaseWallet', } export interface Wallet { @@ -11,8 +11,8 @@ export interface Wallet { const metamask: Wallet = { id: WalletType.Metamask, - name: "Metamask", - logo: "/images/logos/metamask-logo.svg", + name: 'Metamask', + logo: '/images/logos/metamask-logo.svg', }; export const ethereumWallets: Wallet[] = [metamask]; diff --git a/src/styles/app-theme.ts b/src/styles/app-theme.ts index 490b576b..8460d95e 100644 --- a/src/styles/app-theme.ts +++ b/src/styles/app-theme.ts @@ -1,12 +1,12 @@ -import { extendTheme } from "@chakra-ui/react"; +import { extendTheme } from '@chakra-ui/react'; -import { buttonTheme } from "./button-theme"; -import { menuTheme } from "./menu-theme"; -import { modalTheme } from "./modal-theme"; -import { selectTheme } from "./select-theme"; -import { tabsTheme } from "./tabs-theme"; -import { textTheme } from "./text-theme"; -import { dividerTheme } from "./divider-theme"; +import { buttonTheme } from './button-theme'; +import { dividerTheme } from './divider-theme'; +import { menuTheme } from './menu-theme'; +import { modalTheme } from './modal-theme'; +import { selectTheme } from './select-theme'; +import { tabsTheme } from './tabs-theme'; +import { textTheme } from './text-theme'; export const appTheme = extendTheme({ components: { @@ -20,10 +20,10 @@ export const appTheme = extendTheme({ Progress: { baseStyle: { track: { - bg: "white.03", + bg: 'white.03', }, filledTrack: { - bg: "border.cyan.01", + bg: 'border.cyan.01', }, }, }, @@ -31,25 +31,24 @@ export const appTheme = extendTheme({ styles: { global: () => ({ body: { - bgGradient: - "linear(to-r, background.website.01, background.website.02)", + bgGradient: 'linear(to-r, background.website.01, background.website.02)', }, }), }, colors: { - "background.website.01": "rgba(50,3,69,1)", - "background.website.02": "rgba(0,9,51,1)", - "background.container.01": "rgba(40,7,78,1)", - "background.content.01": "rgba(31,9,78,0.25)", - "background.content.02": "rgba(4,13,72,0.25)", - "border.cyan.01": "rgba(7,232,216,0.75)", - "border.white.01": "rgba(255,255,255,0.25)", - "accent.cyan.01": "rgba(7,232,216,1)", - "accent.blue.01": "rgba(0,40,187,1)", - "accent.orange.01": "rgba(247,147,26,1)", - "white.01": "rgba(255,255,255,1)", - "white.02": "rgba(255,255,255,0.75)", - "white.03": "rgba(255,255,255,0.35)", + 'background.website.01': 'rgba(50,3,69,1)', + 'background.website.02': 'rgba(0,9,51,1)', + 'background.container.01': 'rgba(40,7,78,1)', + 'background.content.01': 'rgba(31,9,78,0.25)', + 'background.content.02': 'rgba(4,13,72,0.25)', + 'border.cyan.01': 'rgba(7,232,216,0.75)', + 'border.white.01': 'rgba(255,255,255,0.25)', + 'accent.cyan.01': 'rgba(7,232,216,1)', + 'accent.blue.01': 'rgba(0,40,187,1)', + 'accent.orange.01': 'rgba(247,147,26,1)', + 'white.01': 'rgba(255,255,255,1)', + 'white.02': 'rgba(255,255,255,0.75)', + 'white.03': 'rgba(255,255,255,0.35)', }, fonts: { body: "'Poppins', poppins", diff --git a/src/styles/button-theme.ts b/src/styles/button-theme.ts index 3ef7d0c9..a97d77b5 100644 --- a/src/styles/button-theme.ts +++ b/src/styles/button-theme.ts @@ -1,83 +1,82 @@ -import { defineStyle, defineStyleConfig } from "@chakra-ui/react"; +import { defineStyle, defineStyleConfig } from '@chakra-ui/react'; const basestyle = defineStyle({ - justifyContent: "center", - color: "white", + justifyContent: 'center', + color: 'white', }); const vault = defineStyle({ - py: "10px", - px: "25px", - h: "35px", - w: "100%", - fontSize: "sm", - fontWeight: "normal", - bg: "none", - border: "1px solid", - borderColor: "accent.cyan.01", + py: '10px', + px: '25px', + h: '35px', + w: '100%', + fontSize: 'sm', + fontWeight: 'normal', + bg: 'none', + border: '1px solid', + borderColor: 'accent.cyan.01', _hover: { - bg: "accent.cyan.01", + bg: 'accent.cyan.01', }, }); const navigate = defineStyle({ - py: "10px", - px: "25px", - h: "50px", - w: "100%", - fontSize: "sm", + py: '10px', + px: '25px', + h: '50px', + w: '100%', + fontSize: 'sm', fontWeight: 600, - bg: "none", - border: "1px solid", - borderColor: "accent.cyan.01", + bg: 'none', + border: '1px solid', + borderColor: 'accent.cyan.01', _hover: { - bg: "accent.cyan.01", + bg: 'accent.cyan.01', }, }); const account = defineStyle({ - py: "10px", - px: "50px", - h: "50px", - w: "100%", - fontSize: "lg", + py: '10px', + px: '50px', + h: '50px', + w: '100%', + fontSize: 'lg', fontWeight: 600, - bgSize: "400%", - bgPosition: "left", - bgGradient: - "linear(to-r, accent.cyan.01, accent.blue.01, accent.blue.01, accent.cyan.01)", - transition: "background-position 500ms ease, color 500ms ease", + bgSize: '400%', + bgPosition: 'left', + bgGradient: 'linear(to-r, accent.cyan.01, accent.blue.01, accent.blue.01, accent.cyan.01)', + transition: 'background-position 500ms ease, color 500ms ease', _hover: { - bgPosition: "right", + bgPosition: 'right', }, }); const tab = defineStyle({ - py: "25px", - px: "0px", - h: "50px", - w: "auto", - fontSize: "lg", + py: '25px', + px: '0px', + h: '50px', + w: 'auto', + fontSize: 'lg', fontWeight: 400, - bgColor: "none", - borderBottom: "3.5px solid", - borderRadius: "none", - borderColor: "accent.cyan.01", + bgColor: 'none', + borderBottom: '3.5px solid', + borderRadius: 'none', + borderColor: 'accent.cyan.01', }); const company = defineStyle({ - p: "0px", - h: "50px", - w: "auto", - bgColor: "none", + p: '0px', + h: '50px', + w: 'auto', + bgColor: 'none', }); const wallet = defineStyle({ - bgGradient: "linear(to-b, background.content.01, background.content.02)", - border: "0.5px solid", - borderColor: "border.white.01", + bgGradient: 'linear(to-b, background.content.01, background.content.02)', + border: '0.5px solid', + borderColor: 'border.white.01', _hover: { - bgColor: "white.03", + bgColor: 'white.03', }, }); diff --git a/src/styles/css-styles.ts b/src/styles/css-styles.ts index 52c63712..7b07d307 100644 --- a/src/styles/css-styles.ts +++ b/src/styles/css-styles.ts @@ -1,12 +1,12 @@ export const scrollBarCSS = { - "&::-webkit-scrollbar": { - background: "rgba(255,255,255,0.25)", - width: "3.5px", + '&::-webkit-scrollbar': { + background: 'rgba(255,255,255,0.25)', + width: '3.5px', }, - "&::-webkit-scrollbar-track": { - width: "2.5px", + '&::-webkit-scrollbar-track': { + width: '2.5px', }, - "&::-webkit-scrollbar-thumb": { - background: "rgba(7,232,216,1)", + '&::-webkit-scrollbar-thumb': { + background: 'rgba(7,232,216,1)', }, }; diff --git a/src/styles/divider-theme.ts b/src/styles/divider-theme.ts index ace702cb..ddf17c66 100644 --- a/src/styles/divider-theme.ts +++ b/src/styles/divider-theme.ts @@ -1,15 +1,15 @@ -import { defineStyle, defineStyleConfig } from "@chakra-ui/react"; +import { defineStyle, defineStyleConfig } from '@chakra-ui/react'; const thick = defineStyle({ - borderWidth: "3.5px", - borderStyle: "solid", - borderColor: "border.white.01", + borderWidth: '3.5px', + borderStyle: 'solid', + borderColor: 'border.white.01', }); const thickDotted = defineStyle({ - borderWidth: "3.5px", - borderStyle: "dotted", - borderColor: "border.white.01", + borderWidth: '3.5px', + borderStyle: 'dotted', + borderColor: 'border.white.01', }); export const dividerTheme = defineStyleConfig({ diff --git a/src/styles/icon.tsx b/src/styles/icon.tsx index 068e3b05..2b496097 100644 --- a/src/styles/icon.tsx +++ b/src/styles/icon.tsx @@ -1,6 +1,6 @@ -import React, { SVGProps } from "react"; +import React, { SVGProps } from 'react'; -export const StepIconOne: React.FC> = (props) => ( +export const StepIconOne: React.FC> = props => ( > = (props) => ( ); -export const StepIconTwo: React.FC> = (props) => ( +export const StepIconTwo: React.FC> = props => ( > = (props) => ( ); -export const StepIconThree: React.FC> = (props) => ( +export const StepIconThree: React.FC> = props => ( { - await page.goto("https://playwright.dev/"); +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); // Expect a title "to contain" a substring. await expect(page).toHaveTitle(/Playwright/); }); -test("get started link", async ({ page }) => { - await page.goto("https://playwright.dev/"); +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); // Click the get started link. - await page.getByRole("link", { name: "Get started" }).click(); + await page.getByRole('link', { name: 'Get started' }).click(); // Expects page to have a heading with the name of Installation. - await expect( - page.getByRole("heading", { name: "Installation" }), - ).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); }); diff --git a/tests/unit/utilities.unit.test.ts b/tests/unit/utilities.unit.test.ts index 228d22b8..1b63ccd8 100644 --- a/tests/unit/utilities.unit.test.ts +++ b/tests/unit/utilities.unit.test.ts @@ -1,9 +1,9 @@ -import { expect, test } from "vitest"; +import { expect, test } from 'vitest'; -import { easyTruncateAddress } from "../../src/app/common/utilities"; +import { easyTruncateAddress } from '../../src/app/common/utilities'; -test("address is truncated correctly", () => { - const address = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"; +test('address is truncated correctly', () => { + const address = 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq'; const truncated = easyTruncateAddress(address); - expect(truncated).toBe("bc1q...5mdq"); + expect(truncated).toBe('bc1q...5mdq'); });