Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ jobs:
VITE_VARA_ARCHIVE_NODE_ADDRESSES=${{ secrets.VITE_VARA_ARCHIVE_NODE_ADDRESSES }}
VITE_ETH_BEACON_NODE_ADDRESSES=${{ secrets.VITE_ETH_BEACON_NODE_ADDRESSES }}
VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES=${{ secrets.VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES }}
VITE_SENTRY_DSN=${{ secrets.VITE_SENTRY_DSN }}
VITE_GTM_ID=${{ secrets.VITE_GTM_ID }}

deploy-to-k8s:
Expand Down
3 changes: 2 additions & 1 deletion js/frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ VITE_VARA_ARCHIVE_NODE_ADDRESSES=
VITE_ETH_BEACON_NODE_ADDRESSES=
VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES=

# analytics
# error tracking and analytics
VITE_SENTRY_DSN=
VITE_GTM_ID=
2 changes: 2 additions & 0 deletions js/frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ ARG VITE_VARA_NODE_ADDRESSES \
VITE_VARA_ARCHIVE_NODE_ADDRESSES \
VITE_ETH_BEACON_NODE_ADDRESSES \
VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES \
VITE_SENTRY_DSN \
VITE_GTM_ID

ENV VITE_VARA_NODE_ADDRESSES=${VITE_VARA_NODE_ADDRESSES} \
Expand All @@ -46,6 +47,7 @@ ENV VITE_VARA_NODE_ADDRESSES=${VITE_VARA_NODE_ADDRESSES} \
VITE_VARA_ARCHIVE_NODE_ADDRESSES=${VITE_VARA_ARCHIVE_NODE_ADDRESSES} \
VITE_ETH_BEACON_NODE_ADDRESSES=${VITE_ETH_BEACON_NODE_ADDRESSES} \
VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES=${VITE_ETH_MESSAGE_QUEUE_CONTRACT_ADDRESSES} \
VITE_SENTRY_DSN=${VITE_SENTRY_DSN} \
VITE_GTM_ID=${VITE_GTM_ID}


Expand Down
1 change: 1 addition & 0 deletions js/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@polkadot/react-identicon": "3.16.4",
"@reown/appkit": "1.8.15",
"@reown/appkit-adapter-wagmi": "1.8.15",
"@sentry/react": "10.40.0",
"@tanstack/react-query": "5.90.12",
"gear-bridge-common": "workspace:*",
"graphql": "16.12.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from '@gear-js/vara-ui';
import { Component, ReactNode } from 'react';
import { ErrorBoundary as SentryErrorBoundary, FallbackRender } from '@sentry/react';
import { ComponentProps, PropsWithChildren } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

import { useChangeEffect } from '@/hooks';
Expand All @@ -8,56 +9,27 @@ import { Container } from '../container';

import styles from './error-boundary.module.scss';

type Props = {
children: ReactNode;
};

type FallbackProps = {
message: string;
reset: () => void;
};

type State = {
error: Error | null;
};

function Fallback({ message, reset }: FallbackProps) {
// eslint-disable-next-line @typescript-eslint/unbound-method
function Fallback({ error, resetError }: ComponentProps<FallbackRender>) {
const { pathname } = useLocation();
const navigate = useNavigate();

useChangeEffect(() => {
reset();
resetError();
}, [pathname]);

return (
<Container>
<h2 className={styles.heading}>Oops! Something went wrong:</h2>
<p className={styles.error}>{message}</p>
<p className={styles.error}>{error instanceof Error ? error.message : String(error)}</p>

<Button text="Go Back" size="small" onClick={() => navigate(-1)} />
</Container>
);
}

class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { error: null };
}

static getDerivedStateFromError(error: Error) {
return { error };
}

reset = () => {
this.setState({ error: null });
};

render() {
if (!this.state.error) return this.props.children;

return <Fallback message={this.state.error.message} reset={this.reset} />;
}
function ErrorBoundary({ children }: PropsWithChildren) {
return <SentryErrorBoundary fallback={Fallback}>{children}</SentryErrorBoundary>;
}

