From 9835abb0031360b8cea972e5b8fb5f0957a29af0 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Fri, 24 Nov 2023 15:03:05 +0100 Subject: [PATCH 1/2] feat: added confirmation-checker --- .../vault/components/vault-progress-bar.tsx | 20 ++++++++-- src/app/components/vault/vault-card.tsx | 7 ++-- src/app/hooks/use-confirmation-checker.ts | 39 +++++++++++++++++++ 3 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/app/hooks/use-confirmation-checker.ts diff --git a/src/app/components/vault/components/vault-progress-bar.tsx b/src/app/components/vault/components/vault-progress-bar.tsx index 5c730861..05c20de2 100644 --- a/src/app/components/vault/components/vault-progress-bar.tsx +++ b/src/app/components/vault/components/vault-progress-bar.tsx @@ -1,15 +1,27 @@ import { Box, Progress, Text, VStack } from "@chakra-ui/react"; +import { useEffect } from "react"; interface VaultProgressBarProps { - confirmedBlocks: number; + confirmedBlocks: number | boolean; } export function VaultProgressBar({ confirmedBlocks, -}: VaultProgressBarProps): React.JSX.Element { +}: VaultProgressBarProps): React.JSX.Element | boolean { + useEffect(() => { + console.log(confirmedBlocks); + }, [confirmedBlocks]); + + if (typeof confirmedBlocks === "boolean") return false; return ( - + - WAITING FOR CONFIRMATIONS: {confirmedBlocks}/6 + {`WAITING FOR CONFIRMATIONS: ${confirmedBlocks}/6`} diff --git a/src/app/components/vault/vault-card.tsx b/src/app/components/vault/vault-card.tsx index e2e3b7e2..e500bc4a 100644 --- a/src/app/components/vault/vault-card.tsx +++ b/src/app/components/vault/vault-card.tsx @@ -7,6 +7,7 @@ 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 { useConfirmationChecker } from "@hooks/use-confirmation-checker"; interface VaultBoxProps { vault?: Vault; @@ -21,7 +22,7 @@ export function VaultCard({ isSelectable = false, handleSelect, }: VaultBoxProps): React.JSX.Element { - const confirmedBlocks = 3; + const confirmations = useConfirmationChecker(vault?.fundingTX); const [isExpanded, setIsExpanded] = useState(isSelected ? true : false); if (!vault) return ; @@ -48,8 +49,8 @@ export function VaultCard({ isExpanded={isExpanded} /> )} - {[VaultState.FUNDING, VaultState.CLOSING].includes(vault.state) && ( - + {[VaultState.FUNDING, VaultState.CLOSED].includes(vault.state) && ( + )} ); diff --git a/src/app/hooks/use-confirmation-checker.ts b/src/app/hooks/use-confirmation-checker.ts new file mode 100644 index 00000000..db0a97b2 --- /dev/null +++ b/src/app/hooks/use-confirmation-checker.ts @@ -0,0 +1,39 @@ +import { useEffect, useState } from "react"; + +export function useConfirmationChecker( + txID: string | undefined, +): number | boolean { + const bitcoinExplorerTXURL = `http://stx-btc1.dlc.link:8001/tx/${txID}`; + const bitcoinExplorerHeightURL = `http://stx-btc1.dlc.link:8001//blocks/tip/height`; + + const [confirmations, setConfirmations] = useState(0); + + useEffect(() => { + if (!txID) return; + const interval = setInterval(async () => { + try { + const txResponse = await fetch(bitcoinExplorerTXURL); + const txData = await txResponse.json(); + + const heightResponse = await fetch(bitcoinExplorerHeightURL); + const heightData = await heightResponse.json(); + + const currentConfirmations = heightData - txData.status.block_height; + setConfirmations(currentConfirmations); + + if (currentConfirmations >= 6) { + clearInterval(interval); + setConfirmations(true); + } + } catch (error) { + console.error(error); + clearInterval(interval); + setConfirmations(false); + } + }, 15000); + + return () => clearInterval(interval); + }, [txID]); + + return confirmations; +} From 49595f1363eff3adf9382540efbb77daa73a90f3 Mon Sep 17 00:00:00 2001 From: Polybius93 Date: Fri, 24 Nov 2023 17:13:33 +0100 Subject: [PATCH 2/2] feat: added confirmation checker for funding and closed vaults --- .../vault/components/vault-progress-bar.tsx | 17 ++-- src/app/components/vault/vault-card.tsx | 13 ++- src/app/hooks/use-confirmation-checker.ts | 99 +++++++++++++------ 3 files changed, 87 insertions(+), 42 deletions(-) diff --git a/src/app/components/vault/components/vault-progress-bar.tsx b/src/app/components/vault/components/vault-progress-bar.tsx index 05c20de2..a3375457 100644 --- a/src/app/components/vault/components/vault-progress-bar.tsx +++ b/src/app/components/vault/components/vault-progress-bar.tsx @@ -1,21 +1,22 @@ import { Box, Progress, Text, VStack } from "@chakra-ui/react"; -import { useEffect } from "react"; +import { VaultState } from "@models/vault"; interface VaultProgressBarProps { - confirmedBlocks: number | boolean; + confirmedBlocks: number; + vaultState: VaultState; } export function VaultProgressBar({ confirmedBlocks, + vaultState, }: VaultProgressBarProps): React.JSX.Element | boolean { - useEffect(() => { - console.log(confirmedBlocks); - }, [confirmedBlocks]); + const shouldBeIndeterminate = confirmedBlocks > 6; - if (typeof confirmedBlocks === "boolean") return false; + if (vaultState === VaultState.CLOSED && confirmedBlocks > 6) return false; return ( - {`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 e500bc4a..7334447f 100644 --- a/src/app/components/vault/vault-card.tsx +++ b/src/app/components/vault/vault-card.tsx @@ -1,13 +1,13 @@ 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 { 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 { useConfirmationChecker } from "@hooks/use-confirmation-checker"; interface VaultBoxProps { vault?: Vault; @@ -22,7 +22,11 @@ export function VaultCard({ isSelectable = false, handleSelect, }: VaultBoxProps): React.JSX.Element { - const confirmations = useConfirmationChecker(vault?.fundingTX); + const confirmations = useConfirmationChecker( + vault?.state === VaultState.FUNDING ? vault?.fundingTX : vault?.closingTX, + vault?.state, + ); + const [isExpanded, setIsExpanded] = useState(isSelected ? true : false); if (!vault) return ; @@ -50,7 +54,10 @@ export function VaultCard({ /> )} {[VaultState.FUNDING, VaultState.CLOSED].includes(vault.state) && ( - + )} ); diff --git a/src/app/hooks/use-confirmation-checker.ts b/src/app/hooks/use-confirmation-checker.ts index db0a97b2..b1d78417 100644 --- a/src/app/hooks/use-confirmation-checker.ts +++ b/src/app/hooks/use-confirmation-checker.ts @@ -1,39 +1,74 @@ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; + +import { VaultState } from "@models/vault"; export function useConfirmationChecker( txID: string | undefined, -): number | boolean { - const bitcoinExplorerTXURL = `http://stx-btc1.dlc.link:8001/tx/${txID}`; - const bitcoinExplorerHeightURL = `http://stx-btc1.dlc.link:8001//blocks/tip/height`; + vaultState: VaultState | undefined, +): number { + const bitcoinExplorerTXURL = `https://devnet.dlc.link/electrs/tx/${txID}`; + const bitcoinExplorerHeightURL = `https://devnet.dlc.link/electrs/blocks/tip/height`; + const fetchInterval = useRef(undefined); + + const [transactionProgress, setTransactionProgress] = useState(0); + + const memoizedTransactionProgress = useMemo( + () => transactionProgress, + [transactionProgress], + ); + + const fetchTransactionDetails = async () => { + if ( + !txID || + (vaultState && + ![VaultState.FUNDING, VaultState.CLOSED].includes(vaultState)) + ) { + clearInterval(fetchInterval.current); + return; + } + + let bitcoinCurrentBlockHeight; + try { + const response = await fetch(bitcoinExplorerHeightURL, { + headers: { Accept: "application/json" }, + }); + bitcoinCurrentBlockHeight = await response.json(); + } catch (error) { + console.error(error); + } + + let bitcoinTransactionBlockHeight; - const [confirmations, setConfirmations] = useState(0); + try { + const response = await fetch(bitcoinExplorerTXURL, { + headers: { Accept: "application/json" }, + }); + const bitcoinTransactionDetails = await response.json(); + bitcoinTransactionBlockHeight = + bitcoinTransactionDetails.status.block_height; + } catch (error) { + console.error(error); + } + + const difference = + bitcoinCurrentBlockHeight - bitcoinTransactionBlockHeight; + + setTransactionProgress(difference); + + if (difference > 6) { + clearInterval(fetchInterval.current); + } + }; + + fetchTransactionDetails(); useEffect(() => { - if (!txID) return; - const interval = setInterval(async () => { - try { - const txResponse = await fetch(bitcoinExplorerTXURL); - const txData = await txResponse.json(); - - const heightResponse = await fetch(bitcoinExplorerHeightURL); - const heightData = await heightResponse.json(); - - const currentConfirmations = heightData - txData.status.block_height; - setConfirmations(currentConfirmations); - - if (currentConfirmations >= 6) { - clearInterval(interval); - setConfirmations(true); - } - } catch (error) { - console.error(error); - clearInterval(interval); - setConfirmations(false); - } - }, 15000); - - return () => clearInterval(interval); - }, [txID]); - - return confirmations; + fetchInterval.current = setInterval( + fetchTransactionDetails, + 10000, + ) as unknown as number; // Cleanup the interval when the component unmounts + return () => clearInterval(fetchInterval.current); + }, []); + + return memoizedTransactionProgress; }