From 153b00d60a50476de30e7adcd569c4bd6a1021f4 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 21 Feb 2024 08:40:52 +0100 Subject: [PATCH 01/12] Create a separate directory for sentry - create a directory for hooks - remove SDK parent directory for sentry --- dapp/src/DApp.tsx | 3 ++- dapp/src/hooks/index.ts | 1 - dapp/src/hooks/sentry/index.ts | 1 + dapp/src/hooks/{ => sentry}/useSentry.ts | 2 +- dapp/src/{sdk => }/sentry/index.ts | 0 5 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 dapp/src/hooks/sentry/index.ts rename dapp/src/hooks/{ => sentry}/useSentry.ts (83%) rename dapp/src/{sdk => }/sentry/index.ts (100%) diff --git a/dapp/src/DApp.tsx b/dapp/src/DApp.tsx index d9b2fdc9f..bece62291 100644 --- a/dapp/src/DApp.tsx +++ b/dapp/src/DApp.tsx @@ -1,7 +1,7 @@ import React from "react" import { Box, ChakraProvider } from "@chakra-ui/react" import { RouterProvider } from "react-router-dom" -import { useSentry, useInitializeAcreSdk } from "./hooks" +import { useInitializeAcreSdk } from "./hooks" import theme from "./theme" import { DocsDrawerContextProvider, @@ -15,6 +15,7 @@ import Sidebar from "./components/Sidebar" import DocsDrawer from "./components/DocsDrawer" import GlobalStyles from "./components/GlobalStyles" import { router } from "./router" +import { useSentry } from "./hooks/sentry" function DApp() { // TODO: Let's uncomment when dark mode is ready diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 16a760198..8d9574ab2 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -10,6 +10,5 @@ export * from "./useTransactionDetails" export * from "./useDepositBTCTransaction" export * from "./useInitializeAcreSdk" export * from "./useTransactionHistoryTable" -export * from "./useSentry" export * from "./useExecuteFunction" export * from "./useStakeFlowContext" diff --git a/dapp/src/hooks/sentry/index.ts b/dapp/src/hooks/sentry/index.ts new file mode 100644 index 000000000..20f65be38 --- /dev/null +++ b/dapp/src/hooks/sentry/index.ts @@ -0,0 +1 @@ +export * from "./useSentry" diff --git a/dapp/src/hooks/useSentry.ts b/dapp/src/hooks/sentry/useSentry.ts similarity index 83% rename from dapp/src/hooks/useSentry.ts rename to dapp/src/hooks/sentry/useSentry.ts index 3fb100e35..31214cd28 100644 --- a/dapp/src/hooks/useSentry.ts +++ b/dapp/src/hooks/sentry/useSentry.ts @@ -1,4 +1,4 @@ -import { initializeSentry } from "#/sdk/sentry" +import { initializeSentry } from "#/sentry" import { useEffect } from "react" export const useSentry = () => { diff --git a/dapp/src/sdk/sentry/index.ts b/dapp/src/sentry/index.ts similarity index 100% rename from dapp/src/sdk/sentry/index.ts rename to dapp/src/sentry/index.ts From 35ff5ddfe590a7b3e1e7f83cb0e671cba93333dd Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 21 Feb 2024 08:48:53 +0100 Subject: [PATCH 02/12] Add a special hook to capture Message for Sentry SDKs don't automatically capture messages, but we can capture them manually. --- dapp/package.json | 1 + dapp/src/hooks/sentry/index.ts | 1 + dapp/src/hooks/sentry/useCaptureMessage.ts | 16 ++++++++++++++++ dapp/src/sentry/index.ts | 19 +++++++++++++++++++ pnpm-lock.yaml | 8 ++++++++ 5 files changed, 45 insertions(+) create mode 100644 dapp/src/hooks/sentry/useCaptureMessage.ts diff --git a/dapp/package.json b/dapp/package.json index 7e4ceb3b6..6c0e51957 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -22,6 +22,7 @@ "@ledgerhq/wallet-api-client": "^1.5.0", "@ledgerhq/wallet-api-client-react": "^1.3.0", "@sentry/react": "^7.98.0", + "@sentry/types": "^7.102.0", "@tanstack/react-table": "^8.11.3", "ethers": "^6.10.0", "formik": "^2.4.5", diff --git a/dapp/src/hooks/sentry/index.ts b/dapp/src/hooks/sentry/index.ts index 20f65be38..137677560 100644 --- a/dapp/src/hooks/sentry/index.ts +++ b/dapp/src/hooks/sentry/index.ts @@ -1 +1,2 @@ export * from "./useSentry" +export * from "./useCaptureMessage" diff --git a/dapp/src/hooks/sentry/useCaptureMessage.ts b/dapp/src/hooks/sentry/useCaptureMessage.ts new file mode 100644 index 000000000..0a7855954 --- /dev/null +++ b/dapp/src/hooks/sentry/useCaptureMessage.ts @@ -0,0 +1,16 @@ +import { useCallback } from "react" +import { Primitive } from "@sentry/types" +import { captureMessage } from "#/sentry" + +export const useCaptureMessage = () => + useCallback( + ( + message: string, + params?: { [key: string]: unknown }, + tags?: { [key: string]: Primitive }, + ) => { + if (!import.meta.env.VITE_SENTRY_SUPPORT) return + captureMessage(message, params, tags) + }, + [], + ) diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry/index.ts index 8a6fd63fe..5b1990431 100644 --- a/dapp/src/sentry/index.ts +++ b/dapp/src/sentry/index.ts @@ -1,4 +1,5 @@ import * as Sentry from "@sentry/react" +import { Primitive } from "@sentry/types" export const initializeSentry = (dsn: string) => { Sentry.init({ @@ -9,3 +10,21 @@ export const initializeSentry = (dsn: string) => { tracesSampleRate: 1.0, }) } + +export const captureMessage = ( + message: string, + params?: { [key: string]: unknown }, + tags?: { [key: string]: Primitive }, +) => { + Sentry.withScope((scope) => { + if (params) { + scope.setExtras(params) + } + + if (tags) { + scope.setTags(tags) + } + + Sentry.captureMessage(message) + }) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a1bd1fd1..e272db7a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,6 +141,9 @@ importers: '@sentry/react': specifier: ^7.98.0 version: 7.98.0(react@18.2.0) + '@sentry/types': + specifier: ^7.102.0 + version: 7.102.0 '@tanstack/react-table': specifier: ^8.11.3 version: 8.11.7(react-dom@18.2.0)(react@18.2.0) @@ -6165,6 +6168,11 @@ packages: engines: {node: '>=6'} dev: true + /@sentry/types@7.102.0: + resolution: {integrity: sha512-FPfFBP0x3LkPARw1/6cWySLq1djIo8ao3Qo2KNBeE9CHdq8bsS1a8zzjJLuWG4Ww+wieLP8/lY3WTgrCz4jowg==} + engines: {node: '>=8'} + dev: false + /@sentry/types@7.98.0: resolution: {integrity: sha512-pc034ziM0VTETue4bfBcBqTWGy4w0okidtoZJjGVrYAfE95ObZnUGVj/XYIQ3FeCYWIa7NFN2MvdsCS0buwivQ==} engines: {node: '>=8'} From b00b00ee076f0f12a9cb4edbb7ffa96f2246d003 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 21 Feb 2024 09:03:57 +0100 Subject: [PATCH 03/12] Define `BITCOIN_NETWORK` compatible with type from tbtc-v2 --- dapp/src/constants/chains.ts | 7 ++++++- sdk/src/lib/bitcoin/index.ts | 1 + sdk/src/lib/bitcoin/network.ts | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 sdk/src/lib/bitcoin/network.ts diff --git a/dapp/src/constants/chains.ts b/dapp/src/constants/chains.ts index fc9396426..150d7575f 100644 --- a/dapp/src/constants/chains.ts +++ b/dapp/src/constants/chains.ts @@ -1,5 +1,5 @@ import { Chain } from "#/types" -import { EthereumNetwork } from "@acre-btc/sdk" +import { EthereumNetwork, BitcoinNetwork } from "@acre-btc/sdk" export const BLOCK_EXPLORER: Record = { ethereum: { title: "Etherscan", url: "https://etherscan.io" }, @@ -8,3 +8,8 @@ export const BLOCK_EXPLORER: Record = { export const ETHEREUM_NETWORK: EthereumNetwork = import.meta.env.VITE_USE_TESTNET === "true" ? "sepolia" : "mainnet" + +export const BITCOIN_NETWORK: BitcoinNetwork = + import.meta.env.VITE_USE_TESTNET === "true" + ? BitcoinNetwork.Testnet + : BitcoinNetwork.Mainnet diff --git a/sdk/src/lib/bitcoin/index.ts b/sdk/src/lib/bitcoin/index.ts index 2e48b1561..2652d91ad 100644 --- a/sdk/src/lib/bitcoin/index.ts +++ b/sdk/src/lib/bitcoin/index.ts @@ -1 +1,2 @@ export * from "./transaction" +export * from "./network" diff --git a/sdk/src/lib/bitcoin/network.ts b/sdk/src/lib/bitcoin/network.ts new file mode 100644 index 000000000..bfd491bbb --- /dev/null +++ b/sdk/src/lib/bitcoin/network.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { BitcoinNetwork } from "@keep-network/tbtc-v2.ts" From c910b45ea5b41aa68b4780a5230c6257643f56d4 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 21 Feb 2024 09:57:29 +0100 Subject: [PATCH 04/12] Integrate second track deposit verification with Sentry telemetry --- dapp/package.json | 1 + dapp/src/acre-react/hooks/useStakeFlow.ts | 14 +++++- .../ActiveStakingStep/DepositBTCModal.tsx | 15 +++++-- dapp/src/hooks/index.ts | 1 + dapp/src/hooks/useDepositTelemetry.ts | 44 +++++++++++++++++++ dapp/src/utils/address.ts | 40 +++++++++++++++++ pnpm-lock.yaml | 24 +++++++++- 7 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 dapp/src/hooks/useDepositTelemetry.ts diff --git a/dapp/package.json b/dapp/package.json index 6c0e51957..d2b90f5cc 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -24,6 +24,7 @@ "@sentry/react": "^7.98.0", "@sentry/types": "^7.102.0", "@tanstack/react-table": "^8.11.3", + "axios": "^1.6.7", "ethers": "^6.10.0", "formik": "^2.4.5", "framer-motion": "^10.16.5", diff --git a/dapp/src/acre-react/hooks/useStakeFlow.ts b/dapp/src/acre-react/hooks/useStakeFlow.ts index 5041d0734..b7aaf9079 100644 --- a/dapp/src/acre-react/hooks/useStakeFlow.ts +++ b/dapp/src/acre-react/hooks/useStakeFlow.ts @@ -1,5 +1,9 @@ import { useCallback, useState } from "react" -import { StakeInitialization, EthereumAddress } from "@acre-btc/sdk" +import { + StakeInitialization, + EthereumAddress, + DepositReceipt, +} from "@acre-btc/sdk" import { useAcreContext } from "./useAcreContext" export type UseStakeFlowReturn = { @@ -9,6 +13,7 @@ export type UseStakeFlowReturn = { referral: number, ) => Promise btcAddress?: string + depositReceipt?: DepositReceipt signMessage: () => Promise stake: () => Promise } @@ -20,6 +25,9 @@ export function useStakeFlow(): UseStakeFlowReturn { undefined, ) const [btcAddress, setBtcAddress] = useState(undefined) + const [depositReceipt, setDepositReceipt] = useState< + DepositReceipt | undefined + >(undefined) const initStake = useCallback( async ( @@ -36,10 +44,13 @@ export function useStakeFlow(): UseStakeFlowReturn { ) const btcDepositAddress = await initializedStakeFlow.getBitcoinAddress() + const btcDepositReceipt = initializedStakeFlow.getDepositReceipt() + // TODO: add loading indicators or we can `@tanstack/react-query` lib for // handling requests. setStakeFlow(initializedStakeFlow) setBtcAddress(btcDepositAddress) + setDepositReceipt(btcDepositReceipt) }, [isInitialized, acre], ) @@ -59,6 +70,7 @@ export function useStakeFlow(): UseStakeFlowReturn { return { initStake, btcAddress, + depositReceipt, signMessage, stake, } diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx index 8273aff92..0fbd91d95 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx @@ -1,6 +1,7 @@ import React, { useCallback } from "react" import { useDepositBTCTransaction, + useDepositTelemetry, useExecuteFunction, useModalFlowContext, useStakeFlowContext, @@ -15,7 +16,8 @@ import StakingStepsModalContent from "./StakingStepsModalContent" export default function DepositBTCModal() { const { tokenAmount } = useTransactionContext() const { setStatus } = useModalFlowContext() - const { btcAddress, stake } = useStakeFlowContext() + const { btcAddress, depositReceipt, stake } = useStakeFlowContext() + const depositTelemetry = useDepositTelemetry() const onStakeBTCSuccess = useCallback(() => { setStatus(PROCESS_STATUSES.SUCCEEDED) @@ -46,10 +48,17 @@ export default function DepositBTCModal() { useDepositBTCTransaction(onDepositBTCSuccess) const handledDepositBTC = useCallback(() => { - if (!tokenAmount?.amount || !btcAddress) return + if (!tokenAmount?.amount || !btcAddress || !depositReceipt) return + asyncWrapper(depositTelemetry(depositReceipt, btcAddress)) asyncWrapper(sendBitcoinTransaction(tokenAmount?.amount, btcAddress)) - }, [btcAddress, sendBitcoinTransaction, tokenAmount]) + }, [ + btcAddress, + depositReceipt, + depositTelemetry, + sendBitcoinTransaction, + tokenAmount?.amount, + ]) return ( { + const { status, response } = await verifyDepositAddress( + deposit, + depositAddress, + BITCOIN_NETWORK, + ) + + const { + depositor, + blindingFactor, + walletPublicKeyHash, + refundPublicKeyHash, + refundLocktime, + } = deposit + + captureMessage( + `Generated deposit [${depositAddress}]`, + { + depositor: depositor.identifierHex, + blindingFactor: blindingFactor.toString(), + walletPublicKeyHash: walletPublicKeyHash.toString(), + refundPublicKeyHash: refundPublicKeyHash.toString(), + refundLocktime: refundLocktime.toString(), + verificationStatus: status, + verificationResponse: response, + }, + { + "verification.status": status, + }, + ) + }, + [captureMessage], + ) +} diff --git a/dapp/src/utils/address.ts b/dapp/src/utils/address.ts index 7ed3caa1a..73a49dc1f 100644 --- a/dapp/src/utils/address.ts +++ b/dapp/src/utils/address.ts @@ -1,3 +1,43 @@ +import { BitcoinNetwork, DepositReceipt } from "@acre-btc/sdk" +import axios from "axios" + export function truncateAddress(address: string): string { return `${address.slice(0, 6)}…${address.slice(-5)}` } + +export async function verifyDepositAddress( + deposit: DepositReceipt, + depositAddress: string, + network: BitcoinNetwork, +): Promise<{ + status: "valid" | "invalid" | "error" + response: unknown +}> { + // TODO: Use a correct endpoint + const endpoint = + "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" + + const { depositor, blindingFactor, refundPublicKeyHash, refundLocktime } = + deposit + + try { + const response = await axios.get<{ address: string }>( + `${endpoint}/json/${network}/latest/${ + depositor.identifierHex + }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}`, + { timeout: 10000 }, // 10s + ) + + const match = response.data.address === depositAddress + + return { + status: match ? "valid" : "invalid", + response: response.data, + } + } catch (err) { + return { + status: "error", + response: err, + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e272db7a6..18b37e315 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,6 +147,9 @@ importers: '@tanstack/react-table': specifier: ^8.11.3 version: 8.11.7(react-dom@18.2.0)(react@18.2.0) + axios: + specifier: ^1.6.7 + version: 1.6.7 ethers: specifier: ^6.10.0 version: 6.10.0 @@ -7790,6 +7793,16 @@ packages: - debug dev: true + /axios@1.6.7: + resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} + dependencies: + follow-redirects: 1.15.5 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} dependencies: @@ -11569,6 +11582,16 @@ packages: dependencies: debug: 4.3.4(supports-color@8.1.1) + /follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /follow-redirects@1.5.10: resolution: {integrity: sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==} engines: {node: '>=4.0'} @@ -16358,7 +16381,6 @@ packages: /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true /pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} From 36f9549e4452d5546b7a4d564e7de8fd5df233a1 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 21 Feb 2024 14:38:25 +0100 Subject: [PATCH 05/12] Move `verifyDepositAddress` to external file --- dapp/src/utils/address.ts | 40 ----------------------------------- dapp/src/utils/externalApi.ts | 39 ++++++++++++++++++++++++++++++++++ dapp/src/utils/index.ts | 1 + 3 files changed, 40 insertions(+), 40 deletions(-) create mode 100644 dapp/src/utils/externalApi.ts diff --git a/dapp/src/utils/address.ts b/dapp/src/utils/address.ts index 73a49dc1f..7ed3caa1a 100644 --- a/dapp/src/utils/address.ts +++ b/dapp/src/utils/address.ts @@ -1,43 +1,3 @@ -import { BitcoinNetwork, DepositReceipt } from "@acre-btc/sdk" -import axios from "axios" - export function truncateAddress(address: string): string { return `${address.slice(0, 6)}…${address.slice(-5)}` } - -export async function verifyDepositAddress( - deposit: DepositReceipt, - depositAddress: string, - network: BitcoinNetwork, -): Promise<{ - status: "valid" | "invalid" | "error" - response: unknown -}> { - // TODO: Use a correct endpoint - const endpoint = - "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" - - const { depositor, blindingFactor, refundPublicKeyHash, refundLocktime } = - deposit - - try { - const response = await axios.get<{ address: string }>( - `${endpoint}/json/${network}/latest/${ - depositor.identifierHex - }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}`, - { timeout: 10000 }, // 10s - ) - - const match = response.data.address === depositAddress - - return { - status: match ? "valid" : "invalid", - response: response.data, - } - } catch (err) { - return { - status: "error", - response: err, - } - } -} diff --git a/dapp/src/utils/externalApi.ts b/dapp/src/utils/externalApi.ts new file mode 100644 index 000000000..99f0b04c4 --- /dev/null +++ b/dapp/src/utils/externalApi.ts @@ -0,0 +1,39 @@ +import { BitcoinNetwork, DepositReceipt } from "@acre-btc/sdk" +import axios from "axios" + +export async function verifyDepositAddress( + deposit: DepositReceipt, + depositAddress: string, + network: BitcoinNetwork, +): Promise<{ + status: "valid" | "invalid" | "error" + response: unknown +}> { + // TODO: Use a correct endpoint + const endpoint = + "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" + + const { depositor, blindingFactor, refundPublicKeyHash, refundLocktime } = + deposit + + try { + const response = await axios.get<{ address: string }>( + `${endpoint}/json/${network}/latest/${ + depositor.identifierHex + }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}`, + { timeout: 10000 }, // 10s + ) + + const match = response.data.address === depositAddress + + return { + status: match ? "valid" : "invalid", + response: response.data, + } + } catch (err) { + return { + status: "error", + response: err, + } + } +} diff --git a/dapp/src/utils/index.ts b/dapp/src/utils/index.ts index 40f6c0899..30a1624a9 100644 --- a/dapp/src/utils/index.ts +++ b/dapp/src/utils/index.ts @@ -6,3 +6,4 @@ export * from "./chain" export * from "./text" export * from "./time" export * from "./async" +export * from "./externalApi" From 2bfb6a96ff59e6ff30012346aeed85c4a6600e8a Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Thu, 22 Feb 2024 10:16:10 +0100 Subject: [PATCH 06/12] Support sentry only when flag is set to true VITE_SENTRY_SUPPORT was a boolean but returned a string when parsed. We have to make sure to convert it to the desired type when using it in our code. --- dapp/src/hooks/sentry/useCaptureMessage.ts | 4 +++- dapp/src/hooks/sentry/useSentry.ts | 2 +- dapp/src/vite-env.d.ts | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dapp/src/hooks/sentry/useCaptureMessage.ts b/dapp/src/hooks/sentry/useCaptureMessage.ts index 0a7855954..bba1553bd 100644 --- a/dapp/src/hooks/sentry/useCaptureMessage.ts +++ b/dapp/src/hooks/sentry/useCaptureMessage.ts @@ -9,7 +9,9 @@ export const useCaptureMessage = () => params?: { [key: string]: unknown }, tags?: { [key: string]: Primitive }, ) => { - if (!import.meta.env.VITE_SENTRY_SUPPORT) return + const { VITE_SENTRY_SUPPORT } = import.meta.env + + if (VITE_SENTRY_SUPPORT === "false") return captureMessage(message, params, tags) }, [], diff --git a/dapp/src/hooks/sentry/useSentry.ts b/dapp/src/hooks/sentry/useSentry.ts index 31214cd28..763020cee 100644 --- a/dapp/src/hooks/sentry/useSentry.ts +++ b/dapp/src/hooks/sentry/useSentry.ts @@ -5,7 +5,7 @@ export const useSentry = () => { useEffect(() => { const { VITE_SENTRY_SUPPORT, VITE_SENTRY_DSN } = import.meta.env - if (VITE_SENTRY_SUPPORT) { + if (VITE_SENTRY_SUPPORT === "true") { initializeSentry(VITE_SENTRY_DSN) } }, []) diff --git a/dapp/src/vite-env.d.ts b/dapp/src/vite-env.d.ts index 7a6ae7bcb..9b9d912c1 100644 --- a/dapp/src/vite-env.d.ts +++ b/dapp/src/vite-env.d.ts @@ -1,7 +1,6 @@ /// interface ImportMetaEnv { - readonly VITE_SENTRY_SUPPORT: boolean readonly VITE_SENTRY_DSN: string readonly VITE_ETH_HOSTNAME_HTTP: string readonly VITE_REFERRAL: number From 3135d9995bfe148baee6343ac3bb60d07035fac2 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Thu, 22 Feb 2024 14:46:11 +0100 Subject: [PATCH 07/12] Use a correct endpoint to validate the deposit address --- dapp/src/utils/externalApi.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dapp/src/utils/externalApi.ts b/dapp/src/utils/externalApi.ts index 99f0b04c4..652409805 100644 --- a/dapp/src/utils/externalApi.ts +++ b/dapp/src/utils/externalApi.ts @@ -9,18 +9,27 @@ export async function verifyDepositAddress( status: "valid" | "invalid" | "error" response: unknown }> { - // TODO: Use a correct endpoint const endpoint = "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" - const { depositor, blindingFactor, refundPublicKeyHash, refundLocktime } = - deposit + const { + depositor, + blindingFactor, + refundPublicKeyHash, + refundLocktime, + extraData, + } = deposit try { + const jsonType = extraData ? "json-extradata" : "json" + const baseUrl = `${endpoint}/${jsonType}/${network}/latest/${ + depositor.identifierHex + }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}` + + const url = extraData ? `${baseUrl}/${extraData.toString()}` : baseUrl + const response = await axios.get<{ address: string }>( - `${endpoint}/json/${network}/latest/${ - depositor.identifierHex - }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}`, + url, { timeout: 10000 }, // 10s ) From d4b06225658f09bb56fcc9735acb49c4a5d1cd17 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Mon, 26 Feb 2024 11:05:44 +0100 Subject: [PATCH 08/12] Rename from `externalAPI` to `verifyDepositAddress` --- dapp/src/utils/index.ts | 2 +- dapp/src/utils/{externalApi.ts => verifyDepositAddress.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename dapp/src/utils/{externalApi.ts => verifyDepositAddress.ts} (100%) diff --git a/dapp/src/utils/index.ts b/dapp/src/utils/index.ts index 30a1624a9..865b6211e 100644 --- a/dapp/src/utils/index.ts +++ b/dapp/src/utils/index.ts @@ -6,4 +6,4 @@ export * from "./chain" export * from "./text" export * from "./time" export * from "./async" -export * from "./externalApi" +export * from "./verifyDepositAddress" diff --git a/dapp/src/utils/externalApi.ts b/dapp/src/utils/verifyDepositAddress.ts similarity index 100% rename from dapp/src/utils/externalApi.ts rename to dapp/src/utils/verifyDepositAddress.ts From 6ef50ce5a3617696af92d773c99407dbc0975335 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Mon, 26 Feb 2024 15:17:50 +0100 Subject: [PATCH 09/12] Do not allow deposit action when verification returns invalid or error response --- .../ActiveStakingStep/DepositBTCModal.tsx | 18 ++++++++++++++---- dapp/src/hooks/useDepositTelemetry.ts | 6 +++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx index e79b26885..935bc3ed5 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx @@ -49,13 +49,19 @@ export default function DepositBTCModal() { const { sendBitcoinTransaction } = useDepositBTCTransaction(onDepositBTCSuccess) - const handledDepositBTC = useCallback(() => { + const handledDepositBTC = useCallback(async () => { if (!tokenAmount?.amount || !btcAddress || !depositReceipt || !ethAccount) return - asyncWrapper( - depositTelemetry(depositReceipt, btcAddress, ethAccount.address), + const response = await depositTelemetry( + depositReceipt, + btcAddress, + ethAccount.address, ) + + // TODO: Display the correct message for the user + if (response.verificationStatus !== "valid") return + asyncWrapper(sendBitcoinTransaction(tokenAmount?.amount, btcAddress)) }, [ btcAddress, @@ -66,11 +72,15 @@ export default function DepositBTCModal() { tokenAmount?.amount, ]) + const handledDepositBTCWrapper = useCallback(() => { + asyncWrapper(handledDepositBTC()) + }, [handledDepositBTC]) + return ( diff --git a/dapp/src/hooks/useDepositTelemetry.ts b/dapp/src/hooks/useDepositTelemetry.ts index 40378625e..bcf5d09d3 100644 --- a/dapp/src/hooks/useDepositTelemetry.ts +++ b/dapp/src/hooks/useDepositTelemetry.ts @@ -28,6 +28,8 @@ export function useDepositTelemetry() { extraData, } = deposit + const verificationStatus = { verificationStatus: status } + captureMessage( `Generated deposit [${depositAddress}]`, { @@ -42,9 +44,11 @@ export function useDepositTelemetry() { }, { ethAddress, - "verification.status": status, + ...verificationStatus, }, ) + + return verificationStatus }, [captureMessage], ) From c9b85c04b7b597bf2829b89adce4bfda443a6236 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 27 Feb 2024 12:45:39 +0100 Subject: [PATCH 10/12] Use `ONE_SEC_IN_MILLISECONDS` to define time --- dapp/src/utils/verifyDepositAddress.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dapp/src/utils/verifyDepositAddress.ts b/dapp/src/utils/verifyDepositAddress.ts index 652409805..77655b83f 100644 --- a/dapp/src/utils/verifyDepositAddress.ts +++ b/dapp/src/utils/verifyDepositAddress.ts @@ -1,3 +1,4 @@ +import { ONE_SEC_IN_MILLISECONDS } from "#/constants" import { BitcoinNetwork, DepositReceipt } from "@acre-btc/sdk" import axios from "axios" @@ -28,10 +29,9 @@ export async function verifyDepositAddress( const url = extraData ? `${baseUrl}/${extraData.toString()}` : baseUrl - const response = await axios.get<{ address: string }>( - url, - { timeout: 10000 }, // 10s - ) + const response = await axios.get<{ address: string }>(url, { + timeout: ONE_SEC_IN_MILLISECONDS * 10, + }) const match = response.data.address === depositAddress From 8f6d09a2b8c2a4a703f841bdf5814562a7c63f7f Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 27 Feb 2024 12:46:43 +0100 Subject: [PATCH 11/12] Move endpoint out of `verifyDepositAddress` function --- dapp/src/utils/verifyDepositAddress.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dapp/src/utils/verifyDepositAddress.ts b/dapp/src/utils/verifyDepositAddress.ts index 77655b83f..479c24935 100644 --- a/dapp/src/utils/verifyDepositAddress.ts +++ b/dapp/src/utils/verifyDepositAddress.ts @@ -2,6 +2,9 @@ import { ONE_SEC_IN_MILLISECONDS } from "#/constants" import { BitcoinNetwork, DepositReceipt } from "@acre-btc/sdk" import axios from "axios" +const endpoint = + "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" + export async function verifyDepositAddress( deposit: DepositReceipt, depositAddress: string, @@ -10,9 +13,6 @@ export async function verifyDepositAddress( status: "valid" | "invalid" | "error" response: unknown }> { - const endpoint = - "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" - const { depositor, blindingFactor, From 94eaec0c5bdbbe2456989e37b4f7441b8350179a Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 27 Feb 2024 13:13:07 +0100 Subject: [PATCH 12/12] Create a helper function to generate URL --- dapp/src/utils/verifyDepositAddress.ts | 31 ++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/dapp/src/utils/verifyDepositAddress.ts b/dapp/src/utils/verifyDepositAddress.ts index 479c24935..af1bd1222 100644 --- a/dapp/src/utils/verifyDepositAddress.ts +++ b/dapp/src/utils/verifyDepositAddress.ts @@ -5,14 +5,7 @@ import axios from "axios" const endpoint = "https://us-central1-keep-prd-210b.cloudfunctions.net/verify-deposit-address" -export async function verifyDepositAddress( - deposit: DepositReceipt, - depositAddress: string, - network: BitcoinNetwork, -): Promise<{ - status: "valid" | "invalid" | "error" - response: unknown -}> { +function createURL(deposit: DepositReceipt, network: BitcoinNetwork): string { const { depositor, blindingFactor, @@ -21,14 +14,24 @@ export async function verifyDepositAddress( extraData, } = deposit - try { - const jsonType = extraData ? "json-extradata" : "json" - const baseUrl = `${endpoint}/${jsonType}/${network}/latest/${ - depositor.identifierHex - }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}` + const jsonType = extraData ? "json-extradata" : "json" + const baseUrl = `${endpoint}/${jsonType}/${network}/latest/${ + depositor.identifierHex + }/${blindingFactor.toString()}/${refundPublicKeyHash.toString()}/${refundLocktime.toString()}` - const url = extraData ? `${baseUrl}/${extraData.toString()}` : baseUrl + return extraData ? `${baseUrl}/${extraData.toString()}` : baseUrl +} +export async function verifyDepositAddress( + deposit: DepositReceipt, + depositAddress: string, + network: BitcoinNetwork, +): Promise<{ + status: "valid" | "invalid" | "error" + response: unknown +}> { + try { + const url = createURL(deposit, network) const response = await axios.get<{ address: string }>(url, { timeout: ONE_SEC_IN_MILLISECONDS * 10, })