export { ErrorBoundary };
3 changes: 2 additions & 1 deletion js/frontend/src/consts/env.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const SENTRY_DSN = import.meta.env.VITE_SENTRY_DSN as string | undefined;
const GTM_ID = import.meta.env.VITE_GTM_ID as string | undefined;

export { GTM_ID };
export { SENTRY_DSN, GTM_ID };
4 changes: 2 additions & 2 deletions js/frontend/src/consts/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ERC20_ABI, WRAPPED_ETH_ABI } from './abi';
import { GTM_ID } from './env';
import { SENTRY_DSN, GTM_ID } from './env';
import { ROUTE } from './routing';
import { VftProgram, WrappedVaraProgram } from './sails';

export { ERC20_ABI, WRAPPED_ETH_ABI, ROUTE, GTM_ID, VftProgram, WrappedVaraProgram };
export { ERC20_ABI, WRAPPED_ETH_ABI, ROUTE, SENTRY_DSN, GTM_ID, VftProgram, WrappedVaraProgram };
2 changes: 2 additions & 0 deletions js/frontend/src/context/network-type/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useApi, useAlert } from '@gear-js/react-hooks';
import { useAppKitNetwork } from '@reown/appkit/react';
import { captureException } from '@sentry/react';
import { PropsWithChildren, useState, useEffect, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useChainId, useConfig, useSwitchChain } from 'wagmi';
Expand Down Expand Up @@ -82,6 +83,7 @@ function NetworkTypeProvider({ children }: PropsWithChildren) {
switchNetwork({ endpoint: NEXT_PRESET.NODE_ADDRESS }).catch((error: Error) => {
alert.error(`Failed to switch network. ${error.message}`);
logger.error('Network switch', error);
captureException(error, { tags: { feature: 'network-switch' } });
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { HexString } from '@gear-js/api';
import { useAccount, useAlert, useApi } from '@gear-js/react-hooks';
import { Button } from '@gear-js/vara-ui';
import { Turnstile, TurnstileInstance } from '@marsidev/react-turnstile';
import { captureException } from '@sentry/react';
import { useMutation } from '@tanstack/react-query';
import { useRef, useState } from 'react';

Expand Down Expand Up @@ -62,13 +63,19 @@ function ButtonComponent<T>({ getBalance, onSuccess, ...parameters }: Props<T>)
'Your request for test tokens has been received and is being processed. The tokens will appear in your balance shortly.',
);
})
.catch((error) => alert.error(error instanceof Error ? error.message : String(error)));
.catch((error) => {
alert.error(error instanceof Error ? error.message : String(error));
captureException(error, { tags: { feature: 'faucet', flow: 'request' } });
});
};

const handleVerificationError = (code: string) => {
settleVerification();
alert.error(`Error verifying that you are a human. Please try again.`);

alert.error(`Error verifying that you are a human, code: ${code}. Please try again.`);
const error = new Error(`Cloudflare Turnstile (human verification) error. Code: ${code}`);

captureException(error, { tags: { feature: 'faucet', flow: 'verification' } });
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useAccount, useAlert } from '@gear-js/react-hooks';
import { Button } from '@gear-js/vara-ui';
import { WalletModal } from '@gear-js/wallet-connect';
import { captureException } from '@sentry/react';

import { Tooltip } from '@/components';
import { useModal } from '@/hooks';
Expand Down Expand Up @@ -32,7 +33,10 @@ function PayVaraFeeButton({ nonce, onInBlock }: Props) {
alert.success('Fee paid successfully');
onInBlock();
})
.catch((error: Error) => alert.error(getErrorMessage(error)));
.catch((error: Error) => {
alert.error(getErrorMessage(error));
captureException(error, { tags: { feature: 'pay-tx-fee' } });
});
};

