Skip to content

Commit

Permalink
feat: added error handling to blockchain interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Polybius93 committed Nov 28, 2023
1 parent f02696b commit 7ce92b2
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 249 deletions.
95 changes: 0 additions & 95 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"prettier": "^3.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-query": "^3.39.3",
"react-redux": "^8.1.3",
"react-youtube": "^10.1.0",
"redux": "^4.2.1",
Expand Down
5 changes: 0 additions & 5 deletions src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { QueryClient, QueryClientProvider } from "react-query";
import { Route } from "react-router-dom";

import { AppLayout } from "@components/app.layout";
Expand All @@ -9,11 +8,8 @@ import { About } from "./pages/about/about";
import { Dashboard } from "./pages/dashboard/dashboard";
import { BlockchainContextProvider } from "./providers/blockchain-context-provider";

const queryClient = new QueryClient();

export function App(): React.JSX.Element {
return (
<QueryClientProvider client={queryClient}>
<BlockchainContextProvider>
<AppLayout>
<Route path="/" element={<Dashboard />} />
Expand All @@ -22,6 +18,5 @@ export function App(): React.JSX.Element {
</AppLayout>
<ModalContainer />
</BlockchainContextProvider>
</QueryClientProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {
FormErrorMessage,
Text,
VStack,
useToast,
} from "@chakra-ui/react";
import { customShiftValue } from "@common/utilities";
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";

export interface TransactionFormValues {
amount: number;
Expand All @@ -21,6 +23,7 @@ export interface TransactionFormValues {
const initialValues: TransactionFormValues = { amount: 0.001 };

export function TransactionForm(): React.JSX.Element {
const toast = useToast();
const blockchainContext = useContext(BlockchainContext);
const ethereum = blockchainContext?.ethereum;
const [isSubmitting, setIsSubmitting] = useState(false);
Expand All @@ -36,7 +39,13 @@ export function TransactionForm(): React.JSX.Element {
await ethereum?.setupVault(shiftedBTCDepositAmount);
} catch (error) {
setIsSubmitting(false);
throw new Error("Error setting up vault");
toast({
title: "Failed to create vault",
description: error instanceof EthereumError ? error.message : "",
status: "error",
duration: 9000,
isClosable: true,
});
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/app/components/vault/vault-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ 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";

interface VaultCardProps {
vault: Vault;
Expand All @@ -23,6 +25,7 @@ export function VaultCard({
isSelectable = false,
handleSelect,
}: VaultCardProps): React.JSX.Element {
const toast = useToast();
const blockchainContext = useContext(BlockchainContext);
const bitcoin = blockchainContext?.bitcoin;

Expand All @@ -36,7 +39,13 @@ export function VaultCard({
await bitcoin?.fetchBitcoinContractOfferAndSendToUserWallet(vault);
} catch (error) {
setIsSubmitting(false);
throw new Error("Error locking vault");
toast({
title: "Failed to lock Bitcoin",
description: error instanceof BitcoinError ? error.message : "",
status: "error",
duration: 9000,
isClosable: true,
});
}
}

Expand Down
46 changes: 21 additions & 25 deletions src/app/hooks/use-bitcoin.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// import { Dispatch } from 'react';
import { useDispatch } from "react-redux";
import { useDispatch } from 'react-redux';

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 { mintUnmintActions } from '@store/slices/mintunmint/mintunmint.actions';
import { vaultActions } from '@store/slices/vault/vault.actions';

import { useEndpoints } from "./use-endpoints";
import { useEndpoints } from './use-endpoints';

export interface UseBitcoinReturnType {
fetchBitcoinContractOfferAndSendToUserWallet: (vault: Vault) => Promise<void>;
Expand All @@ -17,65 +17,61 @@ export function useBitcoin(): UseBitcoinReturnType {

function createURLParams(bitcoinContractOffer: any) {
if (!routerWalletURL) {
throw new Error("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;
}

async function sendOfferForSigning(urlParams: any, vaultUUID: string) {
try {
const response = await window.btc.request(
"acceptBitcoinContractOffer",
urlParams,
);
const response = await window.btc.request('acceptBitcoinContractOffer', urlParams);
dispatch(
vaultActions.setVaultToFunding({
vaultUUID,
fundingTX: response.result.txId,
}),
})
);
dispatch(mintUnmintActions.setMintStep(2));
} catch (error) {
throw new Error(`Could not send contract offer for signing: ${error}`);
} catch (error: any) {
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,
}),
});
const responseStream = await response.json();
if (!response.ok) {
throw new Error(responseStream.error);
throw new BitcoinError(responseStream.error.message);
}
return responseStream;
} catch (error) {
throw new Error(
`Could not fetch contract offer from counterparty wallet: ${error}`,
} catch (error: any) {
throw new BitcoinError(
`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);
Expand Down
Loading

0 comments on commit 7ce92b2

Please sign in to comment.