diff --git a/.changeset/lemon-mice-punch.md b/.changeset/lemon-mice-punch.md new file mode 100644 index 00000000..5e5566b1 --- /dev/null +++ b/.changeset/lemon-mice-punch.md @@ -0,0 +1,5 @@ +--- +'@skip-go/widget': patch +--- + +Add sentry integration (session replay, error tracking) diff --git a/packages/widget/package.json b/packages/widget/package.json index c2a1c207..3e26e21c 100644 --- a/packages/widget/package.json +++ b/packages/widget/package.json @@ -98,6 +98,7 @@ "@penumbra-zone/transport-dom": "^7.5.0", "@r2wc/react-to-web-component": "^2.0.3", "@radix-ui/react-dialog": "^1.1.1", + "@sentry/react": "^8.46.0", "@skip-go/client": "workspace:^", "@solana/spl-token": "^0.4.8", "@solana/wallet-adapter-backpack": "^0.1.14", diff --git a/packages/widget/src/hooks/useCreateCosmosWallets.tsx b/packages/widget/src/hooks/useCreateCosmosWallets.tsx index c8c873df..25504cf9 100644 --- a/packages/widget/src/hooks/useCreateCosmosWallets.tsx +++ b/packages/widget/src/hooks/useCreateCosmosWallets.tsx @@ -132,12 +132,12 @@ export const useCreateCosmosWallets = () => { for (const wallet of cosmosWallets) { const isWC = isWalletConnect(wallet); - const mobile = isMobile() + const mobile = isMobile(); const walletInfo = getCosmosWalletInfo(wallet); const initialChainIds = (() => { - if (isWC) return walletConnectMainnetChainIdsInitialConnect - if (wallet === WalletType.KEPLR && !mobile) return keplrMainnetChainIdsInitialConnect - return walletMainnetChainIdsInitialConnect + if (isWC) return walletConnectMainnetChainIdsInitialConnect; + if (wallet === WalletType.KEPLR && !mobile) return keplrMainnetChainIdsInitialConnect; + return walletMainnetChainIdsInitialConnect; })().filter( (x) => chains @@ -299,6 +299,7 @@ export const useCreateCosmosWallets = () => { walletName: wallet, chainIdToAddressMap, }); + } else { await connectSingleChainId(); const address = (await getWallet(wallet).getKey(chainID)) diff --git a/packages/widget/src/index.tsx b/packages/widget/src/index.tsx index db494f3c..b59342ff 100644 --- a/packages/widget/src/index.tsx +++ b/packages/widget/src/index.tsx @@ -1,3 +1,20 @@ export { Widget, ShowWidget } from "./widget/Widget"; export type { WidgetProps } from "./widget/Widget"; -export { defaultTheme, lightTheme } from "./widget/theme"; \ No newline at end of file +export { defaultTheme, lightTheme } from "./widget/theme"; + +import { + init, + replayIntegration, +} from "@sentry/react"; + +init({ + dsn: "https://10ce608bdd1c68a13d3849d6b242333c@o4504768725909504.ingest.us.sentry.io/4508485201231872", + integrations: [replayIntegration({ + maskAllText: false, + maskAllInputs: false, + blockAllMedia: false, + })], + // Session Replay + replaysSessionSampleRate: 0, + replaysOnErrorSampleRate: 1, +}); diff --git a/packages/widget/src/pages/ErrorPage/ErrorPageTransactionFailed.tsx b/packages/widget/src/pages/ErrorPage/ErrorPageTransactionFailed.tsx index d41dfb25..fd9eba6d 100644 --- a/packages/widget/src/pages/ErrorPage/ErrorPageTransactionFailed.tsx +++ b/packages/widget/src/pages/ErrorPage/ErrorPageTransactionFailed.tsx @@ -10,6 +10,8 @@ import { errorAtom } from "@/state/errorPage"; import { currentPageAtom, Routes } from "@/state/router"; import { useSetAtom } from "jotai"; import { getTruncatedAddress } from "@/utils/crypto"; +import { captureException } from "@sentry/browser"; +import { useEffect } from "react"; export type ErrorPageTransactionFailedProps = { transactionHash: string; @@ -24,6 +26,11 @@ export const ErrorPageTransactionFailed = ({ onClickContactSupport, onClickBack, }: ErrorPageTransactionFailedProps) => { + + useEffect(() => { + captureException("TransactionFailed"); + }, []); + const theme = useTheme(); const setErrorAtom = useSetAtom(errorAtom); const setCurrentPage = useSetAtom(currentPageAtom); diff --git a/packages/widget/src/pages/ErrorPage/ErrorPageTransactionReverted.tsx b/packages/widget/src/pages/ErrorPage/ErrorPageTransactionReverted.tsx index 73a1c095..f5066b64 100644 --- a/packages/widget/src/pages/ErrorPage/ErrorPageTransactionReverted.tsx +++ b/packages/widget/src/pages/ErrorPage/ErrorPageTransactionReverted.tsx @@ -11,6 +11,8 @@ import { SwapPageHeader } from "../SwapPage/SwapPageHeader"; import { currentPageAtom, Routes } from "@/state/router"; import { errorAtom } from "@/state/errorPage"; import { useSetAtom } from "jotai"; +import { captureException } from "@sentry/react"; +import { useEffect } from "react"; export type ErrorPageTransactionRevertedProps = { explorerUrl: string; @@ -27,6 +29,11 @@ export const ErrorPageTransactionReverted = ({ onClickContinueTransaction, onClickBack, }: ErrorPageTransactionRevertedProps) => { + + useEffect(() => { + captureException("TransactionReverted"); + }, []); + const setErrorAtom = useSetAtom(errorAtom); const setCurrentPage = useSetAtom(currentPageAtom); const theme = useTheme(); diff --git a/packages/widget/src/pages/SwapPage/SwapPage.tsx b/packages/widget/src/pages/SwapPage/SwapPage.tsx index f9506993..4c040067 100644 --- a/packages/widget/src/pages/SwapPage/SwapPage.tsx +++ b/packages/widget/src/pages/SwapPage/SwapPage.tsx @@ -41,6 +41,7 @@ import NiceModal from "@ebay/nice-modal-react"; import { Modals } from "@/modals/registerModals"; import { useIsSwapOperation } from "@/hooks/useIsGoFast"; import { useShowCosmosLedgerWarning } from "@/hooks/useShowCosmosLedgerWarning"; +import { setUser } from "@sentry/react"; export const SwapPage = () => { const [container, setContainer] = useState(); @@ -304,6 +305,7 @@ export const SwapPage = () => { } setChainAddresses({}); setCurrentPage(Routes.SwapExecutionPage); + setUser({ username: sourceAccount?.address }); setSwapExecutionState(); }} /> diff --git a/packages/widget/src/state/swapExecutionPage.ts b/packages/widget/src/state/swapExecutionPage.ts index 48951702..d28c92a9 100644 --- a/packages/widget/src/state/swapExecutionPage.ts +++ b/packages/widget/src/state/swapExecutionPage.ts @@ -13,6 +13,7 @@ import { isUserRejectedRequestError } from "@/utils/error"; import { CosmosGasAmount, slippageAtom } from "./swapPage"; import { createExplorerLink } from "@/utils/explorerLink"; import { callbacksAtom } from "./callbacks"; +import { setUser } from "@sentry/react"; type ValidatingGasBalanceData = { chainID?: string; @@ -96,6 +97,7 @@ export const setSwapExecutionStateAtom = atom(null, (get, set) => { } }, onTransactionBroadcast: async (txInfo) => { + setUser({ id: txInfo?.txHash }); const chain = chains?.find((chain) => chain.chainID === txInfo.chainID); const explorerLink = createExplorerLink({ chainID: txInfo.chainID, chainType: chain?.chainType, txHash: txInfo.txHash }); set(setTransactionDetailsAtom, { ...txInfo, explorerLink, status: undefined }, transactionHistoryIndex); @@ -281,4 +283,4 @@ export const skipSubmitSwapExecutionAtom = atomWithMutation((get) => { submitSwapExecutionCallbacks?.onError?.(error, transactionDetailsArray); }, }; -}); +}); \ No newline at end of file diff --git a/packages/widget/src/widget/Router.tsx b/packages/widget/src/widget/Router.tsx index f3360416..a8ec8f12 100644 --- a/packages/widget/src/widget/Router.tsx +++ b/packages/widget/src/widget/Router.tsx @@ -6,6 +6,7 @@ import { errorAtom, ErrorType } from "@/state/errorPage"; import { Routes, currentPageAtom } from "@/state/router"; import { useAtom } from "jotai"; import { ErrorBoundary } from "react-error-boundary"; +import { captureException } from "@sentry/browser"; export const Router = () => { const [currentPage] = useAtom(currentPageAtom); @@ -20,9 +21,10 @@ export const Router = () => { return ( - setError({ errorType: ErrorType.Unexpected, error }) - } + onError={(error) => { + captureException(error); + setError({ errorType: ErrorType.Unexpected, error }); + }} > @@ -31,9 +33,10 @@ export const Router = () => { return ( - setError({ errorType: ErrorType.Unexpected, error }) - } + onError={(error) => { + captureException(error); + setError({ errorType: ErrorType.Unexpected, error }); + }} > @@ -42,9 +45,10 @@ export const Router = () => { return ( - setError({ errorType: ErrorType.Unexpected, error }) - } + onError={(error) => { + captureException(error); + setError({ errorType: ErrorType.Unexpected, error }); + }} > diff --git a/yarn.lock b/yarn.lock index 427f448a..765bdca0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7598,6 +7598,77 @@ __metadata: languageName: node linkType: hard +"@sentry-internal/browser-utils@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry-internal/browser-utils@npm:8.46.0" + dependencies: + "@sentry/core": 8.46.0 + checksum: 2151495dc349d48618654217b6250d9cd1cd89fe1a1f9da86e105c2a196549891521783ed055c6c5721ef83f4bdca406b2b0e00b1af3a2f9e235ec1dc3b25d63 + languageName: node + linkType: hard + +"@sentry-internal/feedback@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry-internal/feedback@npm:8.46.0" + dependencies: + "@sentry/core": 8.46.0 + checksum: 1c5751ef69e363a3785676d34da5b43b5d937448d902d7fd3195a6fca6e30050ccbd9565cc7718e0bd3b4ee275f5deb34bfc9370e56ea214a42cf1e379ded0d5 + languageName: node + linkType: hard + +"@sentry-internal/replay-canvas@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry-internal/replay-canvas@npm:8.46.0" + dependencies: + "@sentry-internal/replay": 8.46.0 + "@sentry/core": 8.46.0 + checksum: 5ed79df242c9b2c41084039e6ef73bac0714902822c04e45684c20200f17c89cfda7daf56e066c7e315023e157e150acab36ebaa7132d6062ad1ac6216eb0852 + languageName: node + linkType: hard + +"@sentry-internal/replay@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry-internal/replay@npm:8.46.0" + dependencies: + "@sentry-internal/browser-utils": 8.46.0 + "@sentry/core": 8.46.0 + checksum: 66d90a7e1cf6aecec9d81436eb5d07642dec07f5e8dea95e049af615ae0858e64d36a64524bdff8b4d81b9da359b60b11aea574d313a743de16410489014604b + languageName: node + linkType: hard + +"@sentry/browser@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry/browser@npm:8.46.0" + dependencies: + "@sentry-internal/browser-utils": 8.46.0 + "@sentry-internal/feedback": 8.46.0 + "@sentry-internal/replay": 8.46.0 + "@sentry-internal/replay-canvas": 8.46.0 + "@sentry/core": 8.46.0 + checksum: fc40fd73c8af1f79c2984425cc12354d76d57d12c27b7b83eaaaa118f74e7e81861f8f33c2069d8feaa4a7cd71a1ef8b3e699e2626f4875f4bc226e4d9df6d51 + languageName: node + linkType: hard + +"@sentry/core@npm:8.46.0": + version: 8.46.0 + resolution: "@sentry/core@npm:8.46.0" + checksum: 0d7f5907ae925c51acbf0713f8f685bdc854f7af7f5b4a336ace07f64f86002e9493cc27ee8c06bd440f879472ee2ed47120cd48d0336f4e4a29114b198927b4 + languageName: node + linkType: hard + +"@sentry/react@npm:^8.46.0": + version: 8.46.0 + resolution: "@sentry/react@npm:8.46.0" + dependencies: + "@sentry/browser": 8.46.0 + "@sentry/core": 8.46.0 + hoist-non-react-statics: ^3.3.2 + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + checksum: ceeeed52c68679569a8153a36d8b2efe2da0957c43e51ac0891d5a71af83b1d278bf32fabf65f13f7eb06fd340ee9c763fb7e0765d358f95985b1668e8624bca + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.24.1": version: 0.24.51 resolution: "@sinclair/typebox@npm:0.24.51" @@ -7693,6 +7764,7 @@ __metadata: "@penumbra-zone/transport-dom": ^7.5.0 "@r2wc/react-to-web-component": ^2.0.3 "@radix-ui/react-dialog": ^1.1.1 + "@sentry/react": ^8.46.0 "@skip-go/client": "workspace:^" "@solana/spl-token": ^0.4.8 "@solana/wallet-adapter-backpack": ^0.1.14