const renderTooltipText = () => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DEFAULT_ERROR_OPTIONS, DEFAULT_SUCCESS_OPTIONS, useAlert } from '@gear-
import { Button } from '@gear-js/vara-ui';
import { WalletModal } from '@gear-js/wallet-connect';
import { useAppKit } from '@reown/appkit/react';
import { captureException } from '@sentry/react';

import { Tooltip } from '@/components';
import { useAccountsConnection, useModal } from '@/hooks';
Expand Down Expand Up @@ -39,6 +40,7 @@ function RelayVaraTxButton({ nonce, blockNumber, ...props }: VaraProps) {
const onError = (error: Error) => {
logger.error('Vara -> Eth relay', error);
alert.update(alertId, getErrorMessage(error), DEFAULT_ERROR_OPTIONS);
captureException(error, { tags: { feature: 'manual-tx-relay' } });
};

mutate({ onLog, onReceipt, onError });
Expand Down
6 changes: 5 additions & 1 deletion js/frontend/src/features/swap/hooks/use-swap-form.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useAlert, useAccount, useApi } from '@gear-js/react-hooks';
import { zodResolver } from '@hookform/resolvers/zod';
import { captureException } from '@sentry/react';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { formatUnits } from 'viem';
Expand Down Expand Up @@ -72,8 +73,11 @@ function useSwapForm({ accountBalance, ftBalance, shouldPayBridgingFee }: Params
};

const onError = (error: WriteContractErrorType | string) => {
logger.error('Transfer Error', typeof error === 'string' ? new Error(error) : error);
const err = typeof error === 'string' ? new Error(error) : error;

logger.error('Transfer Error', err);
alert.error(getErrorMessage(error));
captureException(err, { tags: { feature: 'swap' } });
};

onSubmit(values).then(onSuccess).catch(onError);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HexString } from '@gear-js/api';
import { useAccount, useAlert } from '@gear-js/react-hooks';
import { Button } from '@gear-js/vara-ui';
import { captureException } from '@sentry/react';
import { ReactNode } from 'react';

import EthSVG from '@/assets/eth.svg?react';
Expand Down Expand Up @@ -57,7 +58,10 @@ function TokensCardComponent({

return refetchBalances();
})
.catch((error: Error) => alert.error(getErrorMessage(error)));
.catch((error: Error) => {
alert.error(getErrorMessage(error));
captureException(error, { tags: { feature: 'burn-tokens' } });
});
};

const renderBalances = () => {
Expand Down
11 changes: 10 additions & 1 deletion js/frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import '@gear-js/vara-ui/dist/style.css';
import * as Sentry from '@sentry/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import TagManager from 'react-gtm-module';
Expand All @@ -7,11 +8,19 @@ import { Outlet, RouterProvider, createBrowserRouter } from 'react-router-dom';
import { useAccountsConnection } from '@/hooks';

import { App } from './app';
import { ROUTE, GTM_ID } from './consts';
import { ROUTE, GTM_ID, SENTRY_DSN } from './consts';
import { NotFound, Home, Transactions, FAQ, TokenTracker, ConnectWallet, Transaction } from './pages';

import './index.scss';

if (SENTRY_DSN)
Sentry.init({
dsn: SENTRY_DSN,
integrations: [Sentry.replayIntegration()],
replaysSessionSampleRate: 0,
replaysOnErrorSampleRate: 1.0,
});

if (GTM_ID) TagManager.initialize({ gtmId: GTM_ID });

// eslint-disable-next-line react-refresh/only-export-components
Expand Down
71 changes: 71 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5232,6 +5232,76 @@ __metadata:
languageName: node
linkType: hard

"@sentry-internal/browser-utils@npm:10.40.0":
version: 10.40.0
resolution: "@sentry-internal/browser-utils@npm:10.40.0"
dependencies:
"@sentry/core": "npm:10.40.0"
checksum: 10c0/9801776fad1c7e9690823588d978631dad4e66fd5e8eab934e9e508306e7d6d149982d6270e00687d62c96255dabb930871f841f7674ab273ead19c1b38bb700
languageName: node
linkType: hard

"@sentry-internal/feedback@npm:10.40.0":
version: 10.40.0
resolution: "@sentry-internal/feedback@npm:10.40.0"
dependencies:
"@sentry/core": "npm:10.40.0"
checksum: 10c0/8694d99adef186c6e93c9b48638391cefbf3a6414ef9ad5bd250740fbc69685b0fb6362734446ee5473b3f82177b4ae72c228ee9dc6f5b07bd423c8eaf8419db
languageName: node
linkType: hard

"@sentry-internal/replay-canvas@npm:10.40.0":
version: 10.40.0
resolution: "@sentry-internal/replay-canvas@npm:10.40.0"
dependencies:
"@sentry-internal/replay": "npm:10.40.0"
"@sentry/core": "npm:10.40.0"
checksum: 10c0/c1f359945eb1dfdbe37053b67a25cd2f241cd6370b24679bc32512e14af4dc3bd92c9663dbca5e66e206f7633dcb1bf521d989ef8f25e7faa998a3ee84ba1c46
languageName: node
linkType: hard

"@sentry-internal/replay@npm:10.40.0":
version: 10.40.0
resolution: "@sentry-internal/replay@npm:10.40.0"
dependencies:
"@sentry-internal/browser-utils": "npm:10.40.0"
"@sentry/core": "npm:10.40.0"
checksum: 10c0/ce7bf12b12360caabccfe60cc0bc6c96cef151a2897fb2d2fa645d845ff812457df72cd8d16bd167ae5ccdf9a8932905be435f2b473d7b0efa6c106837412fbf
languageName: node
linkType: hard

"@sentry/browser@npm:10.40.0":
version: 10.40.0
resolution: "@sentry/browser@npm:10.40.0"
dependencies:
"@sentry-internal/browser-utils": "npm:10.40.0"
"@sentry-internal/feedback": "npm:10.40.0"
"@sentry-internal/replay": "npm:10.40.0"
"@sentry-internal/replay-canvas": "npm:10.40.0"
"@sentry/core": "npm:10.40.0"
checksum: 10c0/4a383bf7d47640d0b5d14e39da3ebd35c88c93b048df13849eea22316f6ee44caf6221005fe87776eb9957219f50702e07f11213d405af1095acdab7fb62bbdb
languageName: node
linkType: hard

"@sentry/core@npm:10.40.0":
version: 10.40.0
resolution: "@sentry/core@npm:10.40.0"
checksum: 10c0/76dc283cda98ae854be63a1836ea77abaf2a3db88b592ae086982e89d2a9d163b5e92819cbf3005bffc459a56ca90b0f71cc908cce7c55e147606b111a4dbb8a
languageName: node
linkType: hard

"@sentry/react@npm:10.40.0":
version: 10.40.0
resolution: "@sentry/react@npm:10.40.0"
dependencies:
"@sentry/browser": "npm:10.40.0"
"@sentry/core": "npm:10.40.0"
peerDependencies:
react: ^16.14.0 || 17.x || 18.x || 19.x
checksum: 10c0/f7efc5b58d43ed96c37e0dcbfee9cc0d6cb75370d0e88d434a2cf4fdea51b8adffc9b6db8258339d7f5ba16920231ad44488933d9e15e8b8fb420aeacf83922e
languageName: node
linkType: hard

"@sigstore/bundle@npm:^2.3.2":
version: 2.3.2
resolution: "@sigstore/bundle@npm:2.3.2"
Expand Down Expand Up @@ -13003,6 +13073,7 @@ __metadata:
"@polkadot/types": "npm:16.4.6"
"@reown/appkit": "npm:1.8.15"
"@reown/appkit-adapter-wagmi": "npm:1.8.15"
"@sentry/react": "npm:10.40.0"
"@tanstack/react-query": "npm:5.90.12"
"@types/react": "npm:19.2.7"
"@types/react-dom": "npm:19.2.3"
Expand Down
Loading