From 2f6368d0356c2efe9fea50b0572ee6fd18540f87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Thu, 14 Nov 2024 17:57:34 +0000
Subject: [PATCH 01/16] feat(evm): add dynamic
---
apps/evm/package.json | 7 +
.../components/BridgeForm/BobBridgeForm.tsx | 2 +-
.../components/BridgeForm/BtcBridgeForm.tsx | 2 +-
.../BridgeStatus/BridgeStatus.style.tsx | 2 +-
.../components/StakeForm/BtcStakeForm.tsx | 2 +-
apps/evm/src/app/[lang]/nested-providers.tsx | 23 +-
apps/evm/src/app/[lang]/providers.tsx | 55 +-
apps/evm/src/app/[lang]/sign-up/SignUp.tsx | 50 +-
.../AuthButton/AuthButton.stories.tsx | 110 +++
.../src/components/AuthButton/AuthButton.tsx | 111 +++
.../AuthButton/__tests__/AuthButton.test.tsx | 0
.../AuthButton/index.tsx | 0
apps/evm/src/components/Layout/Header.tsx | 6 +-
.../components/LoginButton/LoginButton.tsx | 52 +-
.../components/SignUpButton/SignUpButton.tsx | 50 +-
.../components/WithdrawModal/WithdrawForm.tsx | 2 +-
apps/evm/src/components/index.ts | 1 +
.../component/ConnectWallet/ConnectWallet.tsx | 48 +-
packages/wagmi/src/index.ts | 14 +
pnpm-lock.yaml | 723 ++++++++++++++++--
20 files changed, 1057 insertions(+), 203 deletions(-)
create mode 100644 apps/evm/src/components/AuthButton/AuthButton.stories.tsx
create mode 100644 apps/evm/src/components/AuthButton/AuthButton.tsx
rename apps/evm/src/{connect-ui/component => components}/AuthButton/__tests__/AuthButton.test.tsx (100%)
rename apps/evm/src/{connect-ui/component => components}/AuthButton/index.tsx (100%)
create mode 100644 packages/wagmi/src/index.ts
diff --git a/apps/evm/package.json b/apps/evm/package.json
index 3e6b06403..146eccd2c 100644
--- a/apps/evm/package.json
+++ b/apps/evm/package.json
@@ -18,6 +18,13 @@
"dependencies": {
"@binance/w3w-wagmi-connector-v2": "1.2.4-alpha.0",
"@gobob/bob-sdk": "^3.1.0",
+ "@dynamic-labs/bitcoin": "^3.6.2",
+ "@dynamic-labs/ethereum": "^v3.0.0-alpha.29",
+ "@dynamic-labs/iconic": "^3.6.2",
+ "@dynamic-labs/sdk-react-core": "^v3.0.0-alpha.29",
+ "@dynamic-labs/wagmi-connector": "^v3.0.0-alpha.29",
+ "@eth-optimism/sdk": "^3.1.6",
+ "@ethersproject/providers": "^5.7.2",
"@gobob/chains": "workspace:^",
"@gobob/currency": "workspace:^",
"@gobob/hooks": "workspace:^",
diff --git a/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx b/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx
index c3fb3bedd..d7aeb092e 100644
--- a/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx
+++ b/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx
@@ -19,7 +19,7 @@ import { BridgeAlert } from './BridgeAlert';
import { l1StandardBridgeAbi } from '@/abis/L1StandardBridge.abi';
import { l2StandardBridgeAbi } from '@/abis/L2StandardBridge.abi';
-import { AuthButton } from '@/connect-ui';
+import { AuthButton } from '@/components';
import { L1_CHAIN, L2_CHAIN } from '@/constants';
import { bridgeContracts } from '@/constants/bridge';
import {
diff --git a/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BtcBridgeForm.tsx b/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BtcBridgeForm.tsx
index acc14cdf3..c3fd2b8ef 100644
--- a/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BtcBridgeForm.tsx
+++ b/apps/evm/src/app/[lang]/(bridge)/bridge/components/BridgeForm/BtcBridgeForm.tsx
@@ -13,7 +13,7 @@ import { useAccount } from 'wagmi';
import { BtcTokenInput, GatewayGasSwitch, GatewayTransactionDetails } from '../../../components';
import { useGateway, useGatewayForm } from '../../../hooks';
-import { AuthButton } from '@/connect-ui';
+import { AuthButton } from '@/components';
import { isProd } from '@/constants';
import { TokenData } from '@/hooks';
import { BRIDGE_RECIPIENT, BridgeFormValues } from '@/lib/form/bridge';
diff --git a/apps/evm/src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStatus.style.tsx b/apps/evm/src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStatus.style.tsx
index a557467ac..3e0907038 100644
--- a/apps/evm/src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStatus.style.tsx
+++ b/apps/evm/src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStatus.style.tsx
@@ -1,7 +1,7 @@
import { P } from '@gobob/ui';
import styled from 'styled-components';
-import { AuthButton } from '@/connect-ui';
+import { AuthButton } from '@/components';
const StyledTimePill = styled(P)`
padding: ${({ theme }) => `${theme.spacing('xs')} ${theme.spacing('lg')}`};
diff --git a/apps/evm/src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx b/apps/evm/src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx
index 8333fe91b..0b49cf6cb 100644
--- a/apps/evm/src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx
+++ b/apps/evm/src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx
@@ -12,7 +12,7 @@ import { useGateway, useGatewayForm } from '../../../hooks';
import { StrategyData } from './StakeForm';
-import { AuthButton } from '@/connect-ui';
+import { AuthButton } from '@/components';
import { BRIDGE_RECIPIENT, BridgeFormValues } from '@/lib/form/bridge';
import { GatewayTransactionType, InitGatewayTransaction } from '@/types';
diff --git a/apps/evm/src/app/[lang]/nested-providers.tsx b/apps/evm/src/app/[lang]/nested-providers.tsx
index 0e198d844..5091cc330 100644
--- a/apps/evm/src/app/[lang]/nested-providers.tsx
+++ b/apps/evm/src/app/[lang]/nested-providers.tsx
@@ -11,7 +11,6 @@ import { isAddressEqual } from 'viem';
import { useAccount, useAccountEffect, useChainId, useConfig, useSwitchChain } from 'wagmi';
import { Header, Layout, Sidebar } from '@/components';
-import { ConnectProvider } from '@/connect-ui';
import { isClient, L2_CHAIN, LocalStorageKey } from '@/constants';
import { useBalances, useGetUser, useLogout, useTokens } from '@/hooks';
import { StyledComponentsRegistry } from '@/lib/styled-components';
@@ -136,18 +135,16 @@ export function NestedProviders({ children }: PropsWithChildren) {
return (
-
-
-
-
-
-
-
-
-
- {children}
-
-
+
+
+
+
+
+
+
+
+ {children}
+
);
diff --git a/apps/evm/src/app/[lang]/providers.tsx b/apps/evm/src/app/[lang]/providers.tsx
index fe4d008c4..5477b72b8 100644
--- a/apps/evm/src/app/[lang]/providers.tsx
+++ b/apps/evm/src/app/[lang]/providers.tsx
@@ -1,13 +1,17 @@
'use client';
-import { SatsWagmiConfig } from '@gobob/sats-wagmi';
+import { BitcoinWalletConnectors } from '@dynamic-labs/bitcoin';
+import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';
+import { BitcoinIcon, EthereumIcon } from '@dynamic-labs/iconic';
+import { DynamicContextProvider, FilterChain } from '@dynamic-labs/sdk-react-core';
+import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { PropsWithChildren, useState } from 'react';
import { State, WagmiProvider } from 'wagmi';
import { NestedProviders } from './nested-providers';
-import { bitcoinNetwork, INTERVAL, isProd } from '@/constants';
+import { INTERVAL, isProd } from '@/constants';
import { getConfig } from '@/lib/wagmi';
import { FetchError } from '@/types/fetch';
@@ -38,15 +42,46 @@ export function Providers({ initialState, children }: PropsWithChildren<{ initia
}
})
);
- const [config] = useState(() => getConfig({ isProd }));
+ const [config] = useState(() => getConfig({ isProd, multiInjectedProviderDiscovery: false }));
return (
-
-
-
- {children}
-
-
-
+ },
+ walletsFilter: FilterChain('EVM')
+ },
+ {
+ label: { icon: },
+ walletsFilter: FilterChain('BTC')
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }}
+ >
+
+
+ {/* */}
+
+ {children}
+
+
+
+
);
}
diff --git a/apps/evm/src/app/[lang]/sign-up/SignUp.tsx b/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
index 01918b13c..29dca95f3 100644
--- a/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
+++ b/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
@@ -1,28 +1,28 @@
'use client';
-import { ChainId } from '@gobob/chains';
-import { Button, Divider, Flex, P, toast } from '@gobob/ui';
+import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
+import { Button, Divider, Flex, P } from '@gobob/ui';
import { Trans, t } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { useMutation } from '@tanstack/react-query';
import { useParams, useRouter } from 'next/navigation';
import { FormEventHandler, Suspense, useEffect, useState } from 'react';
-import { useAccount, useSwitchChain } from 'wagmi';
+import { useAccount, useAccountEffect } from 'wagmi';
import { Auditors, HighlightText, ReferralInput } from './components';
import { StyledAuthCard, StyledH1 } from './SignUp.style';
import { Geoblock, LoginSection, Main } from '@/components';
-import { useConnectModal } from '@/connect-ui';
-import { L1_CHAIN, L2_CHAIN, RoutesPath, isValidChain } from '@/constants';
+import { RoutesPath } from '@/constants';
import { useGetUser, useSignUp } from '@/hooks';
import { fusionKeys } from '@/lib/react-query';
import { apiClient } from '@/utils';
const SignUp = (): JSX.Element | null => {
- const { address, chain } = useAccount();
- const { switchChainAsync } = useSwitchChain();
- const { open } = useConnectModal();
+ const { address } = useAccount();
+
+ const { setShowAuthFlow, setSelectedTabIndex } = useDynamicContext();
+
const { i18n } = useLingui();
const router = useRouter();
@@ -31,6 +31,8 @@ const SignUp = (): JSX.Element | null => {
const [referalCode, setReferalCode] = useState('');
+ const [isConnecting, setConnecting] = useState(false);
+
const { mutate: signUp, isPending: isLoadingSignUp } = useSignUp();
const {
@@ -54,6 +56,16 @@ const SignUp = (): JSX.Element | null => {
setReferalCode(code);
};
+ useAccountEffect({
+ onConnect: () => {
+ if (isConnecting) {
+ signUp({});
+
+ setConnecting(false);
+ }
+ }
+ });
+
const handleSubmit: FormEventHandler = async (e) => {
e.preventDefault();
@@ -62,24 +74,12 @@ const SignUp = (): JSX.Element | null => {
}
if (!address) {
- return open({
- onConnectEvm: async ({ address, connector }) => {
- if (!address) return;
- if (!isValidChain((await connector?.getChainId()) as ChainId)) {
- const chain = await connector?.switchChain?.({ chainId: L2_CHAIN });
-
- if (!chain) {
- return toast.error(Something went wrong. Please try connecting your wallet again.);
- }
- }
-
- return signUp(address);
- }
- });
- }
+ setSelectedTabIndex(1);
+ setShowAuthFlow(true);
+
+ setConnecting(true);
- if (!chain || (chain && !isValidChain(chain?.id))) {
- await switchChainAsync({ chainId: L1_CHAIN });
+ return;
}
return signUp(address);
diff --git a/apps/evm/src/components/AuthButton/AuthButton.stories.tsx b/apps/evm/src/components/AuthButton/AuthButton.stories.tsx
new file mode 100644
index 000000000..d68784ac1
--- /dev/null
+++ b/apps/evm/src/components/AuthButton/AuthButton.stories.tsx
@@ -0,0 +1,110 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { useDisconnect, useAccount } from '@gobob/wagmi';
+import { useDisconnect as useStasDisconnect, useAccount as useSatsAccount } from '@gobob/sats-wagmi';
+import { Flex } from '@gobob/ui';
+
+import { ConnectProvider } from '../..';
+
+import { AuthButton as Component, AuthButtonProps } from '.';
+
+export default {
+ title: 'Connect/AuthButton',
+ component: Component,
+ parameters: {
+ layout: 'centered'
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ )
+ ]
+} as Meta;
+
+const RenderDefault = (args: AuthButtonProps) => {
+ const { address } = useAccount();
+ const { disconnect } = useDisconnect();
+
+ const handleDisconnect = () => {
+ if (address) {
+ disconnect();
+ }
+ };
+
+ return (
+
+ {address}
+ {address && Disconnect}
+
+ );
+};
+
+export const Default: StoryObj = {
+ args: {},
+ render: RenderDefault
+};
+
+const RenderOnlyBtc = (args: AuthButtonProps) => {
+ const { address } = useSatsAccount();
+ const { disconnect } = useStasDisconnect();
+
+ const handleDisconnect = () => {
+ if (address) {
+ disconnect();
+ }
+ };
+
+ return (
+
+ {address}
+ {address && Disconnect}
+
+ );
+};
+
+export const OnlyBTC: StoryObj = {
+ args: { isBtcAuthRequired: true },
+ decorators: [
+ (Story) => (
+
+
+
+ )
+ ],
+ render: RenderOnlyBtc
+};
+
+const RenderBtcEvm = (args: AuthButtonProps) => {
+ const { address } = useAccount();
+ const { disconnect } = useDisconnect();
+ const { address: btcAddress } = useSatsAccount();
+ const { disconnect: btcDisconnect } = useStasDisconnect();
+
+ const handleDisconnect = () => {
+ if (address) {
+ disconnect();
+ }
+
+ if (btcAddress) {
+ btcDisconnect();
+ }
+ };
+
+ return (
+
+
+ {address}
+
+ {btcAddress}
+
+ {address && Disconnect}
+
+ );
+};
+
+export const EVM_and_BTC: StoryObj = {
+ args: { isBtcAuthRequired: true },
+
+ render: RenderBtcEvm
+};
diff --git a/apps/evm/src/components/AuthButton/AuthButton.tsx b/apps/evm/src/components/AuthButton/AuthButton.tsx
new file mode 100644
index 000000000..5a09c9da1
--- /dev/null
+++ b/apps/evm/src/components/AuthButton/AuthButton.tsx
@@ -0,0 +1,111 @@
+'use client';
+
+import { useDynamicContext, useUserWallets } from '@dynamic-labs/sdk-react-core';
+import { ChainId, getChainName } from '@gobob/chains';
+import { Button, ButtonProps } from '@gobob/ui';
+import { useAccount, useSwitchChain } from '@gobob/wagmi';
+import { Trans } from '@lingui/macro';
+import { PressEvent } from '@react-aria/interactions';
+import { useIsClient } from 'usehooks-ts';
+
+type Props = {
+ chain?: ChainId;
+ isBtcAuthRequired?: boolean;
+ isEvmAuthRequired?: boolean;
+ isSilentSwitch?: boolean;
+ shouldPressAfterSwitch?: boolean;
+};
+
+type InheritAttrs = Omit;
+
+type AuthButtonProps = Props & InheritAttrs;
+
+const AuthButton = ({
+ onPress,
+ onClick,
+ disabled,
+ children,
+ type,
+ chain: chainProp,
+ isEvmAuthRequired = true,
+ isBtcAuthRequired,
+ isSilentSwitch,
+ shouldPressAfterSwitch,
+ ...props
+}: AuthButtonProps) => {
+ const isClient = useIsClient();
+
+ const { chain } = useAccount();
+ const { switchChainAsync, isPending: isSwitchNetworkLoading } = useSwitchChain();
+
+ const { setShowAuthFlow, setSelectedTabIndex } = useDynamicContext();
+ const userWallets = useUserWallets();
+
+ if (!isClient) {
+ return (
+
+ );
+ }
+
+ const evmWallet = userWallets.find((wallet) => wallet.chain === 'EVM');
+
+ // Comes first because if the connection includes evm, the priority is always evm
+ if (isEvmAuthRequired && !evmWallet) {
+ const handlePress = (): void => {
+ setSelectedTabIndex(1);
+ setShowAuthFlow(true);
+ };
+
+ return (
+
+ );
+ }
+
+ if (isEvmAuthRequired && chainProp && chain?.id !== chainProp) {
+ const name = getChainName(chainProp);
+ const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
+
+ const handlePress = async (e: PressEvent) => {
+ await switchChainAsync?.({ chainId: chainProp });
+
+ if (shouldPressAfterSwitch) {
+ onPress?.(e);
+ }
+ };
+
+ return (
+
+ );
+ }
+
+ const btcWallet = userWallets.find((wallet) => wallet.chain === 'BTC');
+
+ if (isBtcAuthRequired && !btcWallet) {
+ const handlePress = (): void => {
+ console.log('here');
+ setSelectedTabIndex(2);
+ setShowAuthFlow(true);
+ };
+
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+};
+
+export { AuthButton };
+export type { AuthButtonProps };
diff --git a/apps/evm/src/connect-ui/component/AuthButton/__tests__/AuthButton.test.tsx b/apps/evm/src/components/AuthButton/__tests__/AuthButton.test.tsx
similarity index 100%
rename from apps/evm/src/connect-ui/component/AuthButton/__tests__/AuthButton.test.tsx
rename to apps/evm/src/components/AuthButton/__tests__/AuthButton.test.tsx
diff --git a/apps/evm/src/connect-ui/component/AuthButton/index.tsx b/apps/evm/src/components/AuthButton/index.tsx
similarity index 100%
rename from apps/evm/src/connect-ui/component/AuthButton/index.tsx
rename to apps/evm/src/components/AuthButton/index.tsx
diff --git a/apps/evm/src/components/Layout/Header.tsx b/apps/evm/src/components/Layout/Header.tsx
index eaa5352fd..bd05b287b 100644
--- a/apps/evm/src/components/Layout/Header.tsx
+++ b/apps/evm/src/components/Layout/Header.tsx
@@ -1,5 +1,6 @@
'use client';
+import { DynamicWidget } from '@dynamic-labs/sdk-react-core';
import {
Bars3,
Button,
@@ -13,9 +14,9 @@ import {
useMediaQuery
} from '@gobob/ui';
import { t, Trans } from '@lingui/macro';
+import { useLingui } from '@lingui/react';
import { useState } from 'react';
import { useTheme } from 'styled-components';
-import { useLingui } from '@lingui/react';
import { Logo } from '../Logo';
import { SocialsGroup } from '../SocialsGroup';
@@ -26,7 +27,6 @@ import { useLayoutContext } from './LayoutContext';
import { Nav } from './Nav';
import { NavItem } from './NavItem';
-import { ConnectWallet } from '@/connect-ui';
import { DocsLinks, RoutesPath } from '@/constants';
import { useUserAgent } from '@/user-agent';
@@ -113,7 +113,7 @@ const Header = ({ isTestnet, isFusion, ...props }: HeaderProps): JSX.Element =>
-
+
);
diff --git a/apps/evm/src/components/LoginButton/LoginButton.tsx b/apps/evm/src/components/LoginButton/LoginButton.tsx
index de2f70605..26d25da57 100644
--- a/apps/evm/src/components/LoginButton/LoginButton.tsx
+++ b/apps/evm/src/components/LoginButton/LoginButton.tsx
@@ -1,42 +1,40 @@
-import { ChainId } from '@gobob/chains';
-import { Button, ButtonProps, toast } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
+import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
+import { Button, ButtonProps } from '@gobob/ui';
import { mergeProps } from '@react-aria/utils';
-import { useAccount, useSwitchChain } from 'wagmi';
+import { useState } from 'react';
+import { useAccount, useAccountEffect } from 'wagmi';
-import { useConnectModal } from '@/connect-ui';
-import { L1_CHAIN, L2_CHAIN, isValidChain } from '@/constants';
-import { useLogin } from '@/hooks';
+import { useGetUser, useLogin } from '@/hooks';
type LoginButtonProps = ButtonProps;
const LoginButton = (props: LoginButtonProps): JSX.Element => {
- const { switchChainAsync } = useSwitchChain();
- const { open } = useConnectModal();
- const { address, chain } = useAccount();
+ const { address } = useAccount();
+
+ const { setShowAuthFlow, setSelectedTabIndex } = useDynamicContext();
+
+ const [isConnecting, setConnecting] = useState(false);
+
+ useAccountEffect({
+ onConnect: (data) => {
+ if (isConnecting) {
+ login(data.address);
+
+ setConnecting(false);
+ }
+ }
+ });
const { mutate: login, isPending: isLoadingLogin } = useLogin();
const handlePress = async () => {
if (!address) {
- return open({
- onConnectEvm: async ({ address, connector }) => {
- if (!address) return;
- if (!isValidChain((await connector?.getChainId()) as ChainId)) {
- const chain = await connector?.switchChain?.({ chainId: L2_CHAIN });
-
- if (!chain) {
- return toast.error(Something went wrong. Please try connecting your wallet again.);
- }
- }
-
- return login(address);
- }
- });
- }
+ setSelectedTabIndex(1);
+ setShowAuthFlow(true);
+
+ setConnecting(true);
- if (!chain || (chain && !isValidChain(chain?.id))) {
- await switchChainAsync?.({ chainId: L1_CHAIN });
+ return;
}
return login(address);
diff --git a/apps/evm/src/components/SignUpButton/SignUpButton.tsx b/apps/evm/src/components/SignUpButton/SignUpButton.tsx
index 762c11bd5..3aa6af6b1 100644
--- a/apps/evm/src/components/SignUpButton/SignUpButton.tsx
+++ b/apps/evm/src/components/SignUpButton/SignUpButton.tsx
@@ -1,42 +1,40 @@
-import { ChainId } from '@gobob/chains';
-import { Button, ButtonProps, toast } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
+import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
+import { Button, ButtonProps } from '@gobob/ui';
import { mergeProps } from '@react-aria/utils';
-import { useAccount, useSwitchChain } from 'wagmi';
+import { useState } from 'react';
+import { useAccount, useAccountEffect } from 'wagmi';
-import { useConnectModal } from '@/connect-ui';
-import { L2_CHAIN, isValidChain } from '@/constants';
import { useSignUp } from '@/hooks';
type SignUpButtonProps = ButtonProps;
const SignUpButton = (props: SignUpButtonProps): JSX.Element => {
- const { switchChainAsync } = useSwitchChain();
- const { open } = useConnectModal();
- const { address, chain } = useAccount();
+ const { address } = useAccount();
+
+ const { setShowAuthFlow, setSelectedTabIndex } = useDynamicContext();
+
+ const [isConnecting, setConnecting] = useState(false);
const { mutate: signUp, isPending: isSigningUp } = useSignUp();
+ useAccountEffect({
+ onConnect: () => {
+ if (isConnecting) {
+ signUp({});
+
+ setConnecting(false);
+ }
+ }
+ });
+
const handlePress = async () => {
if (!address) {
- return open({
- onConnectEvm: async ({ address, connector }) => {
- if (!address) return;
- if (!isValidChain((await connector?.getChainId()) as ChainId)) {
- const chain = await connector?.switchChain?.({ chainId: L2_CHAIN });
-
- if (!chain) {
- return toast.error(Something went wrong. Please try connecting your wallet again.);
- }
- }
-
- return signUp(address);
- }
- });
- }
+ setSelectedTabIndex(1);
+ setShowAuthFlow(true);
+
+ setConnecting(true);
- if (!chain || (chain && !isValidChain(chain?.id))) {
- await switchChainAsync({ chainId: L2_CHAIN });
+ return;
}
return signUp(address);
diff --git a/apps/evm/src/components/WithdrawModal/WithdrawForm.tsx b/apps/evm/src/components/WithdrawModal/WithdrawForm.tsx
index d24d88927..1b3e53cfe 100644
--- a/apps/evm/src/components/WithdrawModal/WithdrawForm.tsx
+++ b/apps/evm/src/components/WithdrawModal/WithdrawForm.tsx
@@ -10,7 +10,7 @@ import { useMemo } from 'react';
import { isAddressEqual } from 'viem';
import { useAccount, usePublicClient, useWriteContract } from 'wagmi';
-import { AuthButton } from '@/connect-ui';
+import { AuthButton } from '@/components';
import { contracts, ContractType, L1_CHAIN } from '@/constants';
import { useLockedTokens } from '@/hooks';
diff --git a/apps/evm/src/components/index.ts b/apps/evm/src/components/index.ts
index 8d1b42f95..ea7439a5f 100644
--- a/apps/evm/src/components/index.ts
+++ b/apps/evm/src/components/index.ts
@@ -9,3 +9,4 @@ export * from './WithdrawAlert';
export * from './LoginButton';
export * from './SignUpButton';
export * from './SpiceAmount';
+export * from './AuthButton';
diff --git a/apps/evm/src/connect-ui/component/ConnectWallet/ConnectWallet.tsx b/apps/evm/src/connect-ui/component/ConnectWallet/ConnectWallet.tsx
index 098350c09..eb790ddd8 100644
--- a/apps/evm/src/connect-ui/component/ConnectWallet/ConnectWallet.tsx
+++ b/apps/evm/src/connect-ui/component/ConnectWallet/ConnectWallet.tsx
@@ -1,15 +1,14 @@
'use client';
-import { SatsConnector, useAccount as useSatsAccount } from '@gobob/sats-wagmi';
import { Avatar, Button, ButtonProps, Flex, Skeleton, Span } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { chain } from '@react-aria/utils';
import { useIsClient } from 'usehooks-ts';
-import { Connector, useAccount, useConnect } from 'wagmi';
import { Address } from 'viem';
+import { Connector, useAccount, useConnect } from 'wagmi';
+
+import { useDynamicContext, useUserWallets } from '@dynamic-labs/sdk-react-core';
-import { useConnectModal } from '../../providers';
-import { ConnectType } from '../../types';
import { EvmAddressLabel } from '../EvmAddressLabel';
import { WalletIcon } from '../WalletIcon';
@@ -18,25 +17,27 @@ import { StyledWallets } from './ConnectWallet.style';
const Label = ({
address,
isPending,
- btcConnector,
- evmConnector,
- connectType
+ evmConnector
}: {
address?: Address;
isPending?: boolean;
evmConnector?: Connector;
- btcConnector?: SatsConnector;
- connectType: ConnectType;
}) => {
const isClient = useIsClient();
+ const userWallets = useUserWallets();
+
+ const evmWallet = userWallets.find((wallet) => wallet.chain === 'EVM');
+
+ const btcWallet = userWallets.find((wallet) => wallet.chain === 'BTC');
+
if (!isClient) return ;
- if (!evmConnector && !btcConnector) return Connect Wallet;
+ if (!evmWallet && !btcWallet) return Connect Wallet;
if (isPending) return Authorize Wallet;
- if (connectType === 'evm' && address) {
+ if (address) {
return ;
}
@@ -49,12 +50,7 @@ const Label = ({
) : (
))}
- {btcConnector &&
- (btcConnector.icon ? (
-
- ) : (
-
- ))}
+ {btcWallet && }
Wallet
@@ -68,18 +64,16 @@ type ConnectWalletProps = ButtonProps;
const ConnectWallet = ({ onPress, variant = 'outline', ...props }: ConnectWalletProps): JSX.Element => {
const { isPending } = useConnect();
const { connector: evmConnector, address } = useAccount();
- const { connector: btcConnector } = useSatsAccount();
- const { open, type: connectType } = useConnectModal();
+ const { setShowDynamicUserProfile } = useDynamicContext();
return (
-
+ {/*
+ /> */}
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
index 3d035daa5..87d65042f 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
@@ -24,7 +24,8 @@ const StyledSpinnerWrapper = styled.span`
const StyledTransactionList = styled(Flex)`
overflow-y: auto;
- flex: 1 1 auto;
+ position: absolute;
+ inset: 0;
`;
const StyledTransactionListWrapper = styled(Flex)`
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx
index 452226adf..e4336c493 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx
@@ -5,11 +5,11 @@ import { BITCOIN } from '@gobob/tokens';
import { AddornedAsset } from '../AddornedAsset';
-import { StyledTransactionList, StyledTransactionListWrapper } from './ProfileTokenList.style';
+import { StyledTransactionList } from './ProfileTokenList.style';
import { useBalances, useBtcBalance, useTokens } from '@/hooks';
import { calculateAmountUSD } from '@/utils';
-import { ChainLogo } from '@/components/ChainLogo';
+import { ChainLogo } from '@/components';
const ProfileTokenListItem = ({
chainId,
@@ -69,44 +69,42 @@ const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
const ethBalance = ethData && getBalance(ethData.raw.symbol);
return (
-
-
- {ethBalance && ethData && (
-
- )}
+
+ {ethBalance && ethData && (
-
-
- Tokens
-
-
- {list?.map((item) => (
-
- ))}
-
+ )}
+
+
+
+ Tokens
+
+
+ {list?.map((item) => (
+
+ ))}
-
-
+
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx
new file mode 100644
index 000000000..3e0907038
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx
@@ -0,0 +1,19 @@
+import { P } from '@gobob/ui';
+import styled from 'styled-components';
+
+import { AuthButton } from '@/components';
+
+const StyledTimePill = styled(P)`
+ padding: ${({ theme }) => `${theme.spacing('xs')} ${theme.spacing('lg')}`};
+ border-radius: ${({ theme }) => theme.rounded('full')};
+ background-color: ${({ theme }) => theme.color('grey-400')};
+ display: flex;
+ align-items: center;
+ gap: ${({ theme }) => theme.spacing('xs')};
+`;
+
+const StyledStatusActionButton = styled(AuthButton)`
+ height: ${({ theme }) => theme.spacing('4xl')};
+`;
+
+export { StyledStatusActionButton, StyledTimePill };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx
new file mode 100644
index 000000000..81bd1c230
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx
@@ -0,0 +1,29 @@
+import { FlexProps } from '@gobob/ui';
+
+import { DepositStatus } from './DepositStatus';
+import { WithdrawStatus } from './WithdrawStatus';
+
+import { BridgeTransaction, TransactionDirection } from '@/types';
+
+type Props = { data: BridgeTransaction; isExpanded: boolean; onProveSuccess?: () => void; onRelaySuccess?: () => void };
+
+type InheritAttrs = Omit;
+
+type BridgeStatusProps = Props & InheritAttrs;
+
+const BridgeStatus = ({ data, isExpanded, onProveSuccess, onRelaySuccess }: BridgeStatusProps): JSX.Element => {
+ if (data.direction === TransactionDirection.L1_TO_L2) {
+ return ;
+ }
+
+ return (
+
+ );
+};
+
+export { BridgeStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx
new file mode 100644
index 000000000..0b9555393
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx
@@ -0,0 +1,247 @@
+import { t } from '@lingui/macro';
+import { useLingui } from '@lingui/react';
+import { Address } from 'viem';
+
+import { StatusChip } from '../StatusChip';
+
+import {
+ BridgeSteps,
+ BridgeStepStatus,
+ BridgeTransaction,
+ BridgeTransactionStatus,
+ TransactionDirection
+} from '@/types';
+import { chainL1, chainL2 } from '@/constants';
+
+const getOngoingBridgeStep = (status: BridgeTransactionStatus, direction: TransactionDirection): BridgeSteps => {
+ switch (status) {
+ case BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE:
+ return 'deposit';
+ default:
+ case BridgeTransactionStatus.READY_FOR_RELAY:
+ return 'relay';
+ case BridgeTransactionStatus.RELAYED:
+ return direction === TransactionDirection.L1_TO_L2 ? 'l2-confirmation' : 'l1-confirmation';
+ case BridgeTransactionStatus.READY_TO_PROVE:
+ return 'prove';
+ case BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED:
+ return 'state-root-published';
+ case BridgeTransactionStatus.IN_CHALLENGE_PERIOD:
+ return 'challenge-period';
+ }
+};
+
+const getLabel = (stage: BridgeSteps, status: BridgeStepStatus, isActing?: boolean, isActionSuccessful?: boolean) => {
+ switch (stage) {
+ case 'deposit': {
+ switch (status) {
+ case 'idle':
+ return 'Deposit';
+ case 'ongoing':
+ return 'Depositing...';
+ default:
+ case 'complete':
+ return 'Deposited';
+ }
+ }
+ case 'l2-confirmation': {
+ return 'L2 confirmation';
+ }
+ case 'withdraw': {
+ switch (status) {
+ case 'idle':
+ return 'Withdraw';
+ case 'ongoing':
+ return 'Withdrawing...';
+ default:
+ case 'complete':
+ return 'Withdrawn';
+ }
+ }
+ case 'state-root-published': {
+ switch (status) {
+ case 'idle':
+ return 'State root publishment';
+ case 'ongoing':
+ return 'Waiting for state root';
+ default:
+ case 'complete':
+ return 'State root published';
+ }
+ }
+ case 'prove': {
+ switch (status) {
+ case 'idle':
+ return 'Prove';
+ case 'ongoing':
+ return isActionSuccessful ? 'Proved' : isActing ? 'Proving...' : 'Ready to prove...';
+ default:
+ case 'complete':
+ return 'Proved';
+ }
+ }
+ case 'challenge-period': {
+ switch (status) {
+ case 'idle':
+ return 'Challenge period';
+ case 'ongoing':
+ return 'Challenge period';
+ default:
+ case 'complete':
+ return 'Challenge period';
+ }
+ }
+ case 'relay': {
+ switch (status) {
+ case 'idle':
+ return 'Relay';
+ case 'ongoing':
+ return isActing ? 'Relaying...' : 'Ready to relay...';
+ default:
+ case 'complete':
+ return 'Relayed';
+ }
+ }
+ case 'l1-confirmation': {
+ switch (status) {
+ case 'idle':
+ return 'Finalized';
+ case 'ongoing':
+ return 'Finalizing...';
+ default:
+ case 'complete':
+ return 'Finalized';
+ }
+ }
+ }
+};
+
+const withdrawOrder = {
+ [BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED]: 1,
+ [BridgeTransactionStatus.READY_TO_PROVE]: 2,
+ [BridgeTransactionStatus.IN_CHALLENGE_PERIOD]: 3,
+ [BridgeTransactionStatus.READY_FOR_RELAY]: 4,
+ [BridgeTransactionStatus.RELAYED]: 5,
+ [BridgeTransactionStatus.FAILED_L1_TO_L2_MESSAGE]: -1,
+ [BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE]: -1
+} as const;
+
+const getBridgeStepStatus = (step: number, currentStep: number) => {
+ if (currentStep < step) {
+ return 'idle';
+ } else if (currentStep === step) {
+ return 'ongoing';
+ } else {
+ return 'complete';
+ }
+};
+
+const getStatus = (
+ step: BridgeSteps,
+ status: BridgeTransactionStatus | null,
+ direction: TransactionDirection
+): BridgeStepStatus => {
+ if (!status) return 'idle';
+
+ if (direction === TransactionDirection.L1_TO_L2) {
+ switch (step) {
+ case 'deposit': {
+ return status === BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE ? 'ongoing' : 'complete';
+ }
+ case 'l2-confirmation': {
+ switch (status) {
+ case BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE:
+ return 'idle';
+ case BridgeTransactionStatus.RELAYED:
+ return 'complete';
+ case BridgeTransactionStatus.FAILED_L1_TO_L2_MESSAGE:
+ return 'failed';
+
+ default:
+ return 'ongoing';
+ }
+ }
+ }
+ }
+
+ const currentStep = withdrawOrder[status];
+
+ switch (step) {
+ case 'withdraw': {
+ return 'complete';
+ }
+ case 'state-root-published': {
+ const step = withdrawOrder[BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED];
+
+ return getBridgeStepStatus(step, currentStep);
+ }
+ case 'prove': {
+ const step = withdrawOrder[BridgeTransactionStatus.READY_TO_PROVE];
+
+ return getBridgeStepStatus(step, currentStep);
+ }
+ case 'challenge-period': {
+ const step = withdrawOrder[BridgeTransactionStatus.IN_CHALLENGE_PERIOD];
+
+ return getBridgeStepStatus(step, currentStep);
+ }
+ case 'l1-confirmation':
+ case 'relay': {
+ const step = withdrawOrder[BridgeTransactionStatus.READY_FOR_RELAY];
+
+ return getBridgeStepStatus(step, currentStep);
+ }
+ }
+
+ return 'complete';
+};
+
+const getStepUrl = (
+ step: BridgeSteps,
+ transactionHash: Address,
+ l1TransactionHash?: Address,
+ l2TransactionHash?: Address
+) => {
+ switch (step) {
+ case 'deposit': {
+ return `${chainL1.blockExplorers?.default.url}/tx/${transactionHash}`;
+ }
+ case 'l1-confirmation': {
+ return l1TransactionHash ? `${chainL1.blockExplorers?.default.url}/tx/${l1TransactionHash}` : undefined;
+ }
+ case 'withdraw': {
+ return `${chainL2.blockExplorers?.default.url}/tx/${transactionHash}`;
+ }
+ case 'l2-confirmation': {
+ return l2TransactionHash ? `${chainL2.blockExplorers?.default.url}/tx/${l2TransactionHash}` : undefined;
+ }
+ default:
+ return undefined;
+ }
+};
+
+type BridgeStepProps = {
+ isActing?: boolean;
+ isActionSuccessful?: boolean;
+ step?: BridgeSteps;
+ data: BridgeTransaction;
+};
+
+const BridgeStep = ({ data, isActing, isActionSuccessful, step }: BridgeStepProps): JSX.Element => {
+ const { i18n } = useLingui();
+ const { status: messageStatus, l1Receipt, l2Receipt, direction, transactionHash } = data;
+
+ if (step === undefined) {
+ return ;
+ }
+
+ const href = getStepUrl(step, transactionHash, l1Receipt?.transactionHash, l2Receipt?.transactionHash);
+
+ const status = getStatus(step, messageStatus, direction);
+
+ const label = getLabel(step, status, isActing, isActionSuccessful);
+
+ return ;
+};
+
+export { BridgeStep, getOngoingBridgeStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx
new file mode 100644
index 000000000..aa9cdad8c
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx
@@ -0,0 +1,28 @@
+import { Flex, FlexProps } from '@gobob/ui';
+
+import { BridgeStep, getOngoingBridgeStep } from './BridgeStep';
+
+import { BridgeTransaction } from '@/types';
+
+type Props = { data: BridgeTransaction; isExpanded: boolean };
+
+type InheritAttrs = Omit;
+
+type DepositStatusProps = Props & InheritAttrs;
+
+const DepositStatus = ({ data, isExpanded }: DepositStatusProps): JSX.Element => {
+ if (!isExpanded) {
+ const step = data.status ? getOngoingBridgeStep(data.status, data.direction) : undefined;
+
+ return ;
+ }
+
+ return (
+
+
+
+
+ );
+};
+
+export { DepositStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx
new file mode 100644
index 000000000..102529137
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx
@@ -0,0 +1,47 @@
+import { Flex, FlexProps } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
+
+import { StyledStatusActionButton } from './BridgeStatus.style';
+import { BridgeStep } from './BridgeStep';
+
+import { BridgeTransaction } from '@/types';
+import { BridgeSteps, BridgeTransactionStatus } from '@/types';
+import { L1_CHAIN } from '@/constants';
+
+type Props = {
+ data: BridgeTransaction;
+ currentStep?: BridgeSteps;
+ isProving?: boolean;
+ isProveSuccessful: boolean;
+ onPressProve?: () => void;
+};
+
+type InheritAttrs = Omit;
+
+type ProveStepProps = Props & InheritAttrs;
+
+const ProveStep = ({ data, currentStep, isProving, isProveSuccessful, onPressProve }: ProveStepProps): JSX.Element => {
+ const isWaitingProve =
+ currentStep === 'prove' && data.status === BridgeTransactionStatus.READY_TO_PROVE && !isProveSuccessful;
+
+ return (
+
+
+ {isWaitingProve && (
+
+ Prove
+
+ )}
+
+ );
+};
+
+export { ProveStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx
new file mode 100644
index 000000000..11839ffa2
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx
@@ -0,0 +1,52 @@
+import { Flex, FlexProps } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
+
+import { StyledStatusActionButton } from './BridgeStatus.style';
+import { BridgeStep } from './BridgeStep';
+
+import { L1_CHAIN } from '@/constants';
+import { BridgeSteps, BridgeTransaction, BridgeTransactionStatus } from '@/types';
+
+type Props = {
+ data: BridgeTransaction;
+ currentStep?: BridgeSteps;
+ isRelaying?: boolean;
+ isRelaySuccessful: boolean;
+ onPressFinalize?: () => void;
+};
+
+type InheritAttrs = Omit;
+
+type RelayStepProps = Props & InheritAttrs;
+
+const RelayStep = ({
+ data,
+ currentStep,
+ isRelaySuccessful,
+ isRelaying,
+ onPressFinalize
+}: RelayStepProps): JSX.Element => {
+ const isWaitingRelay =
+ currentStep === 'relay' && data.status === BridgeTransactionStatus.READY_FOR_RELAY && !isRelaySuccessful;
+
+ return (
+
+
+ {isWaitingRelay && (
+
+ Finalize
+
+ )}
+
+ );
+};
+
+export { RelayStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx
new file mode 100644
index 000000000..06ccd6366
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx
@@ -0,0 +1,56 @@
+import { Clock, Flex, FlexProps } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
+import { formatDistanceToNow, isFuture } from 'date-fns';
+import { ReactNode, useMemo } from 'react';
+
+import { StyledTimePill } from './BridgeStatus.style';
+import { BridgeStep } from './BridgeStep';
+
+import { BridgeSteps, BridgeTransaction } from '@/types';
+
+const TimeLabel = ({ label }: { label: ReactNode }) => (
+
+
+ {label}
+
+);
+
+type Props = {
+ data: BridgeTransaction;
+ step: Extract;
+ currentStep?: BridgeSteps;
+};
+
+type InheritAttrs = Omit;
+
+type TimeStepProps = Props & InheritAttrs;
+
+const TimeStep = ({ step, data, currentStep }: TimeStepProps): JSX.Element => {
+ const timeLabel = useMemo(() => {
+ // should only show step if it is not a complete step
+ const showTime =
+ (step === 'challenge-period'
+ ? currentStep !== 'l1-confirmation' && currentStep !== 'relay'
+ : currentStep === 'l2-confirmation' || currentStep === 'state-root-published') ||
+ // when the current step is challenge period or state root, we should only show is the date is in the future
+ (currentStep === step && data.statusEndDate && isFuture(data.statusEndDate));
+
+ if (!showTime) return undefined;
+
+ // show default duration estimate if step is still incomplete
+ if (currentStep !== step || !data.statusEndDate) {
+ return step === 'challenge-period' ? 7 days : 2 hours;
+ }
+
+ return {formatDistanceToNow(data.statusEndDate)} remaining;
+ }, [step, currentStep, data.statusEndDate]);
+
+ return (
+
+
+ {timeLabel && }
+
+ );
+};
+
+export { TimeStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx
new file mode 100644
index 000000000..0beff7537
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx
@@ -0,0 +1,169 @@
+'use client';
+
+import { Flex, FlexProps, toast } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
+import * as Sentry from '@sentry/nextjs';
+import { useMutation } from '@tanstack/react-query';
+import { useMemo } from 'react';
+import { getWithdrawals } from 'viem/op-stack';
+import { useAccount } from 'wagmi';
+
+import { BridgeStep, getOngoingBridgeStep } from './BridgeStep';
+import { ProveStep } from './ProveStep';
+import { RelayStep } from './RelayStep';
+import { TimeStep } from './TimeStep';
+
+import { BridgeTransaction } from '@/types';
+import { usePublicClientL1, usePublicClientL2, useWalletClientL1, useWalletClientL2 } from '@/hooks';
+import { bridgeKeys } from '@/lib/react-query';
+
+type Props = { data: BridgeTransaction; isExpanded: boolean; onProveSuccess?: () => void; onRelaySuccess?: () => void };
+
+type InheritAttrs = Omit;
+
+type WithdrawStatusProps = Props & InheritAttrs;
+
+const WithdrawStatus = ({ data, isExpanded, onProveSuccess, onRelaySuccess }: WithdrawStatusProps): JSX.Element => {
+ const publicClientL1 = usePublicClientL1();
+ const publicClientL2 = usePublicClientL2();
+
+ const walletClientL1 = useWalletClientL1();
+ const walletClientL2 = useWalletClientL2();
+
+ const { address } = useAccount();
+
+ const proveMutation = useMutation({
+ mutationKey: bridgeKeys.proveTransaction(address, data.transactionHash),
+ mutationFn: async () => {
+ const receipt =
+ data.l2Receipt ||
+ (await publicClientL2.getTransactionReceipt({
+ hash: data.transactionHash
+ }));
+
+ const { output, withdrawal } = await publicClientL1.waitToProve({
+ receipt,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ targetChain: walletClientL2.chain as any
+ });
+
+ const args = await publicClientL2.buildProveWithdrawal({
+ output,
+ withdrawal
+ });
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const hash = await walletClientL1?.proveWithdrawal(args as any);
+
+ return { hash };
+ },
+ onSuccess: (data) => {
+ toast.success(Successfully submitted ${data?.hash} proof);
+ onProveSuccess?.();
+ },
+ onError: (e) => {
+ Sentry.captureException(e);
+ // eslint-disable-next-line no-console
+ console.log('Prove: ', e);
+ toast.error(Failed to submit proof.);
+ }
+ });
+
+ const relayMutation = useMutation({
+ mutationKey: bridgeKeys.relayTransaction(address, data.transactionHash),
+ mutationFn: async () => {
+ if (!address) return;
+
+ const receiptL2 =
+ data.l2Receipt ||
+ (await publicClientL2.getTransactionReceipt({
+ hash: data.transactionHash
+ }));
+
+ const [withdrawal] = getWithdrawals(receiptL2);
+
+ const hash = await walletClientL1.finalizeWithdrawal({
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ targetChain: walletClientL2.chain as any,
+ withdrawal: withdrawal!,
+ account: address
+ });
+
+ await publicClientL1.waitForTransactionReceipt({
+ hash
+ });
+
+ return hash;
+ },
+ onSuccess: () => {
+ toast.success(Successfully finalized transaction);
+ onRelaySuccess?.();
+ },
+ onError: (e) => {
+ Sentry.captureException(e);
+ // eslint-disable-next-line no-console
+ console.log('Finalize: ', e);
+ toast.error(Failed to finalize.);
+ }
+ });
+
+ const currentStep = useMemo(
+ () => (data.status ? getOngoingBridgeStep(data.status, data.direction) : undefined),
+ [data]
+ );
+
+ if (!isExpanded) {
+ switch (currentStep) {
+ case 'state-root-published':
+ return ;
+ case 'prove':
+ return (
+
+ );
+ case 'relay':
+ return (
+
+ );
+ case 'challenge-period':
+ return ;
+ default:
+ return ;
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export { WithdrawStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx
new file mode 100644
index 000000000..efd4739d4
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx
@@ -0,0 +1 @@
+export { BridgeStatus } from './BridgeStatus';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
index 9d71c6b16..6916f63fc 100644
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
@@ -2,10 +2,10 @@ import { Flex, FlexProps } from '@gobob/ui';
import { useState } from 'react';
import { TransactionDetails } from './TransactionDetails';
+import { BridgeStatus } from './BridgeStatus';
import { L1_CHAIN, L2_CHAIN } from '@/constants';
import { BridgeTransaction, TransactionDirection } from '@/types';
-import { BridgeStatus } from '@/app/[lang]/(bridge)/components/BridgeStatus';
type Props = { data: BridgeTransaction; onProveSuccess?: () => void; onRelaySuccess?: () => void };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx
new file mode 100644
index 000000000..3339d0a6f
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx
@@ -0,0 +1,26 @@
+import { Flex, FlexProps } from '@gobob/ui';
+
+import { GatewayStep } from './GatewayStep';
+
+import { GatewayTransaction } from '@/types';
+
+type Props = { data: GatewayTransaction; isExpanded: boolean };
+
+type InheritAttrs = Omit;
+
+type GatewayStatusProps = Props & InheritAttrs;
+
+const GatewayStatus = ({ data, isExpanded }: GatewayStatusProps): JSX.Element => {
+ if (!isExpanded) {
+ return ;
+ }
+
+ return (
+
+
+
+
+ );
+};
+
+export { GatewayStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx
new file mode 100644
index 000000000..895c80087
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx
@@ -0,0 +1,60 @@
+import { StatusChip } from '../StatusChip';
+
+import { GatewayTransaction } from '@/types';
+import { mempoolUrl } from '@/constants';
+import { GatewaySteps } from '@/types';
+
+const getLabel = (status: GatewaySteps, confirmations: number, totalConfirmations: number) => {
+ switch (status) {
+ case 'btc-confirmation':
+ return confirmations <= totalConfirmations
+ ? `BTC confirmations (${confirmations}/${totalConfirmations})`
+ : 'BTC confirmations';
+ case 'l2-processing':
+ case 'l2-confirmation':
+ return 'L2 confirmation';
+ case 'l2-incomplete':
+ return 'L2 incomplete';
+ }
+};
+
+const getStatus = (data: GatewayTransaction, step: GatewaySteps) => {
+ switch (step) {
+ case 'btc-confirmation':
+ return data.status === 'btc-confirmation' ? 'ongoing' : 'complete';
+ case 'l2-processing':
+ switch (data.status) {
+ case 'btc-confirmation':
+ return 'idle';
+ case 'l2-processing':
+ return 'ongoing';
+ case 'l2-confirmation':
+ return 'complete';
+ case 'l2-incomplete':
+ return 'failed';
+ }
+ case 'l2-incomplete':
+ return data.status === 'l2-incomplete' ? 'failed' : 'idle';
+ case 'l2-confirmation':
+ return data.status === 'l2-confirmation' ? 'complete' : 'idle';
+ }
+};
+
+type GatewayStepProps = {
+ data: GatewayTransaction;
+ step?: GatewaySteps;
+};
+
+const GatewayStep = ({ step: stepProp, data }: GatewayStepProps): JSX.Element => {
+ const step = stepProp || data.status;
+
+ const label = getLabel(step, data.confirmations, data.totalConfirmations);
+
+ const href = step === 'btc-confirmation' ? `${mempoolUrl}/tx/${data.btcTxId}` : undefined;
+
+ const status = getStatus(data, step);
+
+ return ;
+};
+
+export { GatewayStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx
new file mode 100644
index 000000000..e3752a534
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx
@@ -0,0 +1 @@
+export { GatewayStatus } from './GatewayStatus';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
index 89228b519..5e766c4dc 100644
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
@@ -2,10 +2,10 @@ import { Flex, FlexProps } from '@gobob/ui';
import { useState } from 'react';
import { TransactionDetails } from './TransactionDetails';
+import { GatewayStatus } from './GatewayStatus';
import { L2_CHAIN } from '@/constants';
import { GatewayTransaction, TransactionDirection } from '@/types';
-import { GatewayStatus } from '@/app/[lang]/(bridge)/components/GatewayStatus';
type Props = { data: GatewayTransaction };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx
new file mode 100644
index 000000000..47d9cc56b
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx
@@ -0,0 +1,15 @@
+import { Icon, IconProps } from '@gobob/ui';
+import { forwardRef } from 'react';
+
+const Circle = forwardRef((props, ref) => (
+
+
+
+));
+
+Circle.displayName = 'Circle';
+
+export { Circle };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx
new file mode 100644
index 000000000..0af33f5d2
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx
@@ -0,0 +1,22 @@
+import { Icon, IconProps } from '@gobob/ui';
+import { forwardRef } from 'react';
+
+const CircleCheck = forwardRef((props, ref) => (
+
+
+
+
+
+
+
+
+
+
+));
+
+CircleCheck.displayName = 'CircleCheck';
+
+export { CircleCheck };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx
new file mode 100644
index 000000000..71e8ed03a
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx
@@ -0,0 +1,22 @@
+import { forwardRef } from 'react';
+import { Icon, IconProps } from '@gobob/ui';
+
+const CircleX = forwardRef((props, ref) => (
+
+
+
+
+
+
+
+
+
+
+));
+
+CircleX.displayName = 'CircleX';
+
+export { CircleX };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx
new file mode 100644
index 000000000..b35cc0b48
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx
@@ -0,0 +1,42 @@
+import { Link, Spinner } from '@gobob/ui';
+import styled from 'styled-components';
+
+import { BridgeStepStatus } from '@/types';
+
+type StyledChipProps = {
+ $status: BridgeStepStatus;
+};
+
+const StyledChip = styled(Link)`
+ display: inline-flex;
+ width: min-content;
+ white-space: nowrap;
+ gap: ${({ theme }) => theme.spacing('xs')};
+ align-items: center;
+ padding: ${({ theme }) => `${theme.spacing('xs')} ${theme.spacing('lg')}`};
+ border-radius: ${({ theme }) => theme.rounded('full')};
+ background-color: ${({ theme, $status }) =>
+ $status === 'complete'
+ ? theme.color('grey-600')
+ : $status === 'ongoing'
+ ? theme.color('green-300')
+ : $status === 'failed'
+ ? theme.color('red-800')
+ : theme.color('grey-600')};
+ opacity: ${({ $status }) => ($status === 'idle' ? '.7' : '1')};
+ color: ${({ $status, theme }) => ($status === 'ongoing' ? theme.color('dark') : theme.color('light'))};
+
+ &,
+ &:hover {
+ text-decoration: none;
+ }
+`;
+
+const StyledLoadingSpinner = styled(Spinner)`
+ border-bottom-color: transparent;
+ border-left-color: ${({ theme }) => theme.color('dark')};
+ border-top-color: ${({ theme }) => theme.color('dark')};
+ border-right-color: ${({ theme }) => theme.color('dark')};
+`;
+
+export { StyledLoadingSpinner, StyledChip };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx
new file mode 100644
index 000000000..b7280c6f9
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx
@@ -0,0 +1,49 @@
+import { ArrowTopRightOnSquare, Span } from '@gobob/ui';
+
+import { StyledLoadingSpinner, StyledChip } from './StatusChip.style';
+import { Circle } from './Circle';
+import { CircleCheck } from './CircleCheck';
+import { CircleX } from './CircleX';
+
+import { BridgeStepStatus } from '@/types';
+
+const getPillIcon = (status: BridgeStepStatus) => {
+ switch (status) {
+ case 'idle':
+ return ;
+ case 'complete':
+ return ;
+ case 'failed':
+ return ;
+ default:
+ case 'ongoing':
+ return ;
+ }
+};
+
+type StatusChipProps = {
+ href?: string;
+ label: string;
+ status: BridgeStepStatus;
+};
+
+const StatusChip = ({ label, status, href }: StatusChipProps): JSX.Element => {
+ const icon = getPillIcon(status);
+
+ return (
+
+ {icon}
+ {label}
+ {href && }
+
+ );
+};
+
+export { StatusChip };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx
new file mode 100644
index 000000000..466a85edb
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx
@@ -0,0 +1 @@
+export { StatusChip } from './StatusChip';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
index 5bc9742c5..31d20a87a 100644
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
@@ -31,6 +31,7 @@ const TransactionList = ({
flex={1}
gap='xl'
justifyContent={isInitialLoading || !hasData ? 'center' : undefined}
+ paddingX='md'
paddingY='xl'
>
{!isClient || isInitialLoading ? (
diff --git a/apps/evm/src/locales/en.po b/apps/evm/src/locales/en.po
index ccbe6d520..77191baad 100644
--- a/apps/evm/src/locales/en.po
+++ b/apps/evm/src/locales/en.po
@@ -23,10 +23,12 @@ msgstr ", due to the challenge period"
#~ msgstr "{0}"
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:49
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:56
msgid "{0} ago"
msgstr "{0} ago"
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:47
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:45
msgid "{0} remaining"
msgstr "{0} remaining"
@@ -68,6 +70,7 @@ msgid "<0>Stake your BTC with 1-click0> and receive BTC LSTs on BOB."
msgstr "<0>Stake your BTC with 1-click0> and receive BTC LSTs on BOB."
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:44
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:42
msgid "2 hours"
msgstr "2 hours"
@@ -81,14 +84,19 @@ msgid "404 Error"
msgstr "404 Error"
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:44
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:42
msgid "7 days"
msgstr "7 days"
-#: src/components/Layout/Header.tsx:105
+#: src/components/Layout/Header.tsx:106
#: src/components/Layout/Sidebar.tsx:66
msgid "About"
msgstr "About"
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:112
+msgid "Activity"
+msgstr "Activity"
+
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayFeeSettingsModal.tsx:106
msgid "Adjusting the fee rate affects how quickly your Bitcoin transaction is confirmed. Lower fees may lead to significant delays in confirmation time."
msgstr "Adjusting the fee rate affects how quickly your Bitcoin transaction is confirmed. Lower fees may lead to significant delays in confirmation time."
@@ -111,16 +119,16 @@ msgid "Amount"
msgstr "Amount"
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:26
-msgid "An Exclusive Bitcoin Staking and DeFi Campaign"
-msgstr "An Exclusive Bitcoin Staking and DeFi Campaign"
+#~ msgid "An Exclusive Bitcoin Staking and DeFi Campaign"
+#~ msgstr "An Exclusive Bitcoin Staking and DeFi Campaign"
#: src/components/BannerCarousel/BinanceCampaignBanner.tsx:25
#~ msgid "An exclusive quest campaign."
#~ msgstr "An exclusive quest campaign."
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:260
-msgid "and that you have read and understood our"
-msgstr "and that you have read and understood our"
+#~ msgid "and that you have read and understood our"
+#~ msgstr "and that you have read and understood our"
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayFeeSettingsModal.tsx:180
msgid "Apply"
@@ -131,7 +139,7 @@ msgid "Approve"
msgstr "Approve"
#: src/app/[lang]/apps/page.tsx:14
-#: src/components/Layout/Header.tsx:70
+#: src/components/Layout/Header.tsx:71
#: src/components/Layout/Sidebar.tsx:45
msgid "Apps"
msgstr "Apps"
@@ -166,8 +174,8 @@ msgid "Audited by"
msgstr "Audited by"
#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:37
-msgid "Authorize Wallet"
-msgstr "Authorize Wallet"
+#~ msgid "Authorize Wallet"
+#~ msgstr "Authorize Wallet"
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:41
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:108
@@ -205,8 +213,8 @@ msgid "BOB Bridge"
msgstr "BOB Bridge"
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:22
-msgid "BOB Ecosystem on OKX Cryptopedia"
-msgstr "BOB Ecosystem on OKX Cryptopedia"
+#~ msgid "BOB Ecosystem on OKX Cryptopedia"
+#~ msgstr "BOB Ecosystem on OKX Cryptopedia"
#: src/app/[lang]/(bridge)/components/BannerCarousel/FusionBanner.tsx:22
#: src/app/[lang]/fusion/Fusion.tsx:92
@@ -222,8 +230,8 @@ msgstr "BOB Gateway allows you to swap BTC on Bitcoin to ETH on BOB"
#~ msgstr "BOB Gateway allows you to swap BTC on Bitcoin to ETH on BOB."
#: src/app/[lang]/(bridge)/components/BannerCarousel/OnrampBanner.tsx:17
-msgid "BOB Gateway is live!"
-msgstr "BOB Gateway is live!"
+#~ msgid "BOB Gateway is live!"
+#~ msgstr "BOB Gateway is live!"
#: src/app/[lang]/layout.tsx:33
#: src/app/[lang]/layout.tsx:52
@@ -238,9 +246,9 @@ msgstr "BOB TVL Progress"
#~ msgid "BOB Wallet"
#~ msgstr "BOB Wallet"
-#: src/app/[lang]/(bridge)/bridge/page.tsx:14
+#: src/app/[lang]/(bridge)/bridge/page.tsx:13
#: src/app/[lang]/page.tsx:15
-#: src/components/Layout/Header.tsx:67
+#: src/components/Layout/Header.tsx:68
#: src/components/Layout/Sidebar.tsx:42
msgid "Bridge"
msgstr "Bridge"
@@ -288,8 +296,8 @@ msgid "BTC LST Lending"
msgstr "BTC LST Lending"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:252
-msgid "By clicking ‘Connect’ you acknowledge and agree to the"
-msgstr "By clicking ‘Connect’ you acknowledge and agree to the"
+#~ msgid "By clicking ‘Connect’ you acknowledge and agree to the"
+#~ msgstr "By clicking ‘Connect’ you acknowledge and agree to the"
#: src/app/[lang]/wallet/components/ReceiveTokenModal/ReceiveTokenModal.tsx:79
#: src/app/[lang]/wallet/components/SendTokenModal/SendTokenModal.tsx:255
@@ -314,8 +322,8 @@ msgstr "Checking Allowance"
#: src/connect-ui/component/ConnectModal/BtcWalletList.tsx:39
#: src/connect-ui/component/ConnectModal/EvmWalletList.tsx:76
-msgid "choose available wallets"
-msgstr "choose available wallets"
+#~ msgid "choose available wallets"
+#~ msgstr "choose available wallets"
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:179
msgid "Chose any of the existing liquid staking provider to mint your BTC LST."
@@ -367,8 +375,7 @@ msgstr "Complete a variety of on- and off-chain quests using Intract and the BOB
msgid "Congratulations you won!<0/>Take a screenshot to share with your friends!"
msgstr "Congratulations you won!<0/>Take a screenshot to share with your friends!"
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:94
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:107
+#: src/components/AuthButton/AuthButton.tsx:97
msgid "Connect BTC Wallet"
msgstr "Connect BTC Wallet"
@@ -377,26 +384,26 @@ msgid "Connect BTC wallet to access fee rate settings."
msgstr "Connect BTC wallet to access fee rate settings."
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:135
-msgid "Connect request is already pending"
-msgstr "Connect request is already pending"
+#~ msgid "Connect request is already pending"
+#~ msgstr "Connect request is already pending"
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:63
-#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:214
-#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:35
+#: src/components/AuthButton/AuthButton.tsx:64
+#: src/components/ConnectButton/ConnectButton.tsx:69
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:56
msgid "Connect Wallet"
msgstr "Connect Wallet"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:296
-msgid "Connect your Bitcoin Wallet (Optional)"
-msgstr "Connect your Bitcoin Wallet (Optional)"
+#~ msgid "Connect your Bitcoin Wallet (Optional)"
+#~ msgstr "Connect your Bitcoin Wallet (Optional)"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:281
-msgid "Connect your EVM Wallet (Mandatory)"
-msgstr "Connect your EVM Wallet (Mandatory)"
+#~ msgid "Connect your EVM Wallet (Mandatory)"
+#~ msgstr "Connect your EVM Wallet (Mandatory)"
#: src/connect-ui/component/ConnectModal/ConnectedWalletSection.tsx:37
-msgid "Connected with <0>{wallet}0>"
-msgstr "Connected with <0>{wallet}0>"
+#~ msgid "Connected with <0>{wallet}0>"
+#~ msgstr "Connected with <0>{wallet}0>"
#: src/app/[lang]/wallet/components/ReceiveTokenModal/ReceiveTokenModal.tsx:89
#~ msgid "Copy Address"
@@ -436,6 +443,7 @@ msgstr "Deploy high priority assets into high priority DeFi protocols to maximiz
#: src/app/[lang]/(bridge)/bridge/Bridge.tsx:128
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:38
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:38
msgid "Deposit"
msgstr "Deposit"
@@ -455,7 +463,7 @@ msgstr "Deposit your BTC LSTs into <0>Satoshi Protocol0> to mint satUSD and de
msgid "Deposit your BTC LSTs into <0>Satoshi Protocol0> to mint satUSD."
msgstr "Deposit your BTC LSTs into <0>Satoshi Protocol0> to mint satUSD."
-#: src/components/Layout/Header.tsx:102
+#: src/components/Layout/Header.tsx:103
#: src/components/Layout/Sidebar.tsx:63
msgid "Dev"
msgstr "Dev"
@@ -472,7 +480,7 @@ msgstr "DEX Liquidity Provisioning"
msgid "Diamond"
msgstr "Diamond"
-#: src/app/[lang]/nested-providers.tsx:60
+#: src/app/[lang]/nested-providers.tsx:59
msgid "Disconnected"
msgstr "Disconnected"
@@ -548,14 +556,15 @@ msgstr "Estimated within the next block"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:138
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:174
-msgid "Failed to connect to {0}"
-msgstr "Failed to connect to {0}"
+#~ msgid "Failed to connect to {0}"
+#~ msgstr "Failed to connect to {0}"
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:107
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:106
msgid "Failed to finalize."
msgstr "Failed to finalize."
-#: src/app/[lang]/(bridge)/hooks/useGateway.ts:234
+#: src/app/[lang]/(bridge)/hooks/useGateway.ts:235
msgid "Failed to get estimated fee"
msgstr "Failed to get estimated fee"
@@ -564,6 +573,7 @@ msgstr "Failed to get estimated fee"
#~ msgstr "Failed to send {amount} {0}"
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:69
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:68
msgid "Failed to submit proof."
msgstr "Failed to submit proof."
@@ -589,6 +599,7 @@ msgid "Feeling lucky? Try your luck with the daily lottery!<0/>Participate in Fu
msgstr "Feeling lucky? Try your luck with the daily lottery!<0/>Participate in Fusion voting to receive 3 lottery tickets each day."
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionList.tsx:77
+#: src/components/ProfileDrawer/TransactionList/TransactionList.tsx:41
msgid "Fetching bridging operations..."
msgstr "Fetching bridging operations..."
@@ -601,6 +612,7 @@ msgid "Final Leaderboard Rank"
msgstr "Final Leaderboard Rank"
#: src/app/[lang]/(bridge)/components/BridgeStatus/RelayStep.tsx:47
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx:45
msgid "Finalize"
msgstr "Finalize"
@@ -618,7 +630,7 @@ msgid "Follow us on X for updates"
msgstr "Follow us on X for updates"
#: src/app/[lang]/fusion/page.tsx:16
-#: src/components/Layout/Header.tsx:76
+#: src/components/Layout/Header.tsx:77
#: src/components/Layout/Sidebar.tsx:51
msgid "Fusion"
msgstr "Fusion"
@@ -662,14 +674,14 @@ msgstr "Get tickets"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:189
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:203
-msgid "go back"
-msgstr "go back"
+#~ msgid "go back"
+#~ msgstr "go back"
#: src/app/[lang]/404/NotFound.tsx:30
msgid "Go Back"
msgstr "Go Back"
-#: src/app/[lang]/nested-providers.tsx:75
+#: src/app/[lang]/nested-providers.tsx:74
msgid "Got it!"
msgstr "Got it!"
@@ -817,7 +829,7 @@ msgstr "Lending, Restaking, CDP *"
#~ msgid "Liquid Staking"
#~ msgstr "Liquid Staking"
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:51
+#: src/components/AuthButton/AuthButton.tsx:50
msgid "Loading..."
msgstr "Loading..."
@@ -889,7 +901,7 @@ msgstr "Mint satUSD and supply it into a lending market on BOB"
msgid "Multipliers"
msgstr "Multipliers"
-#: src/components/Layout/Header.tsx:108
+#: src/components/Layout/Header.tsx:109
#: src/components/Layout/Sidebar.tsx:54
msgid "Multisig"
msgstr "Multisig"
@@ -922,7 +934,7 @@ msgstr "navigate to Common Prefix audit"
msgid "navigate to discord"
msgstr "navigate to discord"
-#: src/app/[lang]/(bridge)/components/BannerCarousel/BannerCarousel.tsx:90
+#: src/app/[lang]/(bridge)/components/BannerCarousel/BannerCarousel.tsx:61
msgid "navigate to ecosystem section in fusion page"
msgstr "navigate to ecosystem section in fusion page"
@@ -968,6 +980,7 @@ msgstr "new tickets drop in {0}"
#~ msgstr "No assets shown"
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionList.tsx:96
+#: src/components/ProfileDrawer/TransactionList/TransactionList.tsx:56
msgid "No bridging operations found"
msgstr "No bridging operations found"
@@ -996,18 +1009,18 @@ msgid "Not your lucky day... yet!"
msgstr "Not your lucky day... yet!"
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:30
-msgid "OKX Cryptopedia"
-msgstr "OKX Cryptopedia"
+#~ msgid "OKX Cryptopedia"
+#~ msgstr "OKX Cryptopedia"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:246
-msgid "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
-msgstr "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
+#~ msgid "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
+#~ msgstr "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
#: src/app/[lang]/fusion/components/WelcomeBackModal/WelcomeBackModal.tsx:68
msgid "Once complete, your season 3 score will be added to seasons 1 and 2 to calculate your final Spice harvest."
msgstr "Once complete, your season 3 score will be added to seasons 1 and 2 to calculate your final Spice harvest."
-#: src/components/Layout/Header.tsx:55
+#: src/components/Layout/Header.tsx:56
msgid "open drawer"
msgstr "open drawer"
@@ -1029,6 +1042,7 @@ msgid "Output Token"
msgstr "Output Token"
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:62
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:64
msgid "Pending"
msgstr "Pending"
@@ -1073,14 +1087,15 @@ msgid "Preparing..."
msgstr "Preparing..."
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:266
-msgid "Privacy policy"
-msgstr "Privacy policy"
+#~ msgid "Privacy policy"
+#~ msgstr "Privacy policy"
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayTransactionDetails.tsx:121
msgid "Protocol Fee"
msgstr "Protocol Fee"
#: src/app/[lang]/(bridge)/components/BridgeStatus/ProveStep.tsx:41
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx:40
msgid "Prove"
msgstr "Prove"
@@ -1205,12 +1220,12 @@ msgid "Security Review by Bitcoin Layers"
msgstr "Security Review by Bitcoin Layers"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:211
-msgid "Select Bitcoin Wallet"
-msgstr "Select Bitcoin Wallet"
+#~ msgid "Select Bitcoin Wallet"
+#~ msgstr "Select Bitcoin Wallet"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:197
-msgid "Select EVM Wallet"
-msgstr "Select EVM Wallet"
+#~ msgid "Select EVM Wallet"
+#~ msgstr "Select EVM Wallet"
#: src/app/[lang]/(bridge)/components/TransactionDetails/TransactionDetails.tsx:119
msgid "select gas token"
@@ -1262,7 +1277,7 @@ msgstr "Share on X"
msgid "Share this link with a friend and when they sign up, you will receive 15% of their Spice harvest as a bonus, plus 7% of the Spice harvest of anyone they refer"
msgstr "Share this link with a friend and when they sign up, you will receive 15% of their Spice harvest as a bonus, plus 7% of the Spice harvest of anyone they refer"
-#: src/components/Layout/Header.tsx:83
+#: src/components/Layout/Header.tsx:84
msgid "Show secondary navigation"
msgstr "Show secondary navigation"
@@ -1288,8 +1303,8 @@ msgstr "Something went wrong. Please try again later."
#: src/app/[lang]/sign-up/SignUp.tsx:72
#: src/components/LoginButton/LoginButton.tsx:29
#: src/components/SignUpButton/SignUpButton.tsx:29
-msgid "Something went wrong. Please try connecting your wallet again."
-msgstr "Something went wrong. Please try connecting your wallet again."
+#~ msgid "Something went wrong. Please try connecting your wallet again."
+#~ msgstr "Something went wrong. Please try connecting your wallet again."
#: src/app/[lang]/404/NotFound.tsx:23
msgid "Sorry, the page you are looking for doesn't exist or has been moved. Here are some helpful links:"
@@ -1369,7 +1384,7 @@ msgstr "Spice styled background"
#: src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx:97
#: src/app/[lang]/(bridge)/stake/components/StakeTable/StakeTable.tsx:97
#: src/app/[lang]/(bridge)/stake/page.tsx:14
-#: src/components/Layout/Header.tsx:73
+#: src/components/Layout/Header.tsx:74
#: src/components/Layout/Sidebar.tsx:48
msgid "Stake"
msgstr "Stake"
@@ -1441,6 +1456,7 @@ msgid "Strategy"
msgstr "Strategy"
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:100
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:99
msgid "Successfully finalized transaction"
msgstr "Successfully finalized transaction"
@@ -1449,6 +1465,7 @@ msgstr "Successfully finalized transaction"
#~ msgstr "Successfully sent {amount} {0}"
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:62
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:61
msgid "Successfully submitted ${0} proof"
msgstr "Successfully submitted ${0} proof"
@@ -1488,11 +1505,11 @@ msgstr "Supply the newly minted satUSD into a <0>lending protocol on BOB0>."
msgid "Support your favourite BOB apps"
msgstr "Support your favourite BOB apps"
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:84
+#: src/components/AuthButton/AuthButton.tsx:84
msgid "Switch to {capitalizedName}"
msgstr "Switch to {capitalizedName}"
-#: src/components/Layout/Header.tsx:99
+#: src/components/Layout/Header.tsx:100
#: src/components/Layout/Sidebar.tsx:60
msgid "T&Cs"
msgstr "T&Cs"
@@ -1502,8 +1519,8 @@ msgid "Take em home"
msgstr "Take em home"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:258
-msgid "Terms of Service"
-msgstr "Terms of Service"
+#~ msgid "Terms of Service"
+#~ msgstr "Terms of Service"
#: src/components/Logo/Logo.tsx:47
msgid "Testnet"
@@ -1514,8 +1531,8 @@ msgid "Thank you for your understanding and we hope to be able to serve you in a
msgstr "Thank you for your understanding and we hope to be able to serve you in a more decentralized future. The BOB L2 network itself is fully decentralized, cannot be censored and all code is open source."
#: src/app/[lang]/(bridge)/components/BannerCarousel/OnrampBanner.tsx:21
-msgid "The fastest and easiest way to bridge BTC to BOB."
-msgstr "The fastest and easiest way to bridge BTC to BOB."
+#~ msgid "The fastest and easiest way to bridge BTC to BOB."
+#~ msgstr "The fastest and easiest way to bridge BTC to BOB."
#: src/app/[lang]/fusion/components/WelcomeBackModal/WelcomeBackModal.tsx:39
#: src/app/[lang]/fusion/components/WelcomeModal/WelcomeModal.tsx:24
@@ -1691,6 +1708,8 @@ msgstr "Unfortunately, is not possible to bridge to BOB using smart accounts. We
#: src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStep.tsx:230
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:71
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx:235
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:73
msgid "Unknown"
msgstr "Unknown"
@@ -1744,7 +1763,6 @@ msgid "Use your Spice total to support your favourite BOB builders. Winners will
msgstr "Use your Spice total to support your favourite BOB builders. Winners will be announced each week."
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:132
-#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:131
#: src/hooks/useLogin.ts:46
#: src/hooks/useSignUp.ts:49
msgid "User rejected the request"
@@ -1809,7 +1827,7 @@ msgstr "Waiting for approval"
msgid "Waiting for confirmation"
msgstr "Waiting for confirmation"
-#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:60
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:109
msgid "Wallet"
msgstr "Wallet"
@@ -1844,6 +1862,7 @@ msgstr "When you vote, you do not give away any of your harvest. Your Spice tota
#: src/app/[lang]/(bridge)/bridge/Bridge.tsx:131
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:38
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:38
msgid "Withdraw"
msgstr "Withdraw"
@@ -1881,7 +1900,7 @@ msgstr "You can change your votes at any time before the end of the weekly votin
msgid "You Have 0 Tickets"
msgstr "You Have 0 Tickets"
-#: src/app/[lang]/nested-providers.tsx:67
+#: src/app/[lang]/nested-providers.tsx:66
msgid "You have switched your account mid session. Simply switch back the original account and login to have access to your funds again."
msgstr "You have switched your account mid session. Simply switch back the original account and login to have access to your funds again."
@@ -1939,7 +1958,7 @@ msgstr "Your assets will be delivered shortly, with an estimated arrival time of
msgid "Your available balance may differ from your wallet balance due to network fees and available liquidity"
msgstr "Your available balance may differ from your wallet balance due to network fees and available liquidity"
-#: src/app/[lang]/nested-providers.tsx:64
+#: src/app/[lang]/nested-providers.tsx:63
msgid "Your funds are safe!"
msgstr "Your funds are safe!"
diff --git a/apps/evm/src/locales/zh.po b/apps/evm/src/locales/zh.po
index 775bcec86..94c9d93b0 100644
--- a/apps/evm/src/locales/zh.po
+++ b/apps/evm/src/locales/zh.po
@@ -23,10 +23,12 @@ msgstr ""
#~ msgstr ""
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:49
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:56
msgid "{0} ago"
msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:47
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:45
msgid "{0} remaining"
msgstr ""
@@ -68,6 +70,7 @@ msgid "<0>Stake your BTC with 1-click0> and receive BTC LSTs on BOB."
msgstr "<0>一键质押你的BTC0> 并在BOB上接收BTC LSTs。"
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:44
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:42
msgid "2 hours"
msgstr ""
@@ -81,14 +84,19 @@ msgid "404 Error"
msgstr "404 错误"
#: src/app/[lang]/(bridge)/components/BridgeStatus/TimeStep.tsx:44
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx:42
msgid "7 days"
msgstr ""
-#: src/components/Layout/Header.tsx:105
+#: src/components/Layout/Header.tsx:106
#: src/components/Layout/Sidebar.tsx:66
msgid "About"
msgstr "关于"
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:112
+msgid "Activity"
+msgstr ""
+
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayFeeSettingsModal.tsx:106
msgid "Adjusting the fee rate affects how quickly your Bitcoin transaction is confirmed. Lower fees may lead to significant delays in confirmation time."
msgstr ""
@@ -111,16 +119,16 @@ msgid "Amount"
msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:26
-msgid "An Exclusive Bitcoin Staking and DeFi Campaign"
-msgstr ""
+#~ msgid "An Exclusive Bitcoin Staking and DeFi Campaign"
+#~ msgstr ""
#: src/components/BannerCarousel/BinanceCampaignBanner.tsx:25
#~ msgid "An exclusive quest campaign."
#~ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:260
-msgid "and that you have read and understood our"
-msgstr ""
+#~ msgid "and that you have read and understood our"
+#~ msgstr ""
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayFeeSettingsModal.tsx:180
msgid "Apply"
@@ -131,7 +139,7 @@ msgid "Approve"
msgstr "通过"
#: src/app/[lang]/apps/page.tsx:14
-#: src/components/Layout/Header.tsx:70
+#: src/components/Layout/Header.tsx:71
#: src/components/Layout/Sidebar.tsx:45
msgid "Apps"
msgstr ""
@@ -166,8 +174,8 @@ msgid "Audited by"
msgstr "审计"
#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:37
-msgid "Authorize Wallet"
-msgstr ""
+#~ msgid "Authorize Wallet"
+#~ msgstr ""
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:41
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:108
@@ -205,8 +213,8 @@ msgid "BOB Bridge"
msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:22
-msgid "BOB Ecosystem on OKX Cryptopedia"
-msgstr ""
+#~ msgid "BOB Ecosystem on OKX Cryptopedia"
+#~ msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/FusionBanner.tsx:22
#: src/app/[lang]/fusion/Fusion.tsx:92
@@ -222,8 +230,8 @@ msgstr ""
#~ msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/OnrampBanner.tsx:17
-msgid "BOB Gateway is live!"
-msgstr ""
+#~ msgid "BOB Gateway is live!"
+#~ msgstr ""
#: src/app/[lang]/layout.tsx:33
#: src/app/[lang]/layout.tsx:52
@@ -238,9 +246,9 @@ msgstr "BOB TVL进度"
#~ msgid "BOB Wallet"
#~ msgstr "BOB 钱包"
-#: src/app/[lang]/(bridge)/bridge/page.tsx:14
+#: src/app/[lang]/(bridge)/bridge/page.tsx:13
#: src/app/[lang]/page.tsx:15
-#: src/components/Layout/Header.tsx:67
+#: src/components/Layout/Header.tsx:68
#: src/components/Layout/Sidebar.tsx:42
msgid "Bridge"
msgstr "桥"
@@ -288,8 +296,8 @@ msgid "BTC LST Lending"
msgstr "BTC LST借贷"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:252
-msgid "By clicking ‘Connect’ you acknowledge and agree to the"
-msgstr ""
+#~ msgid "By clicking ‘Connect’ you acknowledge and agree to the"
+#~ msgstr ""
#: src/app/[lang]/wallet/components/ReceiveTokenModal/ReceiveTokenModal.tsx:79
#: src/app/[lang]/wallet/components/SendTokenModal/SendTokenModal.tsx:255
@@ -314,8 +322,8 @@ msgstr ""
#: src/connect-ui/component/ConnectModal/BtcWalletList.tsx:39
#: src/connect-ui/component/ConnectModal/EvmWalletList.tsx:76
-msgid "choose available wallets"
-msgstr ""
+#~ msgid "choose available wallets"
+#~ msgstr ""
#: src/app/[lang]/fusion/components/Strategies/Strategies.tsx:179
msgid "Chose any of the existing liquid staking provider to mint your BTC LST."
@@ -367,8 +375,7 @@ msgstr "完成各种链上和链下任务,使用Intract和BOB Stake来额外
msgid "Congratulations you won!<0/>Take a screenshot to share with your friends!"
msgstr ""
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:94
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:107
+#: src/components/AuthButton/AuthButton.tsx:97
msgid "Connect BTC Wallet"
msgstr "连接比特币钱包"
@@ -377,26 +384,26 @@ msgid "Connect BTC wallet to access fee rate settings."
msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:135
-msgid "Connect request is already pending"
-msgstr ""
+#~ msgid "Connect request is already pending"
+#~ msgstr ""
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:63
-#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:214
-#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:35
+#: src/components/AuthButton/AuthButton.tsx:64
+#: src/components/ConnectButton/ConnectButton.tsx:69
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:56
msgid "Connect Wallet"
msgstr "连接钱包"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:296
-msgid "Connect your Bitcoin Wallet (Optional)"
-msgstr ""
+#~ msgid "Connect your Bitcoin Wallet (Optional)"
+#~ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:281
-msgid "Connect your EVM Wallet (Mandatory)"
-msgstr ""
+#~ msgid "Connect your EVM Wallet (Mandatory)"
+#~ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectedWalletSection.tsx:37
-msgid "Connected with <0>{wallet}0>"
-msgstr ""
+#~ msgid "Connected with <0>{wallet}0>"
+#~ msgstr ""
#: src/app/[lang]/wallet/components/ReceiveTokenModal/ReceiveTokenModal.tsx:89
#~ msgid "Copy Address"
@@ -436,6 +443,7 @@ msgstr "将高优先级资产部署到高优先级DeFi协议中,以最大化
#: src/app/[lang]/(bridge)/bridge/Bridge.tsx:128
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:38
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:38
msgid "Deposit"
msgstr ""
@@ -455,7 +463,7 @@ msgstr "将你的BTC LSTs存入 <0>将你的BTC LSTs存入0> 以铸造satUSD
msgid "Deposit your BTC LSTs into <0>Satoshi Protocol0> to mint satUSD."
msgstr "将你的BTC LSTs存入 <0>Satoshi协议0> 以铸造satUSD。"
-#: src/components/Layout/Header.tsx:102
+#: src/components/Layout/Header.tsx:103
#: src/components/Layout/Sidebar.tsx:63
msgid "Dev"
msgstr "开发者"
@@ -472,7 +480,7 @@ msgstr "为DEX提供流动性"
msgid "Diamond"
msgstr ""
-#: src/app/[lang]/nested-providers.tsx:60
+#: src/app/[lang]/nested-providers.tsx:59
msgid "Disconnected"
msgstr ""
@@ -548,14 +556,15 @@ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:138
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:174
-msgid "Failed to connect to {0}"
-msgstr ""
+#~ msgid "Failed to connect to {0}"
+#~ msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:107
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:106
msgid "Failed to finalize."
msgstr ""
-#: src/app/[lang]/(bridge)/hooks/useGateway.ts:234
+#: src/app/[lang]/(bridge)/hooks/useGateway.ts:235
msgid "Failed to get estimated fee"
msgstr ""
@@ -564,6 +573,7 @@ msgstr ""
#~ msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:69
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:68
msgid "Failed to submit proof."
msgstr ""
@@ -589,6 +599,7 @@ msgid "Feeling lucky? Try your luck with the daily lottery!<0/>Participate in Fu
msgstr ""
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionList.tsx:77
+#: src/components/ProfileDrawer/TransactionList/TransactionList.tsx:41
msgid "Fetching bridging operations..."
msgstr ""
@@ -601,6 +612,7 @@ msgid "Final Leaderboard Rank"
msgstr "最终排行榜排名"
#: src/app/[lang]/(bridge)/components/BridgeStatus/RelayStep.tsx:47
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx:45
msgid "Finalize"
msgstr ""
@@ -618,7 +630,7 @@ msgid "Follow us on X for updates"
msgstr ""
#: src/app/[lang]/fusion/page.tsx:16
-#: src/components/Layout/Header.tsx:76
+#: src/components/Layout/Header.tsx:77
#: src/components/Layout/Sidebar.tsx:51
msgid "Fusion"
msgstr "Fusion"
@@ -662,14 +674,14 @@ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:189
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:203
-msgid "go back"
-msgstr ""
+#~ msgid "go back"
+#~ msgstr ""
#: src/app/[lang]/404/NotFound.tsx:30
msgid "Go Back"
msgstr "返回"
-#: src/app/[lang]/nested-providers.tsx:75
+#: src/app/[lang]/nested-providers.tsx:74
msgid "Got it!"
msgstr ""
@@ -817,7 +829,7 @@ msgstr "借贷、再质押、抵押债仓(CDP) *"
#~ msgid "Liquid Staking"
#~ msgstr ""
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:51
+#: src/components/AuthButton/AuthButton.tsx:50
msgid "Loading..."
msgstr ""
@@ -889,7 +901,7 @@ msgstr "铸造satUSD并将其供应到BOB上的借贷市场"
msgid "Multipliers"
msgstr "收益倍数"
-#: src/components/Layout/Header.tsx:108
+#: src/components/Layout/Header.tsx:109
#: src/components/Layout/Sidebar.tsx:54
msgid "Multisig"
msgstr "多签"
@@ -922,7 +934,7 @@ msgstr ""
msgid "navigate to discord"
msgstr ""
-#: src/app/[lang]/(bridge)/components/BannerCarousel/BannerCarousel.tsx:90
+#: src/app/[lang]/(bridge)/components/BannerCarousel/BannerCarousel.tsx:61
msgid "navigate to ecosystem section in fusion page"
msgstr ""
@@ -968,6 +980,7 @@ msgstr ""
#~ msgstr "未显示的资产"
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionList.tsx:96
+#: src/components/ProfileDrawer/TransactionList/TransactionList.tsx:56
msgid "No bridging operations found"
msgstr ""
@@ -996,18 +1009,18 @@ msgid "Not your lucky day... yet!"
msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/OKXCryptopediaBanner.tsx:30
-msgid "OKX Cryptopedia"
-msgstr ""
+#~ msgid "OKX Cryptopedia"
+#~ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:246
-msgid "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
-msgstr ""
+#~ msgid "On BOB, you have the option to link both your EVM and BTC wallets. For optimal functionality, it's advised to connect wallets from both networks."
+#~ msgstr ""
#: src/app/[lang]/fusion/components/WelcomeBackModal/WelcomeBackModal.tsx:68
msgid "Once complete, your season 3 score will be added to seasons 1 and 2 to calculate your final Spice harvest."
msgstr "第3季结束后,你的得分将与第1季和第2季的得分合并,用于计算你的最终Spice收获。"
-#: src/components/Layout/Header.tsx:55
+#: src/components/Layout/Header.tsx:56
msgid "open drawer"
msgstr ""
@@ -1029,6 +1042,7 @@ msgid "Output Token"
msgstr ""
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:62
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:64
msgid "Pending"
msgstr ""
@@ -1073,14 +1087,15 @@ msgid "Preparing..."
msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:266
-msgid "Privacy policy"
-msgstr ""
+#~ msgid "Privacy policy"
+#~ msgstr ""
#: src/app/[lang]/(bridge)/components/GatewayTransactionDetails/GatewayTransactionDetails.tsx:121
msgid "Protocol Fee"
msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/ProveStep.tsx:41
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx:40
msgid "Prove"
msgstr ""
@@ -1205,12 +1220,12 @@ msgid "Security Review by Bitcoin Layers"
msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:211
-msgid "Select Bitcoin Wallet"
-msgstr ""
+#~ msgid "Select Bitcoin Wallet"
+#~ msgstr ""
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:197
-msgid "Select EVM Wallet"
-msgstr ""
+#~ msgid "Select EVM Wallet"
+#~ msgstr ""
#: src/app/[lang]/(bridge)/components/TransactionDetails/TransactionDetails.tsx:119
msgid "select gas token"
@@ -1262,7 +1277,7 @@ msgstr ""
msgid "Share this link with a friend and when they sign up, you will receive 15% of their Spice harvest as a bonus, plus 7% of the Spice harvest of anyone they refer"
msgstr "与朋友分享此链接,当他们注册时,你将获得他们Spice收获的15%作为奖励,以及他们推荐的任何人的Spice收获的7%"
-#: src/components/Layout/Header.tsx:83
+#: src/components/Layout/Header.tsx:84
msgid "Show secondary navigation"
msgstr ""
@@ -1288,8 +1303,8 @@ msgstr ""
#: src/app/[lang]/sign-up/SignUp.tsx:72
#: src/components/LoginButton/LoginButton.tsx:29
#: src/components/SignUpButton/SignUpButton.tsx:29
-msgid "Something went wrong. Please try connecting your wallet again."
-msgstr ""
+#~ msgid "Something went wrong. Please try connecting your wallet again."
+#~ msgstr ""
#: src/app/[lang]/404/NotFound.tsx:23
msgid "Sorry, the page you are looking for doesn't exist or has been moved. Here are some helpful links:"
@@ -1369,7 +1384,7 @@ msgstr ""
#: src/app/[lang]/(bridge)/stake/components/StakeForm/BtcStakeForm.tsx:97
#: src/app/[lang]/(bridge)/stake/components/StakeTable/StakeTable.tsx:97
#: src/app/[lang]/(bridge)/stake/page.tsx:14
-#: src/components/Layout/Header.tsx:73
+#: src/components/Layout/Header.tsx:74
#: src/components/Layout/Sidebar.tsx:48
msgid "Stake"
msgstr "質押"
@@ -1441,6 +1456,7 @@ msgid "Strategy"
msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:100
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:99
msgid "Successfully finalized transaction"
msgstr ""
@@ -1449,6 +1465,7 @@ msgstr ""
#~ msgstr ""
#: src/app/[lang]/(bridge)/components/BridgeStatus/WithdrawStatus.tsx:62
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx:61
msgid "Successfully submitted ${0} proof"
msgstr ""
@@ -1488,11 +1505,11 @@ msgstr "将新铸造的satUSD供应到 <0>BOB上的借贷协议0> 。"
msgid "Support your favourite BOB apps"
msgstr "支持你喜爱的BOB应用"
-#: src/connect-ui/component/AuthButton/AuthButton.tsx:84
+#: src/components/AuthButton/AuthButton.tsx:84
msgid "Switch to {capitalizedName}"
msgstr ""
-#: src/components/Layout/Header.tsx:99
+#: src/components/Layout/Header.tsx:100
#: src/components/Layout/Sidebar.tsx:60
msgid "T&Cs"
msgstr "条款与条件"
@@ -1502,8 +1519,8 @@ msgid "Take em home"
msgstr "回到主页"
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:258
-msgid "Terms of Service"
-msgstr ""
+#~ msgid "Terms of Service"
+#~ msgstr ""
#: src/components/Logo/Logo.tsx:47
msgid "Testnet"
@@ -1514,8 +1531,8 @@ msgid "Thank you for your understanding and we hope to be able to serve you in a
msgstr ""
#: src/app/[lang]/(bridge)/components/BannerCarousel/OnrampBanner.tsx:21
-msgid "The fastest and easiest way to bridge BTC to BOB."
-msgstr ""
+#~ msgid "The fastest and easiest way to bridge BTC to BOB."
+#~ msgstr ""
#: src/app/[lang]/fusion/components/WelcomeBackModal/WelcomeBackModal.tsx:39
#: src/app/[lang]/fusion/components/WelcomeModal/WelcomeModal.tsx:24
@@ -1687,6 +1704,8 @@ msgstr "很抱歉,目前智能账户还不能跨链到BOB。我们正在努力
#: src/app/[lang]/(bridge)/components/BridgeStatus/BridgeStep.tsx:230
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:71
+#: src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx:235
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:73
msgid "Unknown"
msgstr ""
@@ -1740,7 +1759,6 @@ msgid "Use your Spice total to support your favourite BOB builders. Winners will
msgstr "用你的Spice总数来支持你最喜爱的BOB构建者。获胜者将每周公布。"
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:132
-#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:131
#: src/hooks/useLogin.ts:46
#: src/hooks/useSignUp.ts:49
msgid "User rejected the request"
@@ -1805,7 +1823,7 @@ msgstr ""
msgid "Waiting for confirmation"
msgstr ""
-#: src/connect-ui/component/ConnectWallet/ConnectWallet.tsx:60
+#: src/components/ProfileDrawer/ProfileDrawer.tsx:109
msgid "Wallet"
msgstr "钱包"
@@ -1840,6 +1858,7 @@ msgstr "投票时,你不会失去任何收获。你的Spice总数仅用于计
#: src/app/[lang]/(bridge)/bridge/Bridge.tsx:131
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionDetails.tsx:38
+#: src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx:38
msgid "Withdraw"
msgstr ""
@@ -1877,7 +1896,7 @@ msgstr "你可以在每周投票期结束前随时更改你的投票"
msgid "You Have 0 Tickets"
msgstr ""
-#: src/app/[lang]/nested-providers.tsx:67
+#: src/app/[lang]/nested-providers.tsx:66
msgid "You have switched your account mid session. Simply switch back the original account and login to have access to your funds again."
msgstr ""
@@ -1935,7 +1954,7 @@ msgstr ""
msgid "Your available balance may differ from your wallet balance due to network fees and available liquidity"
msgstr ""
-#: src/app/[lang]/nested-providers.tsx:64
+#: src/app/[lang]/nested-providers.tsx:63
msgid "Your funds are safe!"
msgstr ""
From a85c0bee1234f3fe434be78f9d15e76a6060aa88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Mon, 9 Dec 2024 15:23:34 +0000
Subject: [PATCH 09/16] feat: first iteration
---
apps/evm/package.json | 1 +
.../ChainAsset/ChainAsset.style.tsx | 23 ++
.../src/components/ChainAsset/ChainAsset.tsx | 29 ++
apps/evm/src/components/ChainAsset/index.tsx | 1 +
.../src/components/ChainLogo/ChainLogo.tsx | 1 +
.../ProfileDrawer/AddornedAsset.tsx | 31 ---
.../ProfileDrawer/ProfileBtcWallet.tsx | 9 +-
.../ProfileDrawer/ProfileDrawer.style.tsx | 27 +-
.../ProfileDrawer/ProfileDrawer.tsx | 62 +----
.../ProfileDrawer/ProfileEvmWallet.tsx | 14 +-
.../components/ProfileDrawer/ProfileTag.tsx | 4 +-
.../ProfileTokenList.tsx | 53 +---
.../ProfileTokenList.style.tsx | 56 ----
.../ProfileDrawer/ProfileTokenList/index.tsx | 1 -
.../ProfileDrawer/ProfileTokenListItem.tsx | 40 +++
.../BridgeStatus/BridgeStatus.style.tsx | 19 --
.../BridgeStatus/BridgeStatus.tsx | 29 --
.../BridgeStatus/BridgeStep.tsx | 247 ------------------
.../BridgeStatus/DepositStatus.tsx | 28 --
.../BridgeStatus/ProveStep.tsx | 47 ----
.../BridgeStatus/RelayStep.tsx | 52 ----
.../TransactionList/BridgeStatus/TimeStep.tsx | 56 ----
.../BridgeStatus/WithdrawStatus.tsx | 169 ------------
.../TransactionList/BridgeStatus/index.tsx | 1 -
.../TransactionList/BridgeTransactionItem.tsx | 48 ----
.../GatewayStatus/GatewayStatus.tsx | 26 --
.../GatewayStatus/GatewayStep.tsx | 60 -----
.../TransactionList/GatewayStatus/index.tsx | 1 -
.../GatewayTransactionItem.tsx | 38 ---
.../TransactionList/StatusChip/Circle.tsx | 15 --
.../StatusChip/CircleCheck.tsx | 22 --
.../TransactionList/StatusChip/CircleX.tsx | 22 --
.../StatusChip/StatusChip.style.tsx | 42 ---
.../TransactionList/StatusChip/StatusChip.tsx | 49 ----
.../TransactionList/StatusChip/index.tsx | 1 -
.../TransactionList/TransactionDetails.tsx | 84 ------
.../TransactionList/TransactionItem.tsx | 19 --
.../TransactionList/TransactionList.style.tsx | 56 ----
.../TransactionList/TransactionList.tsx | 66 -----
.../ProfileDrawer/TransactionList/index.tsx | 1 -
.../components/ReceiveModal/ReceiveModal.tsx | 96 +++++++
.../evm/src/components/ReceiveModal/index.tsx | 1 +
apps/evm/src/components/index.ts | 9 +-
.../src/components/Drawer/DesktopDrawer.tsx | 62 +++++
pnpm-lock.yaml | 3 +
45 files changed, 291 insertions(+), 1430 deletions(-)
create mode 100644 apps/evm/src/components/ChainAsset/ChainAsset.style.tsx
create mode 100644 apps/evm/src/components/ChainAsset/ChainAsset.tsx
create mode 100644 apps/evm/src/components/ChainAsset/index.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/AddornedAsset.tsx
rename apps/evm/src/components/ProfileDrawer/{ProfileTokenList => }/ProfileTokenList.tsx (64%)
delete mode 100644 apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/ProfileTokenList/index.tsx
create mode 100644 apps/evm/src/components/ProfileDrawer/ProfileTokenListItem.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/TransactionItem.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.style.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
delete mode 100644 apps/evm/src/components/ProfileDrawer/TransactionList/index.tsx
create mode 100644 apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
create mode 100644 apps/evm/src/components/ReceiveModal/index.tsx
create mode 100644 packages/ui/src/components/Drawer/DesktopDrawer.tsx
diff --git a/apps/evm/package.json b/apps/evm/package.json
index cea83c921..bf693c0b8 100644
--- a/apps/evm/package.json
+++ b/apps/evm/package.json
@@ -58,6 +58,7 @@
"react-jazzicon": "^1.0.4",
"react-multi-carousel": "^2.8.5",
"react-otp-input": "^3.1.1",
+ "react-qr-code": "^2.0.12",
"siwe": "^2.1.4",
"styled-components": "catalog:",
"use-count-up": "^3.0.1",
diff --git a/apps/evm/src/components/ChainAsset/ChainAsset.style.tsx b/apps/evm/src/components/ChainAsset/ChainAsset.style.tsx
new file mode 100644
index 000000000..48cee303c
--- /dev/null
+++ b/apps/evm/src/components/ChainAsset/ChainAsset.style.tsx
@@ -0,0 +1,23 @@
+import { Flex } from '@gobob/ui';
+import styled from 'styled-components';
+
+const StyledWrapper = styled(Flex)`
+ position: relative;
+ display: inline-flex;
+ width: max-content;
+ height: fit-content;
+`;
+
+const StyledChain = styled.span`
+ display: inline-flex;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ border: 2px solid ${({ theme }) => theme.color('grey-400')};
+ background-color: ${({ theme }) => theme.color('grey-400')};
+ border-radius: ${({ theme }) => theme.rounded('full')};
+ overflow: hidden;
+ transform: translate(25%, 25%);
+`;
+
+export { StyledWrapper, StyledChain };
diff --git a/apps/evm/src/components/ChainAsset/ChainAsset.tsx b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
new file mode 100644
index 000000000..a87e3bf33
--- /dev/null
+++ b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
@@ -0,0 +1,29 @@
+import { ChainId } from '@gobob/chains';
+import { FlexProps } from '@gobob/ui';
+import { ReactNode } from 'react';
+
+import { ChainLogo } from '../ChainLogo';
+import { ChainLogoProps } from '../ChainLogo/ChainLogo';
+
+import { StyledChain, StyledWrapper } from './ChainAsset.style';
+
+type Props = {
+ chainId: ChainId | 'BTC';
+ asset: ReactNode;
+ chainProps: Omit;
+};
+
+type InheritAttrs = Omit;
+
+type ChainAssetProps = Props & InheritAttrs;
+
+const ChainAsset = ({ asset, chainId, chainProps, ...props }: ChainAssetProps) => (
+
+ {asset}
+
+
+
+
+);
+
+export { ChainAsset };
diff --git a/apps/evm/src/components/ChainAsset/index.tsx b/apps/evm/src/components/ChainAsset/index.tsx
new file mode 100644
index 000000000..01bc90fd1
--- /dev/null
+++ b/apps/evm/src/components/ChainAsset/index.tsx
@@ -0,0 +1 @@
+export { ChainAsset } from './ChainAsset';
diff --git a/apps/evm/src/components/ChainLogo/ChainLogo.tsx b/apps/evm/src/components/ChainLogo/ChainLogo.tsx
index ac5923f61..a3964d628 100644
--- a/apps/evm/src/components/ChainLogo/ChainLogo.tsx
+++ b/apps/evm/src/components/ChainLogo/ChainLogo.tsx
@@ -39,3 +39,4 @@ const ChainLogo = ({ chainId, ...props }: ChainLogoProps) => {
};
export { ChainLogo };
+export type { ChainLogoProps };
diff --git a/apps/evm/src/components/ProfileDrawer/AddornedAsset.tsx b/apps/evm/src/components/ProfileDrawer/AddornedAsset.tsx
deleted file mode 100644
index c4016658b..000000000
--- a/apps/evm/src/components/ProfileDrawer/AddornedAsset.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-'use client';
-
-import { Flex } from '@gobob/ui';
-import { ReactNode } from 'react';
-
-const AddornedAsset = ({ addornment, asset }: { asset: ReactNode; addornment: ReactNode }) => {
- return (
-
- {asset}
-
- {addornment}
-
-
- );
-};
-
-export { AddornedAsset };
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
index a0b2c97c5..752ebdaab 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
@@ -2,14 +2,12 @@
import { WalletIcon } from '@dynamic-labs/wallet-book';
import { BTC } from '@gobob/icons';
-import { Button, Card, ChevronRight, Flex, Span } from '@gobob/ui';
+import { Card, Flex, Span } from '@gobob/ui';
import { truncateBtcAddress } from '@gobob/utils';
import { useBtcAccount, useBtcBalance } from '@/hooks';
-type ProfileBtcWalletProps = { onPress?: () => void };
-
-const ProfileBtcWallet = ({ onPress }: ProfileBtcWalletProps): JSX.Element | null => {
+const ProfileBtcWallet = (): JSX.Element | null => {
const { data: btcBalance } = useBtcBalance();
const { address: btcAddress, connector: btcConnector } = useBtcAccount();
@@ -38,9 +36,6 @@ const ProfileBtcWallet = ({ onPress }: ProfileBtcWalletProps): JSX.Element | nul
-
-
-
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
index 577e79aa3..bc80577a8 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
@@ -1,6 +1,5 @@
-import { Flex, Tabs } from '@gobob/ui';
-import styled from 'styled-components';
-import { css } from 'styled-components';
+import { Flex } from '@gobob/ui';
+import styled, { css } from 'styled-components';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const SyledWrapper = styled(Flex)<{ snap: any }>`
@@ -13,23 +12,9 @@ const SyledWrapper = styled(Flex)<{ snap: any }>`
`}
`;
-const StyledTabs = styled(Tabs)`
- height: 100%;
-
- [role='tabpanel'] {
- height: 100%;
- width: 100%;
- position: relative;
-
- ${({ theme }) => {
- return css`
- @media ${theme.breakpoints.down('s')} {
- min-height: 20vh;
- max-height: 20vh;
- }
- `;
- }}
- }
+const StyledTokenList = styled(Flex)`
+ overflow-y: auto;
+ inset: 0;
`;
-export { StyledTabs, SyledWrapper };
+export { StyledTokenList, SyledWrapper };
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
index 53c9d8f53..1193cd1db 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
@@ -1,13 +1,12 @@
'use client';
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
-import { Button, Card, ChevronLeft, Cog, Flex, P, Power, QrCode, SolidCreditCard, Span, TabsItem } from '@gobob/ui';
+import { Button, Card, Cog, Flex, P, Power, QrCode, SolidCreditCard } from '@gobob/ui';
import { Trans } from '@lingui/macro';
-import { useState } from 'react';
import { useAccount } from 'wagmi';
import { ProfileBtcWallet } from './ProfileBtcWallet';
-import { StyledTabs, SyledWrapper } from './ProfileDrawer.style';
+import { SyledWrapper } from './ProfileDrawer.style';
import { ProfileEvmWallet } from './ProfileEvmWallet';
import { ProfileTag } from './ProfileTag';
import { ProfileTokenList } from './ProfileTokenList';
@@ -15,17 +14,6 @@ import { ProfileTokenList } from './ProfileTokenList';
import { L1_CHAIN } from '@/constants';
import { useBtcAccount, useTotalBalance } from '@/hooks';
-enum ProfileViews {
- Main = 'main',
- BtcWallet = 'btc-wallet',
- EvmWallet = 'evm-wallet'
-}
-
-enum ProfileDrawerTabs {
- Wallet = 'wallet',
- Activity = 'activity'
-}
-
type ProfileDrawerProps = {
isMobile: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -42,8 +30,6 @@ const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Ele
const { formatted } = useTotalBalance(chainId);
- const [view, setView] = useState(ProfileViews.Main);
-
const isAuthenticated = evmAddress || btcAddress;
if (!isAuthenticated) {
@@ -63,12 +49,6 @@ const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Ele
onClose();
};
- const handlePressEvmWallet = () => setView(ProfileViews.EvmWallet);
-
- const handlePressBtcWallet = () => setView(ProfileViews.BtcWallet);
-
- const handlePressBack = () => setView(ProfileViews.Main);
-
return (
@@ -99,39 +79,13 @@ const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Ele
- {view === ProfileViews.Main ? (
-
-
-
-
-
-
- Wallet}>
-
-
- Activity}>
- No Activity here
- {/* */}
-
-
-
- ) : (
-
-
-
-
- Back
-
-
- {view === ProfileViews.EvmWallet && Evm}
- {view === ProfileViews.BtcWallet && Btc}
+
+
+
+
- )}
+
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
index 18ff88e12..10877bdb5 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
@@ -3,21 +3,18 @@
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { WalletIcon } from '@dynamic-labs/wallet-book';
import { ETH } from '@gobob/icons';
-import { Button, Card, ChevronRight, Flex, Span } from '@gobob/ui';
+import { Card, Flex, Span } from '@gobob/ui';
import { truncateEthAddress } from '@gobob/utils';
-import { ChainLogo } from '../ChainLogo';
-
-import { AddornedAsset } from './AddornedAsset';
+import { ChainAsset } from '../ChainAsset';
import { useBalances } from '@/hooks';
type ProfileEvmWalletProps = {
chainId: number;
- onPress?: () => void;
};
-const ProfileEvmWallet = ({ chainId, onPress }: ProfileEvmWalletProps): JSX.Element | null => {
+const ProfileEvmWallet = ({ chainId }: ProfileEvmWalletProps): JSX.Element | null => {
const { getBalance } = useBalances(chainId);
const { primaryWallet } = useDynamicContext();
@@ -33,7 +30,7 @@ const ProfileEvmWallet = ({ chainId, onPress }: ProfileEvmWalletProps): JSX.Elem
padding='md'
>
- } asset={} />
+ } chainId={chainId} chainProps={{ size: 'xs' }} />
{getBalance('ETH')?.toSignificant()} ETH
@@ -46,9 +43,6 @@ const ProfileEvmWallet = ({ chainId, onPress }: ProfileEvmWalletProps): JSX.Elem
-
-
-
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx
index 3accfcdd7..03fe175b1 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx
@@ -21,12 +21,14 @@ const ProfileTag = ({
evmAddress,
btcAddress,
user,
- size = 's'
+ size = 's',
+ isLoading
}: {
btcAddress?: string;
evmAddress?: Address;
user?: UserProfile;
size?: 's' | 'md';
+ isLoading?: boolean;
}) => {
const displayedAddress = evmAddress
? truncateEthAddress(evmAddress)
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
similarity index 64%
rename from apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx
rename to apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
index e4336c493..58d721a57 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
@@ -1,54 +1,13 @@
-import { Avatar, Flex, P, useCurrencyFormatter } from '@gobob/ui';
-import { usePrices } from '@gobob/hooks';
import { CurrencyAmount } from '@gobob/currency';
+import { usePrices } from '@gobob/hooks';
import { BITCOIN } from '@gobob/tokens';
+import { Flex, P } from '@gobob/ui';
-import { AddornedAsset } from '../AddornedAsset';
-
-import { StyledTransactionList } from './ProfileTokenList.style';
+import { StyledTokenList } from './ProfileDrawer.style';
+import { ProfileTokenListItem } from './ProfileTokenListItem';
import { useBalances, useBtcBalance, useTokens } from '@/hooks';
import { calculateAmountUSD } from '@/utils';
-import { ChainLogo } from '@/components';
-
-const ProfileTokenListItem = ({
- chainId,
- amountUSD,
- balance,
- logoUrl,
- name,
- symbol
-}: {
- chainId?: number;
- name: string;
- logoUrl: string;
- balance: string;
- symbol: string;
- amountUSD: number;
-}) => {
- const format = useCurrencyFormatter();
-
- return (
-
-
- {chainId ? (
- }
- asset={}
- />
- ) : (
-
- )}
-
- {name}
-
- {balance} {symbol} ({format(amountUSD)})
-
-
-
-
- );
-};
type ProfileTokenListProps = {
chainId: number;
@@ -69,7 +28,7 @@ const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
const ethBalance = ethData && getBalance(ethData.raw.symbol);
return (
-
+
{ethBalance && ethData && (
{
))}
-
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
deleted file mode 100644
index 87d65042f..000000000
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/ProfileTokenList.style.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Flex, Span, ArrowDownCircle } from '@gobob/ui';
-import styled from 'styled-components';
-
-type StyledExpandIconProps = {
- $isExpanded?: boolean;
-};
-
-const StyledSpan = styled(Span)`
- display: inline-flex;
- align-items: center;
- position: relative;
- margin-left: ${({ theme }) => theme.spacing('md')};
- padding: 0 ${({ theme }) => theme.spacing('s')};
- height: 24px;
- border-radius: ${({ theme }) => theme.rounded('full')};
-`;
-
-const StyledSpinnerWrapper = styled.span`
- position: absolute;
- top: 0;
- left: 50%;
- transform: translateX(-50%);
-`;
-
-const StyledTransactionList = styled(Flex)`
- overflow-y: auto;
- position: absolute;
- inset: 0;
-`;
-
-const StyledTransactionListWrapper = styled(Flex)`
- overflow: hidden;
-`;
-
-const StyledDetailsButton = styled(Flex)`
- font: inherit;
- display: flex;
- width: 100%;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing('md')};
- padding: ${({ theme }) => `${theme.spacing('md')} 0`};
-`;
-
-const StyledExpandIcon = styled(ArrowDownCircle)`
- ${({ theme }) => theme.transition('common', 'normal')};
- transform: ${({ $isExpanded }) => ($isExpanded ? 'rotate(-180deg)' : 'rotate(0deg)')};
-`;
-
-export {
- StyledDetailsButton,
- StyledExpandIcon,
- StyledSpan,
- StyledSpinnerWrapper,
- StyledTransactionList,
- StyledTransactionListWrapper
-};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/index.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList/index.tsx
deleted file mode 100644
index 83a9e600b..000000000
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { ProfileTokenList } from './ProfileTokenList';
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenListItem.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenListItem.tsx
new file mode 100644
index 000000000..a381eb878
--- /dev/null
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenListItem.tsx
@@ -0,0 +1,40 @@
+import { Avatar, Flex, P, useCurrencyFormatter } from '@gobob/ui';
+
+import { ChainAsset } from '@/components';
+
+type ProfileTokenListItemProps = {
+ chainId?: number;
+ name: string;
+ logoUrl: string;
+ balance: string;
+ symbol: string;
+ amountUSD: number;
+};
+
+const ProfileTokenListItem = ({ chainId, amountUSD, balance, logoUrl, name, symbol }: ProfileTokenListItemProps) => {
+ const format = useCurrencyFormatter();
+
+ return (
+
+
+ {chainId ? (
+ }
+ chainId={chainId}
+ chainProps={{ size: 'xs' }}
+ />
+ ) : (
+
+ )}
+
+ {name}
+
+ {balance} {symbol} ({format(amountUSD)})
+
+
+
+
+ );
+};
+
+export { ProfileTokenListItem };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx
deleted file mode 100644
index 3e0907038..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.style.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { P } from '@gobob/ui';
-import styled from 'styled-components';
-
-import { AuthButton } from '@/components';
-
-const StyledTimePill = styled(P)`
- padding: ${({ theme }) => `${theme.spacing('xs')} ${theme.spacing('lg')}`};
- border-radius: ${({ theme }) => theme.rounded('full')};
- background-color: ${({ theme }) => theme.color('grey-400')};
- display: flex;
- align-items: center;
- gap: ${({ theme }) => theme.spacing('xs')};
-`;
-
-const StyledStatusActionButton = styled(AuthButton)`
- height: ${({ theme }) => theme.spacing('4xl')};
-`;
-
-export { StyledStatusActionButton, StyledTimePill };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx
deleted file mode 100644
index 81bd1c230..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStatus.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { FlexProps } from '@gobob/ui';
-
-import { DepositStatus } from './DepositStatus';
-import { WithdrawStatus } from './WithdrawStatus';
-
-import { BridgeTransaction, TransactionDirection } from '@/types';
-
-type Props = { data: BridgeTransaction; isExpanded: boolean; onProveSuccess?: () => void; onRelaySuccess?: () => void };
-
-type InheritAttrs = Omit;
-
-type BridgeStatusProps = Props & InheritAttrs;
-
-const BridgeStatus = ({ data, isExpanded, onProveSuccess, onRelaySuccess }: BridgeStatusProps): JSX.Element => {
- if (data.direction === TransactionDirection.L1_TO_L2) {
- return ;
- }
-
- return (
-
- );
-};
-
-export { BridgeStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx
deleted file mode 100644
index 0b9555393..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/BridgeStep.tsx
+++ /dev/null
@@ -1,247 +0,0 @@
-import { t } from '@lingui/macro';
-import { useLingui } from '@lingui/react';
-import { Address } from 'viem';
-
-import { StatusChip } from '../StatusChip';
-
-import {
- BridgeSteps,
- BridgeStepStatus,
- BridgeTransaction,
- BridgeTransactionStatus,
- TransactionDirection
-} from '@/types';
-import { chainL1, chainL2 } from '@/constants';
-
-const getOngoingBridgeStep = (status: BridgeTransactionStatus, direction: TransactionDirection): BridgeSteps => {
- switch (status) {
- case BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE:
- return 'deposit';
- default:
- case BridgeTransactionStatus.READY_FOR_RELAY:
- return 'relay';
- case BridgeTransactionStatus.RELAYED:
- return direction === TransactionDirection.L1_TO_L2 ? 'l2-confirmation' : 'l1-confirmation';
- case BridgeTransactionStatus.READY_TO_PROVE:
- return 'prove';
- case BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED:
- return 'state-root-published';
- case BridgeTransactionStatus.IN_CHALLENGE_PERIOD:
- return 'challenge-period';
- }
-};
-
-const getLabel = (stage: BridgeSteps, status: BridgeStepStatus, isActing?: boolean, isActionSuccessful?: boolean) => {
- switch (stage) {
- case 'deposit': {
- switch (status) {
- case 'idle':
- return 'Deposit';
- case 'ongoing':
- return 'Depositing...';
- default:
- case 'complete':
- return 'Deposited';
- }
- }
- case 'l2-confirmation': {
- return 'L2 confirmation';
- }
- case 'withdraw': {
- switch (status) {
- case 'idle':
- return 'Withdraw';
- case 'ongoing':
- return 'Withdrawing...';
- default:
- case 'complete':
- return 'Withdrawn';
- }
- }
- case 'state-root-published': {
- switch (status) {
- case 'idle':
- return 'State root publishment';
- case 'ongoing':
- return 'Waiting for state root';
- default:
- case 'complete':
- return 'State root published';
- }
- }
- case 'prove': {
- switch (status) {
- case 'idle':
- return 'Prove';
- case 'ongoing':
- return isActionSuccessful ? 'Proved' : isActing ? 'Proving...' : 'Ready to prove...';
- default:
- case 'complete':
- return 'Proved';
- }
- }
- case 'challenge-period': {
- switch (status) {
- case 'idle':
- return 'Challenge period';
- case 'ongoing':
- return 'Challenge period';
- default:
- case 'complete':
- return 'Challenge period';
- }
- }
- case 'relay': {
- switch (status) {
- case 'idle':
- return 'Relay';
- case 'ongoing':
- return isActing ? 'Relaying...' : 'Ready to relay...';
- default:
- case 'complete':
- return 'Relayed';
- }
- }
- case 'l1-confirmation': {
- switch (status) {
- case 'idle':
- return 'Finalized';
- case 'ongoing':
- return 'Finalizing...';
- default:
- case 'complete':
- return 'Finalized';
- }
- }
- }
-};
-
-const withdrawOrder = {
- [BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED]: 1,
- [BridgeTransactionStatus.READY_TO_PROVE]: 2,
- [BridgeTransactionStatus.IN_CHALLENGE_PERIOD]: 3,
- [BridgeTransactionStatus.READY_FOR_RELAY]: 4,
- [BridgeTransactionStatus.RELAYED]: 5,
- [BridgeTransactionStatus.FAILED_L1_TO_L2_MESSAGE]: -1,
- [BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE]: -1
-} as const;
-
-const getBridgeStepStatus = (step: number, currentStep: number) => {
- if (currentStep < step) {
- return 'idle';
- } else if (currentStep === step) {
- return 'ongoing';
- } else {
- return 'complete';
- }
-};
-
-const getStatus = (
- step: BridgeSteps,
- status: BridgeTransactionStatus | null,
- direction: TransactionDirection
-): BridgeStepStatus => {
- if (!status) return 'idle';
-
- if (direction === TransactionDirection.L1_TO_L2) {
- switch (step) {
- case 'deposit': {
- return status === BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE ? 'ongoing' : 'complete';
- }
- case 'l2-confirmation': {
- switch (status) {
- case BridgeTransactionStatus.UNCONFIRMED_L1_TO_L2_MESSAGE:
- return 'idle';
- case BridgeTransactionStatus.RELAYED:
- return 'complete';
- case BridgeTransactionStatus.FAILED_L1_TO_L2_MESSAGE:
- return 'failed';
-
- default:
- return 'ongoing';
- }
- }
- }
- }
-
- const currentStep = withdrawOrder[status];
-
- switch (step) {
- case 'withdraw': {
- return 'complete';
- }
- case 'state-root-published': {
- const step = withdrawOrder[BridgeTransactionStatus.STATE_ROOT_NOT_PUBLISHED];
-
- return getBridgeStepStatus(step, currentStep);
- }
- case 'prove': {
- const step = withdrawOrder[BridgeTransactionStatus.READY_TO_PROVE];
-
- return getBridgeStepStatus(step, currentStep);
- }
- case 'challenge-period': {
- const step = withdrawOrder[BridgeTransactionStatus.IN_CHALLENGE_PERIOD];
-
- return getBridgeStepStatus(step, currentStep);
- }
- case 'l1-confirmation':
- case 'relay': {
- const step = withdrawOrder[BridgeTransactionStatus.READY_FOR_RELAY];
-
- return getBridgeStepStatus(step, currentStep);
- }
- }
-
- return 'complete';
-};
-
-const getStepUrl = (
- step: BridgeSteps,
- transactionHash: Address,
- l1TransactionHash?: Address,
- l2TransactionHash?: Address
-) => {
- switch (step) {
- case 'deposit': {
- return `${chainL1.blockExplorers?.default.url}/tx/${transactionHash}`;
- }
- case 'l1-confirmation': {
- return l1TransactionHash ? `${chainL1.blockExplorers?.default.url}/tx/${l1TransactionHash}` : undefined;
- }
- case 'withdraw': {
- return `${chainL2.blockExplorers?.default.url}/tx/${transactionHash}`;
- }
- case 'l2-confirmation': {
- return l2TransactionHash ? `${chainL2.blockExplorers?.default.url}/tx/${l2TransactionHash}` : undefined;
- }
- default:
- return undefined;
- }
-};
-
-type BridgeStepProps = {
- isActing?: boolean;
- isActionSuccessful?: boolean;
- step?: BridgeSteps;
- data: BridgeTransaction;
-};
-
-const BridgeStep = ({ data, isActing, isActionSuccessful, step }: BridgeStepProps): JSX.Element => {
- const { i18n } = useLingui();
- const { status: messageStatus, l1Receipt, l2Receipt, direction, transactionHash } = data;
-
- if (step === undefined) {
- return ;
- }
-
- const href = getStepUrl(step, transactionHash, l1Receipt?.transactionHash, l2Receipt?.transactionHash);
-
- const status = getStatus(step, messageStatus, direction);
-
- const label = getLabel(step, status, isActing, isActionSuccessful);
-
- return ;
-};
-
-export { BridgeStep, getOngoingBridgeStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx
deleted file mode 100644
index aa9cdad8c..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/DepositStatus.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-
-import { BridgeStep, getOngoingBridgeStep } from './BridgeStep';
-
-import { BridgeTransaction } from '@/types';
-
-type Props = { data: BridgeTransaction; isExpanded: boolean };
-
-type InheritAttrs = Omit;
-
-type DepositStatusProps = Props & InheritAttrs;
-
-const DepositStatus = ({ data, isExpanded }: DepositStatusProps): JSX.Element => {
- if (!isExpanded) {
- const step = data.status ? getOngoingBridgeStep(data.status, data.direction) : undefined;
-
- return ;
- }
-
- return (
-
-
-
-
- );
-};
-
-export { DepositStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx
deleted file mode 100644
index 102529137..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/ProveStep.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-
-import { StyledStatusActionButton } from './BridgeStatus.style';
-import { BridgeStep } from './BridgeStep';
-
-import { BridgeTransaction } from '@/types';
-import { BridgeSteps, BridgeTransactionStatus } from '@/types';
-import { L1_CHAIN } from '@/constants';
-
-type Props = {
- data: BridgeTransaction;
- currentStep?: BridgeSteps;
- isProving?: boolean;
- isProveSuccessful: boolean;
- onPressProve?: () => void;
-};
-
-type InheritAttrs = Omit;
-
-type ProveStepProps = Props & InheritAttrs;
-
-const ProveStep = ({ data, currentStep, isProving, isProveSuccessful, onPressProve }: ProveStepProps): JSX.Element => {
- const isWaitingProve =
- currentStep === 'prove' && data.status === BridgeTransactionStatus.READY_TO_PROVE && !isProveSuccessful;
-
- return (
-
-
- {isWaitingProve && (
-
- Prove
-
- )}
-
- );
-};
-
-export { ProveStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx
deleted file mode 100644
index 11839ffa2..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/RelayStep.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-
-import { StyledStatusActionButton } from './BridgeStatus.style';
-import { BridgeStep } from './BridgeStep';
-
-import { L1_CHAIN } from '@/constants';
-import { BridgeSteps, BridgeTransaction, BridgeTransactionStatus } from '@/types';
-
-type Props = {
- data: BridgeTransaction;
- currentStep?: BridgeSteps;
- isRelaying?: boolean;
- isRelaySuccessful: boolean;
- onPressFinalize?: () => void;
-};
-
-type InheritAttrs = Omit;
-
-type RelayStepProps = Props & InheritAttrs;
-
-const RelayStep = ({
- data,
- currentStep,
- isRelaySuccessful,
- isRelaying,
- onPressFinalize
-}: RelayStepProps): JSX.Element => {
- const isWaitingRelay =
- currentStep === 'relay' && data.status === BridgeTransactionStatus.READY_FOR_RELAY && !isRelaySuccessful;
-
- return (
-
-
- {isWaitingRelay && (
-
- Finalize
-
- )}
-
- );
-};
-
-export { RelayStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx
deleted file mode 100644
index 06ccd6366..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/TimeStep.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Clock, Flex, FlexProps } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-import { formatDistanceToNow, isFuture } from 'date-fns';
-import { ReactNode, useMemo } from 'react';
-
-import { StyledTimePill } from './BridgeStatus.style';
-import { BridgeStep } from './BridgeStep';
-
-import { BridgeSteps, BridgeTransaction } from '@/types';
-
-const TimeLabel = ({ label }: { label: ReactNode }) => (
-
-
- {label}
-
-);
-
-type Props = {
- data: BridgeTransaction;
- step: Extract;
- currentStep?: BridgeSteps;
-};
-
-type InheritAttrs = Omit;
-
-type TimeStepProps = Props & InheritAttrs;
-
-const TimeStep = ({ step, data, currentStep }: TimeStepProps): JSX.Element => {
- const timeLabel = useMemo(() => {
- // should only show step if it is not a complete step
- const showTime =
- (step === 'challenge-period'
- ? currentStep !== 'l1-confirmation' && currentStep !== 'relay'
- : currentStep === 'l2-confirmation' || currentStep === 'state-root-published') ||
- // when the current step is challenge period or state root, we should only show is the date is in the future
- (currentStep === step && data.statusEndDate && isFuture(data.statusEndDate));
-
- if (!showTime) return undefined;
-
- // show default duration estimate if step is still incomplete
- if (currentStep !== step || !data.statusEndDate) {
- return step === 'challenge-period' ? 7 days : 2 hours;
- }
-
- return {formatDistanceToNow(data.statusEndDate)} remaining;
- }, [step, currentStep, data.statusEndDate]);
-
- return (
-
-
- {timeLabel && }
-
- );
-};
-
-export { TimeStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx
deleted file mode 100644
index 0beff7537..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/WithdrawStatus.tsx
+++ /dev/null
@@ -1,169 +0,0 @@
-'use client';
-
-import { Flex, FlexProps, toast } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-import * as Sentry from '@sentry/nextjs';
-import { useMutation } from '@tanstack/react-query';
-import { useMemo } from 'react';
-import { getWithdrawals } from 'viem/op-stack';
-import { useAccount } from 'wagmi';
-
-import { BridgeStep, getOngoingBridgeStep } from './BridgeStep';
-import { ProveStep } from './ProveStep';
-import { RelayStep } from './RelayStep';
-import { TimeStep } from './TimeStep';
-
-import { BridgeTransaction } from '@/types';
-import { usePublicClientL1, usePublicClientL2, useWalletClientL1, useWalletClientL2 } from '@/hooks';
-import { bridgeKeys } from '@/lib/react-query';
-
-type Props = { data: BridgeTransaction; isExpanded: boolean; onProveSuccess?: () => void; onRelaySuccess?: () => void };
-
-type InheritAttrs = Omit;
-
-type WithdrawStatusProps = Props & InheritAttrs;
-
-const WithdrawStatus = ({ data, isExpanded, onProveSuccess, onRelaySuccess }: WithdrawStatusProps): JSX.Element => {
- const publicClientL1 = usePublicClientL1();
- const publicClientL2 = usePublicClientL2();
-
- const walletClientL1 = useWalletClientL1();
- const walletClientL2 = useWalletClientL2();
-
- const { address } = useAccount();
-
- const proveMutation = useMutation({
- mutationKey: bridgeKeys.proveTransaction(address, data.transactionHash),
- mutationFn: async () => {
- const receipt =
- data.l2Receipt ||
- (await publicClientL2.getTransactionReceipt({
- hash: data.transactionHash
- }));
-
- const { output, withdrawal } = await publicClientL1.waitToProve({
- receipt,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- targetChain: walletClientL2.chain as any
- });
-
- const args = await publicClientL2.buildProveWithdrawal({
- output,
- withdrawal
- });
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const hash = await walletClientL1?.proveWithdrawal(args as any);
-
- return { hash };
- },
- onSuccess: (data) => {
- toast.success(Successfully submitted ${data?.hash} proof);
- onProveSuccess?.();
- },
- onError: (e) => {
- Sentry.captureException(e);
- // eslint-disable-next-line no-console
- console.log('Prove: ', e);
- toast.error(Failed to submit proof.);
- }
- });
-
- const relayMutation = useMutation({
- mutationKey: bridgeKeys.relayTransaction(address, data.transactionHash),
- mutationFn: async () => {
- if (!address) return;
-
- const receiptL2 =
- data.l2Receipt ||
- (await publicClientL2.getTransactionReceipt({
- hash: data.transactionHash
- }));
-
- const [withdrawal] = getWithdrawals(receiptL2);
-
- const hash = await walletClientL1.finalizeWithdrawal({
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- targetChain: walletClientL2.chain as any,
- withdrawal: withdrawal!,
- account: address
- });
-
- await publicClientL1.waitForTransactionReceipt({
- hash
- });
-
- return hash;
- },
- onSuccess: () => {
- toast.success(Successfully finalized transaction);
- onRelaySuccess?.();
- },
- onError: (e) => {
- Sentry.captureException(e);
- // eslint-disable-next-line no-console
- console.log('Finalize: ', e);
- toast.error(Failed to finalize.);
- }
- });
-
- const currentStep = useMemo(
- () => (data.status ? getOngoingBridgeStep(data.status, data.direction) : undefined),
- [data]
- );
-
- if (!isExpanded) {
- switch (currentStep) {
- case 'state-root-published':
- return ;
- case 'prove':
- return (
-
- );
- case 'relay':
- return (
-
- );
- case 'challenge-period':
- return ;
- default:
- return ;
- }
- }
-
- return (
-
-
-
-
-
-
-
- );
-};
-
-export { WithdrawStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx
deleted file mode 100644
index efd4739d4..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeStatus/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { BridgeStatus } from './BridgeStatus';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
deleted file mode 100644
index 6916f63fc..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/BridgeTransactionItem.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-import { useState } from 'react';
-
-import { TransactionDetails } from './TransactionDetails';
-import { BridgeStatus } from './BridgeStatus';
-
-import { L1_CHAIN, L2_CHAIN } from '@/constants';
-import { BridgeTransaction, TransactionDirection } from '@/types';
-
-type Props = { data: BridgeTransaction; onProveSuccess?: () => void; onRelaySuccess?: () => void };
-
-type InheritAttrs = Omit;
-
-type BridgeTransactionItemProps = Props & InheritAttrs;
-
-const BridgeTransactionItem = ({
- data,
- onProveSuccess,
- onRelaySuccess,
- ...props
-}: BridgeTransactionItemProps): JSX.Element => {
- const [isExpanded, setExpanded] = useState(false);
-
- const fromChaindId = data.direction === TransactionDirection.L1_TO_L2 ? L1_CHAIN : L2_CHAIN;
- const toChaindId = data.direction === TransactionDirection.L1_TO_L2 ? L2_CHAIN : L1_CHAIN;
-
- return (
-
- setExpanded((isExpanded) => !isExpanded)}
- />
-
-
- );
-};
-
-export { BridgeTransactionItem };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx
deleted file mode 100644
index 3339d0a6f..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStatus.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-
-import { GatewayStep } from './GatewayStep';
-
-import { GatewayTransaction } from '@/types';
-
-type Props = { data: GatewayTransaction; isExpanded: boolean };
-
-type InheritAttrs = Omit;
-
-type GatewayStatusProps = Props & InheritAttrs;
-
-const GatewayStatus = ({ data, isExpanded }: GatewayStatusProps): JSX.Element => {
- if (!isExpanded) {
- return ;
- }
-
- return (
-
-
-
-
- );
-};
-
-export { GatewayStatus };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx
deleted file mode 100644
index 895c80087..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/GatewayStep.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { StatusChip } from '../StatusChip';
-
-import { GatewayTransaction } from '@/types';
-import { mempoolUrl } from '@/constants';
-import { GatewaySteps } from '@/types';
-
-const getLabel = (status: GatewaySteps, confirmations: number, totalConfirmations: number) => {
- switch (status) {
- case 'btc-confirmation':
- return confirmations <= totalConfirmations
- ? `BTC confirmations (${confirmations}/${totalConfirmations})`
- : 'BTC confirmations';
- case 'l2-processing':
- case 'l2-confirmation':
- return 'L2 confirmation';
- case 'l2-incomplete':
- return 'L2 incomplete';
- }
-};
-
-const getStatus = (data: GatewayTransaction, step: GatewaySteps) => {
- switch (step) {
- case 'btc-confirmation':
- return data.status === 'btc-confirmation' ? 'ongoing' : 'complete';
- case 'l2-processing':
- switch (data.status) {
- case 'btc-confirmation':
- return 'idle';
- case 'l2-processing':
- return 'ongoing';
- case 'l2-confirmation':
- return 'complete';
- case 'l2-incomplete':
- return 'failed';
- }
- case 'l2-incomplete':
- return data.status === 'l2-incomplete' ? 'failed' : 'idle';
- case 'l2-confirmation':
- return data.status === 'l2-confirmation' ? 'complete' : 'idle';
- }
-};
-
-type GatewayStepProps = {
- data: GatewayTransaction;
- step?: GatewaySteps;
-};
-
-const GatewayStep = ({ step: stepProp, data }: GatewayStepProps): JSX.Element => {
- const step = stepProp || data.status;
-
- const label = getLabel(step, data.confirmations, data.totalConfirmations);
-
- const href = step === 'btc-confirmation' ? `${mempoolUrl}/tx/${data.btcTxId}` : undefined;
-
- const status = getStatus(data, step);
-
- return ;
-};
-
-export { GatewayStep };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx
deleted file mode 100644
index e3752a534..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayStatus/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { GatewayStatus } from './GatewayStatus';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
deleted file mode 100644
index 5e766c4dc..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/GatewayTransactionItem.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Flex, FlexProps } from '@gobob/ui';
-import { useState } from 'react';
-
-import { TransactionDetails } from './TransactionDetails';
-import { GatewayStatus } from './GatewayStatus';
-
-import { L2_CHAIN } from '@/constants';
-import { GatewayTransaction, TransactionDirection } from '@/types';
-
-type Props = { data: GatewayTransaction };
-
-type InheritAttrs = Omit;
-
-type GatewayTransactionItemProps = Props & InheritAttrs;
-
-const GatewayTransactionItem = ({ data, ...props }: GatewayTransactionItemProps): JSX.Element => {
- const [isExpanded, setExpanded] = useState(false);
-
- const fromChaindId = 'BTC';
- const toChaindId = L2_CHAIN;
-
- return (
-
- setExpanded((isExpanded) => !isExpanded)}
- />
-
-
- );
-};
-
-export { GatewayTransactionItem };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx
deleted file mode 100644
index 47d9cc56b..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/Circle.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Icon, IconProps } from '@gobob/ui';
-import { forwardRef } from 'react';
-
-const Circle = forwardRef((props, ref) => (
-
-
-
-));
-
-Circle.displayName = 'Circle';
-
-export { Circle };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx
deleted file mode 100644
index 0af33f5d2..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleCheck.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Icon, IconProps } from '@gobob/ui';
-import { forwardRef } from 'react';
-
-const CircleCheck = forwardRef((props, ref) => (
-
-
-
-
-
-
-
-
-
-
-));
-
-CircleCheck.displayName = 'CircleCheck';
-
-export { CircleCheck };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx
deleted file mode 100644
index 71e8ed03a..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/CircleX.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { forwardRef } from 'react';
-import { Icon, IconProps } from '@gobob/ui';
-
-const CircleX = forwardRef((props, ref) => (
-
-
-
-
-
-
-
-
-
-
-));
-
-CircleX.displayName = 'CircleX';
-
-export { CircleX };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx
deleted file mode 100644
index b35cc0b48..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.style.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Link, Spinner } from '@gobob/ui';
-import styled from 'styled-components';
-
-import { BridgeStepStatus } from '@/types';
-
-type StyledChipProps = {
- $status: BridgeStepStatus;
-};
-
-const StyledChip = styled(Link)`
- display: inline-flex;
- width: min-content;
- white-space: nowrap;
- gap: ${({ theme }) => theme.spacing('xs')};
- align-items: center;
- padding: ${({ theme }) => `${theme.spacing('xs')} ${theme.spacing('lg')}`};
- border-radius: ${({ theme }) => theme.rounded('full')};
- background-color: ${({ theme, $status }) =>
- $status === 'complete'
- ? theme.color('grey-600')
- : $status === 'ongoing'
- ? theme.color('green-300')
- : $status === 'failed'
- ? theme.color('red-800')
- : theme.color('grey-600')};
- opacity: ${({ $status }) => ($status === 'idle' ? '.7' : '1')};
- color: ${({ $status, theme }) => ($status === 'ongoing' ? theme.color('dark') : theme.color('light'))};
-
- &,
- &:hover {
- text-decoration: none;
- }
-`;
-
-const StyledLoadingSpinner = styled(Spinner)`
- border-bottom-color: transparent;
- border-left-color: ${({ theme }) => theme.color('dark')};
- border-top-color: ${({ theme }) => theme.color('dark')};
- border-right-color: ${({ theme }) => theme.color('dark')};
-`;
-
-export { StyledLoadingSpinner, StyledChip };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx
deleted file mode 100644
index b7280c6f9..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/StatusChip.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { ArrowTopRightOnSquare, Span } from '@gobob/ui';
-
-import { StyledLoadingSpinner, StyledChip } from './StatusChip.style';
-import { Circle } from './Circle';
-import { CircleCheck } from './CircleCheck';
-import { CircleX } from './CircleX';
-
-import { BridgeStepStatus } from '@/types';
-
-const getPillIcon = (status: BridgeStepStatus) => {
- switch (status) {
- case 'idle':
- return ;
- case 'complete':
- return ;
- case 'failed':
- return ;
- default:
- case 'ongoing':
- return ;
- }
-};
-
-type StatusChipProps = {
- href?: string;
- label: string;
- status: BridgeStepStatus;
-};
-
-const StatusChip = ({ label, status, href }: StatusChipProps): JSX.Element => {
- const icon = getPillIcon(status);
-
- return (
-
- {icon}
- {label}
- {href && }
-
- );
-};
-
-export { StatusChip };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx
deleted file mode 100644
index 466a85edb..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/StatusChip/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { StatusChip } from './StatusChip';
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx
deleted file mode 100644
index 17ade1610..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionDetails.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { ChainId } from '@gobob/chains';
-import { Currency, CurrencyAmount } from '@gobob/currency';
-import { ArrowLongRight, Flex, FlexProps, P, UnstyledButton } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-import { formatDistanceToNow } from 'date-fns';
-
-import { StyledDetailsButton, StyledExpandIcon } from './TransactionList.style';
-
-import { ChainLogo } from '@/components';
-import { TransactionDirection } from '@/types';
-
-type Props = {
- direction: TransactionDirection;
- date: Date;
- fromChainId: ChainId | 'BTC';
- toChainId: ChainId | 'BTC';
- amount?: CurrencyAmount;
- isPending?: boolean;
- isExpanded?: boolean;
- onExpand?: () => void;
-};
-
-type InheritAttrs = Omit;
-
-type TransactionDetailsProps = Props & InheritAttrs;
-
-const TransactionDetails = ({
- direction,
- date,
- fromChainId,
- toChainId,
- amount,
- isPending,
- isExpanded,
- onExpand,
- ...props
-}: TransactionDetailsProps): JSX.Element => {
- const directionLabel = direction === TransactionDirection.L1_TO_L2 ? Deposit : Withdraw;
-
- const isExpandable = !!onExpand;
-
- return (
-
-
-
-
-
-
-
-
-
- {directionLabel}
-
-
-
- {formatDistanceToNow(date)} ago
-
-
-
-
-
- {(isPending && (
-
- Pending
-
- )) ||
- (amount && (
-
- {amount.toExact()} {amount.currency.symbol}
-
- )) || (
-
- Unknown
-
- )}
- {isExpandable && }
-
-
-
-
- );
-};
-
-export { TransactionDetails };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionItem.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionItem.tsx
deleted file mode 100644
index d48c43da9..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionItem.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { BridgeTransactionItem } from './BridgeTransactionItem';
-import { GatewayTransactionItem } from './GatewayTransactionItem';
-
-import { Transaction, TransactionType } from '@/types';
-
-type TransactionItemProps = { data: Transaction; onProveSuccess?: () => void; onRelaySuccess?: () => void };
-
-const TransactionItem = ({ data, onProveSuccess, onRelaySuccess }: TransactionItemProps): JSX.Element | null => {
- switch (data.type) {
- case TransactionType.Bridge:
- return ;
- case TransactionType.Gateway:
- return ;
- default:
- return null;
- }
-};
-
-export { TransactionItem };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.style.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.style.tsx
deleted file mode 100644
index 87d65042f..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.style.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Flex, Span, ArrowDownCircle } from '@gobob/ui';
-import styled from 'styled-components';
-
-type StyledExpandIconProps = {
- $isExpanded?: boolean;
-};
-
-const StyledSpan = styled(Span)`
- display: inline-flex;
- align-items: center;
- position: relative;
- margin-left: ${({ theme }) => theme.spacing('md')};
- padding: 0 ${({ theme }) => theme.spacing('s')};
- height: 24px;
- border-radius: ${({ theme }) => theme.rounded('full')};
-`;
-
-const StyledSpinnerWrapper = styled.span`
- position: absolute;
- top: 0;
- left: 50%;
- transform: translateX(-50%);
-`;
-
-const StyledTransactionList = styled(Flex)`
- overflow-y: auto;
- position: absolute;
- inset: 0;
-`;
-
-const StyledTransactionListWrapper = styled(Flex)`
- overflow: hidden;
-`;
-
-const StyledDetailsButton = styled(Flex)`
- font: inherit;
- display: flex;
- width: 100%;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing('md')};
- padding: ${({ theme }) => `${theme.spacing('md')} 0`};
-`;
-
-const StyledExpandIcon = styled(ArrowDownCircle)`
- ${({ theme }) => theme.transition('common', 'normal')};
- transform: ${({ $isExpanded }) => ($isExpanded ? 'rotate(-180deg)' : 'rotate(0deg)')};
-`;
-
-export {
- StyledDetailsButton,
- StyledExpandIcon,
- StyledSpan,
- StyledSpinnerWrapper,
- StyledTransactionList,
- StyledTransactionListWrapper
-};
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
deleted file mode 100644
index 31d20a87a..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/TransactionList.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { Divider, Flex, P, Spinner } from '@gobob/ui';
-import { Trans } from '@lingui/macro';
-import { Fragment } from 'react';
-import { useIsClient } from 'usehooks-ts';
-
-import { TransactionItem } from './TransactionItem';
-import { StyledTransactionList } from './TransactionList.style';
-
-import { Transaction } from '@/types';
-
-type TransactionListProps = {
- isInitialLoading?: boolean;
- data?: Transaction[];
- onProveSuccess?: () => void;
- onRelaySuccess?: () => void;
-};
-
-const TransactionList = ({
- isInitialLoading,
- data,
- onProveSuccess,
- onRelaySuccess
-}: TransactionListProps): JSX.Element => {
- const isClient = useIsClient();
-
- const hasData = !!data?.length;
-
- return (
-
- {!isClient || isInitialLoading ? (
-
-
-
- Fetching bridging operations...
-
-
- ) : (
- <>
- {hasData ? (
- data.map((transaction, idx) => (
-
-
- {idx < data.length - 1 && }
-
- ))
- ) : (
-
-
- No bridging operations found
-
-
- )}
- >
- )}
-
- );
-};
-
-export { TransactionList };
diff --git a/apps/evm/src/components/ProfileDrawer/TransactionList/index.tsx b/apps/evm/src/components/ProfileDrawer/TransactionList/index.tsx
deleted file mode 100644
index 30e9c699e..000000000
--- a/apps/evm/src/components/ProfileDrawer/TransactionList/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { TransactionList } from './TransactionList';
diff --git a/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
new file mode 100644
index 000000000..81a9c214a
--- /dev/null
+++ b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
@@ -0,0 +1,96 @@
+import { Card, Flex, Modal, ModalBody, ModalHeader, ModalProps, P } from '@gobob/ui';
+import QRCode from 'react-qr-code';
+import { useAccount } from 'wagmi';
+import { useCopyToClipboard } from 'usehooks-ts';
+import { Trans } from '@lingui/macro';
+import { useState } from 'react';
+
+import { Chain } from '../Chain';
+
+import { useBtcAccount } from '@/hooks';
+import { L1_CHAIN, L2_CHAIN } from '@/constants';
+
+enum ReceiveSteps {
+ Main = 'main',
+ EVM = 'evm',
+ BTC = 'btc'
+}
+
+type ReceiveModalProps = Omit;
+
+const ReceiveModal = ({ onClose, ...props }: ReceiveModalProps): JSX.Element => {
+ const [step, setStep] = useState(ReceiveSteps.Main);
+
+ const { address: evmAddress } = useAccount();
+ const { address: btcAddress } = useBtcAccount();
+ const [, copy] = useCopyToClipboard();
+
+ const address = (step === ReceiveSteps.EVM ? evmAddress : btcAddress) || '';
+
+ return (
+
+ Receive crypto
+
+ {step === ReceiveSteps.Main && (
+
+
+ Fund your wallet(s) by transferring crypto from another wallet or account.
+
+ {evmAddress && (
+ setStep(ReceiveSteps.EVM)}>
+ EVM
+
+ )}
+ {btcAddress && (
+ setStep(ReceiveSteps.BTC)}>
+ BTC
+
+ )}
+
+ )}
+ {/* {token !== 'btc' && (
+
+
+ Ensure that you are transferring from the BOB Network to avoid any loss of funds.
+
+ )} */}
+ {step !== ReceiveSteps.Main && (
+ <>
+
+ {address}
+
+
+
+
+ >
+ )}
+ {step === ReceiveSteps.EVM && (
+
+ You can receive tokens on our supportred networks
+
+
+
+
+
+ )}
+
+
+ );
+};
+
+export { ReceiveModal };
diff --git a/apps/evm/src/components/ReceiveModal/index.tsx b/apps/evm/src/components/ReceiveModal/index.tsx
new file mode 100644
index 000000000..7aee75edb
--- /dev/null
+++ b/apps/evm/src/components/ReceiveModal/index.tsx
@@ -0,0 +1 @@
+export { ReceiveModal } from './ReceiveModal';
diff --git a/apps/evm/src/components/index.ts b/apps/evm/src/components/index.ts
index ea7439a5f..105709d74 100644
--- a/apps/evm/src/components/index.ts
+++ b/apps/evm/src/components/index.ts
@@ -1,12 +1,13 @@
export * from './AmountLabel';
+export * from './AuthButton';
export * from './Chain';
+export * from './ChainAsset';
export * from './ChainLogo';
export * from './Geoblock';
export * from './Layout';
-export * from './LoginSection';
-export * from './Trapezoid';
-export * from './WithdrawAlert';
export * from './LoginButton';
+export * from './LoginSection';
export * from './SignUpButton';
export * from './SpiceAmount';
-export * from './AuthButton';
+export * from './Trapezoid';
+export * from './WithdrawAlert';
diff --git a/packages/ui/src/components/Drawer/DesktopDrawer.tsx b/packages/ui/src/components/Drawer/DesktopDrawer.tsx
new file mode 100644
index 000000000..aa37a0b6b
--- /dev/null
+++ b/packages/ui/src/components/Drawer/DesktopDrawer.tsx
@@ -0,0 +1,62 @@
+'use client';
+
+import { forwardRef, useRef } from 'react';
+
+import { useDOMRef } from '../../hooks';
+import { DialogProps } from '../Dialog';
+import { Overlay } from '../Overlay';
+import { ElementTypeProp } from '../utils/types';
+
+import { StyledDialog } from './Drawer.style';
+import { DrawerWrapper, DrawerWrapperProps } from './DrawerWrapper';
+
+type Props = {
+ container?: Element;
+};
+
+type InheritAttrs = Omit;
+
+type DrawerProps = Props & InheritAttrs & ElementTypeProp;
+
+const Drawer = forwardRef(
+ (
+ {
+ children,
+ isDismissable = true,
+ isKeyboardDismissDisabled,
+ shouldCloseOnBlur,
+ container,
+ isOpen,
+ elementType = 'div',
+ ...props
+ },
+ ref
+ ): JSX.Element | null => {
+ const domRef = useDOMRef(ref);
+ const { onClose } = props;
+ const wrapperRef = useRef(null);
+
+ return (
+
+
+
+ {children}
+
+
+
+ );
+ }
+);
+
+Drawer.displayName = 'Drawer';
+
+export { Drawer };
+export type { DrawerProps };
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index aa8d5c867..faff88f7c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -571,6 +571,9 @@ importers:
react-otp-input:
specifier: ^3.1.1
version: 3.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-qr-code:
+ specifier: ^2.0.12
+ version: 2.0.14(react@18.3.1)
siwe:
specifier: ^2.1.4
version: 2.3.2(ethers@6.13.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))
From 697a6d5dada8fcc014ccde3bb5b18aac61c420d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Tue, 10 Dec 2024 12:26:24 +0000
Subject: [PATCH 10/16] feat: continue
---
.../ConnectButton/ConnectButton.style.tsx | 15 ++-
.../ConnectButton/ConnectButton.tsx | 93 ++++++++++++-------
.../ProfileDrawer/ProfileBtcWallet.tsx | 42 ++++++++-
.../ProfileDrawer/ProfileDrawer.style.tsx | 22 +----
.../ProfileDrawer/ProfileDrawer.tsx | 27 +++---
.../ProfileDrawer/ProfileTokenList.tsx | 5 +-
apps/evm/src/hooks/btc/index.ts | 1 +
7 files changed, 129 insertions(+), 76 deletions(-)
diff --git a/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx b/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
index 42b984905..a805b73af 100644
--- a/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
+++ b/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
@@ -1,6 +1,15 @@
import styled from 'styled-components';
-import { Drawer } from 'vaul';
-const StyledContent = styled(Drawer.Content)``;
+const StyledContentWrapper = styled.div`
+ background: ${({ theme }) => theme.color('grey-400')};
+`;
-export { StyledContent };
+const StyledMobileContentWrapper = styled(StyledContentWrapper)`
+ border-top-right-radius: ${({ theme }) => theme.rounded('lg')};
+ border-top-left-radius: ${({ theme }) => theme.rounded('lg')};
+ overflow-y: auto;
+ padding: 1rem;
+ flex: 1 1 0%;
+`;
+
+export { StyledContentWrapper, StyledMobileContentWrapper };
diff --git a/apps/evm/src/components/ConnectButton/ConnectButton.tsx b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
index 79049f838..2d5fcc9c1 100644
--- a/apps/evm/src/components/ConnectButton/ConnectButton.tsx
+++ b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
@@ -14,7 +14,7 @@ import { useTheme } from 'styled-components';
import { ProfileDrawer } from '../ProfileDrawer';
-import { StyledContent } from './ConnectButton.style';
+import { StyledMobileContentWrapper } from './ConnectButton.style';
import { useBtcAccount } from '@/hooks';
@@ -43,11 +43,7 @@ const Profile = ({
);
};
-const snapPoints = ['500px', 1];
-
const ConnectButton = (): JSX.Element => {
- const [snap, setSnap] = useState(snapPoints[0] as number);
-
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('s'));
@@ -73,13 +69,52 @@ const ConnectButton = (): JSX.Element => {
const handleClose = () => setOpen(false);
- const snapProps = isMobile ? { activeSnapPoint: snap, setActiveSnapPoint: setSnap, snapPoints } : undefined;
+ if (isMobile) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
return (
-
+
-
+
@@ -93,37 +128,23 @@ const ConnectButton = (): JSX.Element => {
backgroundColor: 'rgba(0, 0, 0, 0.6)'
}}
/>
-
-
-
+
+
);
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
index 752ebdaab..3fa95c637 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
@@ -2,16 +2,47 @@
import { WalletIcon } from '@dynamic-labs/wallet-book';
import { BTC } from '@gobob/icons';
-import { Card, Flex, Span } from '@gobob/ui';
+import { Button, Card, ChevronRight, Flex, Power, Span } from '@gobob/ui';
import { truncateBtcAddress } from '@gobob/utils';
+import { Trans } from '@lingui/macro';
-import { useBtcAccount, useBtcBalance } from '@/hooks';
+import { StyledWalletCard } from './ProfileDrawer.style';
-const ProfileBtcWallet = (): JSX.Element | null => {
+import { useBtcAccount, useBtcBalance, useBtcDynamicWallet } from '@/hooks';
+
+type ProfileBtcWalletProps = {
+ onPressConnect: () => void;
+ onUnlink: (id: string) => void;
+};
+
+const ProfileBtcWallet = ({ onPressConnect, onUnlink }: ProfileBtcWalletProps): JSX.Element | null => {
const { data: btcBalance } = useBtcBalance();
const { address: btcAddress, connector: btcConnector } = useBtcAccount();
+ const btcWallet = useBtcDynamicWallet();
- if (!btcConnector || !btcAddress) return null;
+ if (!btcConnector || !btcAddress || !btcWallet) {
+ return (
+
+
+
+
+ Connect BTC Wallet
+
+
+
+
+ );
+ }
return (
{
+ onUnlink(btcWallet.id)}>
+
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
index bc80577a8..81656521e 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.style.tsx
@@ -1,20 +1,8 @@
-import { Flex } from '@gobob/ui';
-import styled, { css } from 'styled-components';
+import { Card } from '@gobob/ui';
+import styled from 'styled-components';
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const SyledWrapper = styled(Flex)<{ snap: any }>`
- background: ${({ theme }) => theme.color('grey-400')};
- border-radius: ${({ theme }) => theme.rounded('lg')};
- ${({ snap }) => css`
- // @ts-expect-error
- overflow-y: ${snap === 1 ? 'auto' : undefined};
- overflow: ${snap !== 1 ? 'hidden' : undefined};
- `}
+const StyledWalletCard = styled(Card)`
+ min-height: 3.375rem;
`;
-const StyledTokenList = styled(Flex)`
- overflow-y: auto;
- inset: 0;
-`;
-
-export { StyledTokenList, SyledWrapper };
+export { StyledWalletCard };
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
index 1193cd1db..d1bcca08f 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
@@ -1,12 +1,11 @@
'use client';
-import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
-import { Button, Card, Cog, Flex, P, Power, QrCode, SolidCreditCard } from '@gobob/ui';
+import { useDynamicContext, useDynamicModals } from '@dynamic-labs/sdk-react-core';
+import { Button, Card, Flex, P, Power, QrCode, SolidCreditCard } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { useAccount } from 'wagmi';
import { ProfileBtcWallet } from './ProfileBtcWallet';
-import { SyledWrapper } from './ProfileDrawer.style';
import { ProfileEvmWallet } from './ProfileEvmWallet';
import { ProfileTag } from './ProfileTag';
import { ProfileTokenList } from './ProfileTokenList';
@@ -15,16 +14,15 @@ import { L1_CHAIN } from '@/constants';
import { useBtcAccount, useTotalBalance } from '@/hooks';
type ProfileDrawerProps = {
- isMobile: boolean;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- snap: any;
onClose: () => void;
};
-const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Element => {
+const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
const { setShowAuthFlow, user, handleLogOut } = useDynamicContext();
const { address: evmAddress, chain } = useAccount();
const { address: btcAddress } = useBtcAccount();
+ const { handleUnlinkWallet, setSelectedTabIndex } = useDynamicContext();
+ const { setShowLinkNewWalletModal } = useDynamicModals();
const chainId = chain?.id || L1_CHAIN;
@@ -49,14 +47,17 @@ const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Ele
onClose();
};
+ const handleConnectBtcWallet = () => {
+ setSelectedTabIndex(2);
+ setShowLinkNewWalletModal(true);
+ onClose();
+ };
+
return (
-
+
-
-
-
@@ -82,11 +83,11 @@ const ProfileDrawer = ({ snap, isMobile, onClose }: ProfileDrawerProps): JSX.Ele
-
+
-
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
index 58d721a57..81d7d7d1d 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
@@ -3,7 +3,6 @@ import { usePrices } from '@gobob/hooks';
import { BITCOIN } from '@gobob/tokens';
import { Flex, P } from '@gobob/ui';
-import { StyledTokenList } from './ProfileDrawer.style';
import { ProfileTokenListItem } from './ProfileTokenListItem';
import { useBalances, useBtcBalance, useTokens } from '@/hooks';
@@ -28,7 +27,7 @@ const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
const ethBalance = ethData && getBalance(ethData.raw.symbol);
return (
-
+
{ethBalance && ethData && (
{
))}
-
+
);
};
diff --git a/apps/evm/src/hooks/btc/index.ts b/apps/evm/src/hooks/btc/index.ts
index 34d846acc..d7b17f77a 100644
--- a/apps/evm/src/hooks/btc/index.ts
+++ b/apps/evm/src/hooks/btc/index.ts
@@ -1,4 +1,5 @@
export * from './useAccount';
+export * from './useDynamicWallet';
export * from './useBalance';
export * from './useFeeEstimate';
export * from './useFeeRate';
From 92089b2b27079c0448406d3b32d6b9930f417826 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Tue, 10 Dec 2024 17:38:44 +0000
Subject: [PATCH 11/16] feat: final
---
apps/evm/package.json | 1 -
apps/evm/src/app/[lang]/nested-providers.tsx | 3 +-
.../src/components/ChainAsset/ChainAsset.tsx | 9 +-
.../ConnectButton/ConnectButton.style.tsx | 64 +++++-
.../ConnectButton/ConnectButton.tsx | 143 ++++---------
.../ProfileDrawer/ProfileBtcWallet.tsx | 10 +-
.../ProfileDrawer/ProfileDrawer.tsx | 52 ++++-
.../ProfileDrawer/ProfileTokenList.tsx | 42 ++--
.../ProfileTag.tsx | 23 ++-
apps/evm/src/components/ProfileTag/index.tsx | 1 +
.../components/ReceiveModal/ReceiveModal.tsx | 195 +++++++++++++-----
apps/evm/src/components/index.ts | 1 +
apps/evm/src/constants/chain.ts | 4 +-
apps/evm/src/hooks/index.ts | 1 -
apps/evm/src/hooks/useGetTransactions.ts | 68 ------
apps/evm/src/lib/store.ts | 8 +
apps/evm/src/lib/wagmi/config.ts | 29 +--
packages/ui/package.json | 3 +-
.../src/components/Drawer/DesktopDrawer.tsx | 62 ------
packages/ui/src/icons/LinkSlash.tsx | 25 +++
packages/ui/src/icons/index.ts | 1 +
pnpm-lock.yaml | 41 +---
22 files changed, 394 insertions(+), 392 deletions(-)
rename apps/evm/src/components/{ProfileDrawer => ProfileTag}/ProfileTag.tsx (65%)
create mode 100644 apps/evm/src/components/ProfileTag/index.tsx
delete mode 100644 apps/evm/src/hooks/useGetTransactions.ts
delete mode 100644 packages/ui/src/components/Drawer/DesktopDrawer.tsx
create mode 100644 packages/ui/src/icons/LinkSlash.tsx
diff --git a/apps/evm/package.json b/apps/evm/package.json
index bf693c0b8..7b84e3885 100644
--- a/apps/evm/package.json
+++ b/apps/evm/package.json
@@ -55,7 +55,6 @@
"next": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
- "react-jazzicon": "^1.0.4",
"react-multi-carousel": "^2.8.5",
"react-otp-input": "^3.1.1",
"react-qr-code": "^2.0.12",
diff --git a/apps/evm/src/app/[lang]/nested-providers.tsx b/apps/evm/src/app/[lang]/nested-providers.tsx
index 5091cc330..9ea8c196e 100644
--- a/apps/evm/src/app/[lang]/nested-providers.tsx
+++ b/apps/evm/src/app/[lang]/nested-providers.tsx
@@ -10,7 +10,7 @@ import { useLocalStorage } from 'usehooks-ts';
import { isAddressEqual } from 'viem';
import { useAccount, useAccountEffect, useChainId, useConfig, useSwitchChain } from 'wagmi';
-import { Header, Layout, Sidebar } from '@/components';
+import { Header, Layout, ReceiveModal, Sidebar } from '@/components';
import { isClient, L2_CHAIN, LocalStorageKey } from '@/constants';
import { useBalances, useGetUser, useLogout, useTokens } from '@/hooks';
import { StyledComponentsRegistry } from '@/lib/styled-components';
@@ -140,6 +140,7 @@ export function NestedProviders({ children }: PropsWithChildren) {
+
diff --git a/apps/evm/src/components/ChainAsset/ChainAsset.tsx b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
index a87e3bf33..4a301ec9f 100644
--- a/apps/evm/src/components/ChainAsset/ChainAsset.tsx
+++ b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
@@ -10,19 +10,18 @@ import { StyledChain, StyledWrapper } from './ChainAsset.style';
type Props = {
chainId: ChainId | 'BTC';
asset: ReactNode;
- chainProps: Omit;
+ chainProps?: Omit;
+ chainLogo?: ReactNode;
};
type InheritAttrs = Omit;
type ChainAssetProps = Props & InheritAttrs;
-const ChainAsset = ({ asset, chainId, chainProps, ...props }: ChainAssetProps) => (
+const ChainAsset = ({ asset, chainId, chainLogo, chainProps, ...props }: ChainAssetProps) => (
{asset}
-
-
-
+ {chainLogo || }
);
diff --git a/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx b/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
index a805b73af..32fc3187a 100644
--- a/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
+++ b/apps/evm/src/components/ConnectButton/ConnectButton.style.tsx
@@ -1,15 +1,59 @@
-import styled from 'styled-components';
+import styled, { css } from 'styled-components';
+import { Drawer } from 'vaul';
-const StyledContentWrapper = styled.div`
- background: ${({ theme }) => theme.color('grey-400')};
+const StyledContent = styled(Drawer.Content)`
+ ${({ theme }) => {
+ return css`
+ display: flex;
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin-top: 6rem;
+ flex-direction: column;
+ outline-style: none;
+ height: calc(100% - 72px);
+
+ @media ${theme.breakpoints.up('s')} {
+ top: 0.5rem;
+ right: 0.5rem;
+ bottom: 0.5rem;
+ left: unset;
+ height: 100%;
+ margin-top: 0;
+
+ width: 310px;
+ --initial-transform: calc(100% + 8px);
+ }
+ `;
+ }}
`;
-const StyledMobileContentWrapper = styled(StyledContentWrapper)`
- border-top-right-radius: ${({ theme }) => theme.rounded('lg')};
- border-top-left-radius: ${({ theme }) => theme.rounded('lg')};
- overflow-y: auto;
- padding: 1rem;
- flex: 1 1 0%;
+const StyledUnderlay = styled(Drawer.Overlay)`
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+`;
+
+const StyledMobileContentWrapper = styled.div`
+ ${({ theme }) => {
+ return css`
+ background: ${theme.color('grey-400')};
+ border: 1px solid ${theme.color('grey-300')};
+ border-top-right-radius: ${theme.rounded('xl')};
+ border-top-left-radius: ${theme.rounded('xl')};
+ overflow-y: auto;
+ padding: 1rem;
+ flex: 1 1 0%;
+
+ @media ${theme.breakpoints.up('md')} {
+ border-radius: ${theme.rounded('xl')};
+ }
+ `;
+ }}
`;
-export { StyledContentWrapper, StyledMobileContentWrapper };
+export { StyledContent, StyledUnderlay, StyledMobileContentWrapper };
diff --git a/apps/evm/src/components/ConnectButton/ConnectButton.tsx b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
index 2d5fcc9c1..bb07ffd5a 100644
--- a/apps/evm/src/components/ConnectButton/ConnectButton.tsx
+++ b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
@@ -1,61 +1,38 @@
'use client';
-import { useDynamicContext, UserProfile } from '@dynamic-labs/sdk-react-core';
-import { Button, Flex, Span } from '@gobob/ui';
-import { truncateBtcAddress, truncateEthAddress } from '@gobob/utils';
+import { useDynamicContext, useIsLoggedIn } from '@dynamic-labs/sdk-react-core';
+import { Button } from '@gobob/ui';
import { Trans } from '@lingui/macro';
-import ProfileAvatar from 'boring-avatars';
import { useState } from 'react';
-import { Address } from 'viem';
-import { useAccount } from 'wagmi';
-import { Drawer } from 'vaul';
-import { useMediaQuery } from 'usehooks-ts';
import { useTheme } from 'styled-components';
+import { useMediaQuery } from 'usehooks-ts';
+import { Drawer } from 'vaul';
+import { useAccount } from 'wagmi';
+import { useStore } from '@tanstack/react-store';
import { ProfileDrawer } from '../ProfileDrawer';
+import { ProfileTag } from '../ProfileTag';
-import { StyledMobileContentWrapper } from './ConnectButton.style';
+import { StyledContent, StyledMobileContentWrapper, StyledUnderlay } from './ConnectButton.style';
import { useBtcAccount } from '@/hooks';
-
-const Profile = ({
- evmAddress,
- btcAddress,
- user,
- hideAddress
-}: {
- btcAddress?: string;
- evmAddress?: Address;
- user?: UserProfile;
- hideAddress?: boolean;
-}) => {
- const displayedAddress = evmAddress
- ? truncateEthAddress(evmAddress)
- : btcAddress
- ? truncateBtcAddress(btcAddress)
- : undefined;
-
- return (
-
- {user?.userId ? : undefined}
- {!hideAddress && {displayedAddress}}
-
- );
-};
+import { store } from '@/lib/store';
const ConnectButton = (): JSX.Element => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('s'));
+ const isReceiveModalOpen = useStore(store, (state) => state.shared.isReceiveModalOpen);
+
const { setShowAuthFlow, user } = useDynamicContext();
const { address: evmAddress } = useAccount();
const { address: btcAddress } = useBtcAccount();
-
+ const isLoggedIn = useIsLoggedIn();
const [isOpen, setOpen] = useState(false);
- const isAuthenticated = evmAddress || btcAddress;
+ // const isAuthenticated = evmAddress || btcAddress;
- if (!isAuthenticated) {
+ if (!isLoggedIn) {
const handleConnect = () => {
setShowAuthFlow(true);
};
@@ -69,82 +46,34 @@ const ConnectButton = (): JSX.Element => {
const handleClose = () => setOpen(false);
- if (isMobile) {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
+ const isLoading = isLoggedIn && !(evmAddress || btcAddress);
return (
-
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
);
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
index 3fa95c637..8b0c34876 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
@@ -2,7 +2,7 @@
import { WalletIcon } from '@dynamic-labs/wallet-book';
import { BTC } from '@gobob/icons';
-import { Button, Card, ChevronRight, Flex, Power, Span } from '@gobob/ui';
+import { Button, Card, ChevronRight, Flex, LinkSlash, Span, Tooltip } from '@gobob/ui';
import { truncateBtcAddress } from '@gobob/utils';
import { Trans } from '@lingui/macro';
@@ -67,9 +67,11 @@ const ProfileBtcWallet = ({ onPressConnect, onUnlink }: ProfileBtcWalletProps):
- onUnlink(btcWallet.id)}>
-
-
+ Unlink wallet}>
+ onUnlink(btcWallet.id)}>
+
+
+
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
index d1bcca08f..e4676b184 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
@@ -5,13 +5,15 @@ import { Button, Card, Flex, P, Power, QrCode, SolidCreditCard } from '@gobob/ui
import { Trans } from '@lingui/macro';
import { useAccount } from 'wagmi';
+import { ProfileTag } from '../ProfileTag';
+
import { ProfileBtcWallet } from './ProfileBtcWallet';
import { ProfileEvmWallet } from './ProfileEvmWallet';
-import { ProfileTag } from './ProfileTag';
import { ProfileTokenList } from './ProfileTokenList';
import { L1_CHAIN } from '@/constants';
import { useBtcAccount, useTotalBalance } from '@/hooks';
+import { store } from '@/lib/store';
type ProfileDrawerProps = {
onClose: () => void;
@@ -53,9 +55,23 @@ const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
onClose();
};
+ const handlePressBuy = () => {
+ window.open('https://checkout.banxa.com/?coinType=ETH&fiatType=EUR&blockchain=BOB', '_blank', 'noreferrer');
+ onClose();
+ };
+
+ const handlePressReceive = () =>
+ store.setState((state) => ({
+ ...state,
+ shared: {
+ ...state.shared,
+ isReceiveModalOpen: true
+ }
+ }));
+
return (
-
+
@@ -63,28 +79,44 @@ const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
-
+
{formatted}
-
+
Buy
-
+
Receive
-
-
-
-
-
+
+
+
+
+
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
index 81d7d7d1d..1dcbb2a53 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
@@ -1,7 +1,8 @@
import { CurrencyAmount } from '@gobob/currency';
import { usePrices } from '@gobob/hooks';
import { BITCOIN } from '@gobob/tokens';
-import { Flex, P } from '@gobob/ui';
+import { Card, Flex, P } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
import { ProfileTokenListItem } from './ProfileTokenListItem';
@@ -27,7 +28,12 @@ const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
const ethBalance = ethData && getBalance(ethData.raw.symbol);
return (
-
+
+
+
+ Wallet
+
+
{ethBalance && ethData && (
{
name='Bitcoin'
symbol='BTC'
/>
-
-
- Tokens
-
-
- {list?.map((item) => (
-
- ))}
-
-
+
+ Tokens
+
+ {list?.map((item) => (
+
+ ))}
);
};
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx b/apps/evm/src/components/ProfileTag/ProfileTag.tsx
similarity index 65%
rename from apps/evm/src/components/ProfileDrawer/ProfileTag.tsx
rename to apps/evm/src/components/ProfileTag/ProfileTag.tsx
index 03fe175b1..decb6e77d 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTag.tsx
+++ b/apps/evm/src/components/ProfileTag/ProfileTag.tsx
@@ -1,7 +1,7 @@
'use client';
import { UserProfile } from '@dynamic-labs/sdk-react-core';
-import { Flex, Span } from '@gobob/ui';
+import { Flex, Skeleton, Span } from '@gobob/ui';
import { truncateBtcAddress, truncateEthAddress } from '@gobob/utils';
import ProfileAvatar from 'boring-avatars';
import { Address } from 'viem';
@@ -22,14 +22,25 @@ const ProfileTag = ({
btcAddress,
user,
size = 's',
- isLoading
+ isLoading,
+ hideAddress
}: {
btcAddress?: string;
evmAddress?: Address;
user?: UserProfile;
size?: 's' | 'md';
isLoading?: boolean;
+ hideAddress?: boolean;
}) => {
+ if (isLoading) {
+ return (
+
+
+ {!hideAddress && }
+
+ );
+ }
+
const displayedAddress = evmAddress
? truncateEthAddress(evmAddress)
: btcAddress
@@ -39,9 +50,11 @@ const ProfileTag = ({
return (
{user?.userId ? : undefined}
-
- {displayedAddress}
-
+ {!hideAddress && (
+
+ {displayedAddress}
+
+ )}
);
};
diff --git a/apps/evm/src/components/ProfileTag/index.tsx b/apps/evm/src/components/ProfileTag/index.tsx
new file mode 100644
index 000000000..0af92c5d2
--- /dev/null
+++ b/apps/evm/src/components/ProfileTag/index.tsx
@@ -0,0 +1 @@
+export { ProfileTag } from './ProfileTag';
diff --git a/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
index 81a9c214a..560fc3dec 100644
--- a/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
+++ b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
@@ -1,14 +1,35 @@
-import { Card, Flex, Modal, ModalBody, ModalHeader, ModalProps, P } from '@gobob/ui';
+import {
+ ArrowLeft,
+ Button,
+ Card,
+ DocumentDuplicate,
+ Flex,
+ Modal,
+ ModalBody,
+ ModalHeader,
+ P,
+ QrCode,
+ Span,
+ UnstyledButton
+} from '@gobob/ui';
import QRCode from 'react-qr-code';
import { useAccount } from 'wagmi';
import { useCopyToClipboard } from 'usehooks-ts';
import { Trans } from '@lingui/macro';
import { useState } from 'react';
+import { useStore } from '@tanstack/react-store';
+import { truncateBtcAddress, truncateEthAddress } from '@gobob/utils';
+import { BTC, ETH } from '@gobob/icons';
+import { WalletIcon } from '@dynamic-labs/wallet-book';
+import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
+import { ChainId } from '@gobob/chains';
import { Chain } from '../Chain';
+import { ChainAsset } from '../ChainAsset/ChainAsset';
import { useBtcAccount } from '@/hooks';
import { L1_CHAIN, L2_CHAIN } from '@/constants';
+import { store } from '@/lib/store';
enum ReceiveSteps {
Main = 'main',
@@ -16,78 +37,158 @@ enum ReceiveSteps {
BTC = 'btc'
}
-type ReceiveModalProps = Omit;
+const ReceiveModal = (): JSX.Element => {
+ const isReceiveModalOpen = useStore(store, (state) => state.shared.isReceiveModalOpen);
-const ReceiveModal = ({ onClose, ...props }: ReceiveModalProps): JSX.Element => {
const [step, setStep] = useState(ReceiveSteps.Main);
-
+ const { primaryWallet } = useDynamicContext();
const { address: evmAddress } = useAccount();
- const { address: btcAddress } = useBtcAccount();
+ const { address: btcAddress, connector: btcConnector } = useBtcAccount();
const [, copy] = useCopyToClipboard();
const address = (step === ReceiveSteps.EVM ? evmAddress : btcAddress) || '';
+ const shortAddress =
+ step === ReceiveSteps.EVM
+ ? truncateEthAddress(evmAddress || '')
+ : btcAddress
+ ? truncateBtcAddress(btcAddress)
+ : undefined;
+
+ const handleClose = () =>
+ store.setState((state) => ({
+ ...state,
+ shared: {
+ ...state.shared,
+ isReceiveModalOpen: false
+ }
+ }));
+
return (
-
- Receive crypto
-
+
+
+ {step === ReceiveSteps.Main ? (
+ Receive crypto
+ ) : (
+ setStep(ReceiveSteps.Main)}>
+
+
+
+ Back
+
+
+
+ )}
+
+
{step === ReceiveSteps.Main && (
-
-
+
+
Fund your wallet(s) by transferring crypto from another wallet or account.
- {evmAddress && (
- setStep(ReceiveSteps.EVM)}>
- EVM
-
- )}
- {btcAddress && (
- setStep(ReceiveSteps.BTC)}>
- BTC
-
- )}
+
+ {evmAddress && (
+
+
+ }
+ chainId={ChainId.ETHEREUM}
+ chainLogo={
+ primaryWallet && (
+
+ )
+ }
+ />
+
+ {truncateEthAddress(evmAddress)}
+
+
+
+ copy(evmAddress)}>
+
+
+ setStep(ReceiveSteps.EVM)}>
+
+
+
+
+ )}
+ {btcAddress && (
+
+
+ }
+ chainId={ChainId.ETHEREUM}
+ chainLogo={
+ btcConnector && (
+
+ )
+ }
+ />
+
+ {truncateBtcAddress(btcAddress)}
+
+
+
+ copy(btcAddress)}>
+
+
+ setStep(ReceiveSteps.BTC)}>
+
+
+
+
+ )}
+
)}
- {/* {token !== 'btc' && (
-
-
- Ensure that you are transferring from the BOB Network to avoid any loss of funds.
-
- )} */}
{step !== ReceiveSteps.Main && (
<>
-
- {address}
+
+ {shortAddress}
-
+
+ {step === ReceiveSteps.EVM && (
+
+
+ You can receive tokens on our supported networks
+
+
+
+
+
+
+ )}
>
)}
- {step === ReceiveSteps.EVM && (
-
- You can receive tokens on our supportred networks
-
-
-
-
-
- )}
);
diff --git a/apps/evm/src/components/index.ts b/apps/evm/src/components/index.ts
index 105709d74..8a1f42f06 100644
--- a/apps/evm/src/components/index.ts
+++ b/apps/evm/src/components/index.ts
@@ -11,3 +11,4 @@ export * from './SignUpButton';
export * from './SpiceAmount';
export * from './Trapezoid';
export * from './WithdrawAlert';
+export * from './ReceiveModal';
diff --git a/apps/evm/src/constants/chain.ts b/apps/evm/src/constants/chain.ts
index 7000d88d5..38487f0f9 100644
--- a/apps/evm/src/constants/chain.ts
+++ b/apps/evm/src/constants/chain.ts
@@ -21,11 +21,9 @@ if (!L2_CHAIN || !validL2Chains.includes(L2_CHAIN) || (isL1Testnet && !isTestnet
throw new Error('Missing or invalid L2 chain');
}
-const isValidChain = (chainId: ChainId) => chainId === L1_CHAIN || chainId === L2_CHAIN;
-
const isProd = !isL1Testnet;
const chainL1: Chain = isProd ? mainnet : sepolia;
const chainL2: Chain = isProd ? bob : bobSepolia;
-export { chainL1, chainL2, isProd, isValidChain, L1_CHAIN, L2_CHAIN };
+export { chainL1, chainL2, isProd, L1_CHAIN, L2_CHAIN };
diff --git a/apps/evm/src/hooks/index.ts b/apps/evm/src/hooks/index.ts
index 2757d0bdb..d7b723dc3 100644
--- a/apps/evm/src/hooks/index.ts
+++ b/apps/evm/src/hooks/index.ts
@@ -19,6 +19,5 @@ export * from './useSubscribeBalances';
export * from './useTokens';
export * from './useTotalBalance';
export * from './useWalletClient';
-export * from './useGetTransactions';
export * from './btc';
diff --git a/apps/evm/src/hooks/useGetTransactions.ts b/apps/evm/src/hooks/useGetTransactions.ts
deleted file mode 100644
index 261d99440..000000000
--- a/apps/evm/src/hooks/useGetTransactions.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-'use client';
-
-import { useStore } from '@tanstack/react-store';
-import { watchAccount } from '@wagmi/core';
-import { useEffect, useMemo, useRef } from 'react';
-import { useConfig } from 'wagmi';
-
-import { useGetBridgeTransactions, useGetGatewayTransactions } from '@/app/[lang]/(bridge)/hooks';
-import { store } from '@/lib/store';
-
-const useGetTransactions = () => {
- const config = useConfig();
- const gateway = useGetGatewayTransactions();
- const bridge = useGetBridgeTransactions();
-
- const isInitialLoading = useStore(store, (state) => state.bridge.transactions.isInitialLoading);
-
- const isLoading = gateway.isLoading || bridge.isLoading;
-
- const watchAccountRef = useRef<() => void>();
-
- useEffect(() => {
- watchAccountRef.current = watchAccount(config, {
- onChange: (account) => {
- if (account.address) {
- store.setState((state) => ({
- ...state,
- bridge: { ...state.bridge, transactions: { ...state.bridge.transactions, isInitialLoading: true } }
- }));
- }
- }
- });
-
- // Cleanup by calling unwatch to unsubscribe from the account change event
- return () => watchAccountRef.current?.();
- }, [config]);
-
- useEffect(() => {
- if (isInitialLoading && !isLoading) {
- store.setState((state) => ({
- ...state,
- bridge: { ...state.bridge, transactions: { ...state.bridge.transactions, isInitialLoading: false } }
- }));
- }
- }, [isInitialLoading, isLoading]);
-
- const data = useMemo(() => {
- const data = [...(gateway.data || []), ...bridge.data];
-
- return data?.sort((a, b) => b.date.getTime() - a.date.getTime());
- }, [bridge.data, gateway.data]);
-
- return {
- data,
- refetch: {
- gateway: gateway.refetch,
- bridge: bridge.refetch
- },
- addPlaceholderTransaction: {
- bridge: bridge.addPlaceholderTransaction
- },
- txPendingUserAction: bridge.txPendingUserAction,
- isInitialLoading,
- isLoading
- };
-};
-
-export { useGetTransactions };
diff --git a/apps/evm/src/lib/store.ts b/apps/evm/src/lib/store.ts
index 2b62f13d2..227123038 100644
--- a/apps/evm/src/lib/store.ts
+++ b/apps/evm/src/lib/store.ts
@@ -2,6 +2,10 @@ import { Store as StoreLib } from '@tanstack/react-store';
import { BridgeTransaction } from '../types';
+type SharedStore = {
+ isReceiveModalOpen: boolean;
+};
+
type BridgeStore = {
transactions: {
isInitialLoading: boolean;
@@ -18,11 +22,15 @@ type StakeStore = {
};
type Store = {
+ shared: SharedStore;
bridge: BridgeStore;
stake: StakeStore;
};
const store = new StoreLib({
+ shared: {
+ isReceiveModalOpen: false
+ },
bridge: {
transactions: {
isInitialLoading: true,
diff --git a/apps/evm/src/lib/wagmi/config.ts b/apps/evm/src/lib/wagmi/config.ts
index e8598aa0c..6034013e3 100644
--- a/apps/evm/src/lib/wagmi/config.ts
+++ b/apps/evm/src/lib/wagmi/config.ts
@@ -1,12 +1,13 @@
import { cookieStorage, createConfig, createStorage, http } from 'wagmi';
-import { coinbaseWallet, injected } from 'wagmi/connectors';
+import { coinbaseWallet, injected, walletConnect } from 'wagmi/connectors';
+import { getWagmiConnectorV2 } from '@binance/w3w-wagmi-connector-v2';
import { Config } from './types';
import { bob, bobSepolia } from './bob';
import { mainnet } from './mainnet';
import { sepolia } from './sepolia';
-// const binanceConnector = getWagmiConnectorV2();
+const binanceConnector = getWagmiConnectorV2();
const testnetChains = [bobSepolia, sepolia];
@@ -23,21 +24,21 @@ const getConfig = ({ isProd, multiInjectedProviderDiscovery }: Config) => {
})
]
: []),
- // walletConnect({
- // showQrModal: true,
- // projectId: 'd9a2f927549acc3da9e4893729772641',
- // metadata: {
- // name: 'BOB',
- // description: 'BOB is a hybrid L2 that combines the security of Bitcoin with the versatility of Ethereum',
- // url: 'https://www.app.gobob.xyz',
- // icons: ['https://uploads-ssl.webflow.com/64e85c2f3609488b3ed725f4/64ecae53ef4b561482f1c49f_bob1.jpg']
- // }
- // }),
+ walletConnect({
+ showQrModal: true,
+ projectId: 'd9a2f927549acc3da9e4893729772641',
+ metadata: {
+ name: 'BOB',
+ description: 'BOB is a hybrid L2 that combines the security of Bitcoin with the versatility of Ethereum',
+ url: 'https://www.app.gobob.xyz',
+ icons: ['https://uploads-ssl.webflow.com/64e85c2f3609488b3ed725f4/64ecae53ef4b561482f1c49f_bob1.jpg']
+ }
+ }),
coinbaseWallet({
appName: 'BOB',
appLogoUrl: 'https://uploads-ssl.webflow.com/64e85c2f3609488b3ed725f4/64ecae53ef4b561482f1c49f_bob1.jpg'
- })
- // binanceConnector()
+ }),
+ binanceConnector()
];
return createConfig({
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 8dea28e4d..78ec8499f 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -78,8 +78,7 @@
"react-toastify": "^10.0.5",
"react-transition-group": "^4.4.5",
"react-use": "^17.4.0",
- "scroll-into-view-if-needed": "^3.1.0",
- "vaul": "^1.1.1"
+ "scroll-into-view-if-needed": "^3.1.0"
},
"peerDependencies": {
"react": "catalog:uiPeerDeps",
diff --git a/packages/ui/src/components/Drawer/DesktopDrawer.tsx b/packages/ui/src/components/Drawer/DesktopDrawer.tsx
deleted file mode 100644
index aa37a0b6b..000000000
--- a/packages/ui/src/components/Drawer/DesktopDrawer.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-'use client';
-
-import { forwardRef, useRef } from 'react';
-
-import { useDOMRef } from '../../hooks';
-import { DialogProps } from '../Dialog';
-import { Overlay } from '../Overlay';
-import { ElementTypeProp } from '../utils/types';
-
-import { StyledDialog } from './Drawer.style';
-import { DrawerWrapper, DrawerWrapperProps } from './DrawerWrapper';
-
-type Props = {
- container?: Element;
-};
-
-type InheritAttrs = Omit;
-
-type DrawerProps = Props & InheritAttrs & ElementTypeProp;
-
-const Drawer = forwardRef(
- (
- {
- children,
- isDismissable = true,
- isKeyboardDismissDisabled,
- shouldCloseOnBlur,
- container,
- isOpen,
- elementType = 'div',
- ...props
- },
- ref
- ): JSX.Element | null => {
- const domRef = useDOMRef(ref);
- const { onClose } = props;
- const wrapperRef = useRef(null);
-
- return (
-
-
-
- {children}
-
-
-
- );
- }
-);
-
-Drawer.displayName = 'Drawer';
-
-export { Drawer };
-export type { DrawerProps };
diff --git a/packages/ui/src/icons/LinkSlash.tsx b/packages/ui/src/icons/LinkSlash.tsx
new file mode 100644
index 000000000..104208670
--- /dev/null
+++ b/packages/ui/src/icons/LinkSlash.tsx
@@ -0,0 +1,25 @@
+import { forwardRef } from 'react';
+
+import { Icon, IconProps } from '../components';
+
+const LinkSlash = forwardRef((props, ref) => (
+
+
+
+));
+
+LinkSlash.displayName = 'LinkSlash';
+
+export { LinkSlash };
diff --git a/packages/ui/src/icons/index.ts b/packages/ui/src/icons/index.ts
index 2e4eae5a1..928a73b98 100644
--- a/packages/ui/src/icons/index.ts
+++ b/packages/ui/src/icons/index.ts
@@ -28,6 +28,7 @@ export { EllipsisHorizontal } from './EllipsisHorizontal';
export { EllipsisVertical } from './EllipsisVertical';
export { ExclamationCircle } from './ExclamationCircle';
export { InformationCircle } from './InformationCircle';
+export { LinkSlash } from './LinkSlash';
export { ListBullet } from './ListBullet';
export { PencilSquare } from './PencilSquare';
export { Photo } from './Photo';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index faff88f7c..8e56c23ec 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -562,9 +562,6 @@ importers:
react-dom:
specifier: ^18.2.0
version: 18.3.1(react@18.3.1)
- react-jazzicon:
- specifier: ^1.0.4
- version: 1.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-multi-carousel:
specifier: ^2.8.5
version: 2.8.5
@@ -866,9 +863,6 @@ importers:
scroll-into-view-if-needed:
specifier: ^3.1.0
version: 3.1.0
- vaul:
- specifier: ^1.1.1
- version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
devDependencies:
'@gobob/test-utils':
specifier: workspace:^
@@ -9848,9 +9842,6 @@ packages:
resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==}
engines: {node: '>= 7.6.0'}
- mersenne-twister@1.1.0:
- resolution: {integrity: sha512-mUYWsMKNrm4lfygPkL3OfGzOPTR2DBlTkBNHM//F6hGp8cLThY897crAlk3/Jo17LEOOjQUrNAx6DvgO77QJkA==}
-
methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
@@ -11041,12 +11032,6 @@ packages:
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
- react-jazzicon@1.0.4:
- resolution: {integrity: sha512-/3kWv5vtAhI18GBFoqjpxRTtL+EImuB73PAC02r/zJQ6E+PAUmoBx8edYvTCIYHwS01uFf6N3elTDqSrVPwg4w==}
- peerDependencies:
- react: ^18.2.0
- react-dom: ^18.2.0
-
react-loading-skeleton@3.5.0:
resolution: {integrity: sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==}
peerDependencies:
@@ -14428,7 +14413,7 @@ snapshots:
'@types/node': 20.5.1
chalk: 4.1.2
cosmiconfig: 8.3.6(typescript@5.4.5)
- cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5)
+ cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.4.5))(typescript@5.4.5)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -15655,14 +15640,14 @@ snapshots:
'@hpke/dhkem-x25519@1.6.0':
dependencies:
'@hpke/common': 1.6.0
- '@noble/curves': 1.6.0
- '@noble/hashes': 1.5.0
+ '@noble/curves': 1.7.0
+ '@noble/hashes': 1.6.1
'@hpke/dhkem-x448@1.6.0':
dependencies:
'@hpke/common': 1.6.0
- '@noble/curves': 1.6.0
- '@noble/hashes': 1.5.0
+ '@noble/curves': 1.7.0
+ '@noble/hashes': 1.6.1
'@humanwhocodes/config-array@0.11.14':
dependencies:
@@ -22487,7 +22472,7 @@ snapshots:
core-util-is@1.0.3: {}
- cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5):
+ cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.4.5))(typescript@5.4.5):
dependencies:
'@types/node': 20.5.1
cosmiconfig: 8.3.6(typescript@5.4.5)
@@ -23413,7 +23398,7 @@ snapshots:
'@typescript-eslint/parser': 7.13.0(eslint@8.57.0)(typescript@5.4.5)
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
eslint-plugin-react: 7.34.2(eslint@8.57.0)
@@ -23437,7 +23422,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.3.7(supports-color@8.1.1)
@@ -23463,7 +23448,7 @@ snapshots:
'@typescript-eslint/parser': 7.13.0(eslint@8.57.0)(typescript@5.4.5)
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0)
transitivePeerDependencies:
- supports-color
@@ -25915,8 +25900,6 @@ snapshots:
treeify: 1.1.0
web3-utils: 1.10.4
- mersenne-twister@1.1.0: {}
-
methods@1.1.2: {}
metro-babel-transformer@0.80.9:
@@ -27258,12 +27241,6 @@ snapshots:
react-is@18.3.1: {}
- react-jazzicon@1.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
- dependencies:
- mersenne-twister: 1.1.0
- react: 18.3.1
- react-dom: 18.3.1(react@18.3.1)
-
react-loading-skeleton@3.5.0(react@18.3.1):
dependencies:
react: 18.3.1
From dbc359ffa119b5361799fa1d9bab68eee5301730 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Wed, 11 Dec 2024 17:52:23 +0000
Subject: [PATCH 12/16] feat: improvements
---
.../app/[lang]/(bridge)/hooks/useGateway.ts | 4 +-
.../src/components/ChainAsset/ChainAsset.tsx | 4 +-
.../ConnectButton/ConnectButton.tsx | 24 +--
.../components/CopyAddress/CopyAddress.tsx | 71 +++++++
apps/evm/src/components/CopyAddress/index.tsx | 1 +
.../src/components/CopyButton/CopyButton.tsx | 41 ++++
apps/evm/src/components/CopyButton/index.tsx | 1 +
.../ProfileDrawer/ProfileBtcWallet.tsx | 37 +++-
.../ProfileDrawer/ProfileDrawer.tsx | 22 +-
.../ProfileDrawer/ProfileEvmWallet.tsx | 13 +-
.../ProfileDrawer/ProfileTokenList.tsx | 26 ++-
.../ProfileDrawer/ProfileTokenListItem.tsx | 36 ++--
.../src/components/ProfileTag/ProfileTag.tsx | 67 ++++--
.../components/ReceiveModal/ReceiveModal.tsx | 41 ++--
apps/evm/src/components/index.ts | 3 +-
apps/evm/src/hooks/btc/useFeeEstimate.tsx | 2 +-
apps/evm/src/hooks/index.ts | 1 +
apps/evm/src/hooks/useIntervalTooltip.ts | 28 +++
apps/evm/src/hooks/useTotalBalance.ts | 44 ++--
packages/ui/package.json | 2 +-
packages/ui/src/icons/CopyClipboard.tsx | 16 ++
packages/ui/src/icons/index.ts | 1 +
pnpm-lock.yaml | 195 +++++++++---------
pnpm-workspace.yaml | 1 +
24 files changed, 473 insertions(+), 208 deletions(-)
create mode 100644 apps/evm/src/components/CopyAddress/CopyAddress.tsx
create mode 100644 apps/evm/src/components/CopyAddress/index.tsx
create mode 100644 apps/evm/src/components/CopyButton/CopyButton.tsx
create mode 100644 apps/evm/src/components/CopyButton/index.tsx
create mode 100644 apps/evm/src/hooks/useIntervalTooltip.ts
create mode 100644 packages/ui/src/icons/CopyClipboard.tsx
diff --git a/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts b/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
index 31910efb6..1edef79be 100644
--- a/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
+++ b/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
@@ -226,7 +226,9 @@ const useGateway = ({ params, onError, onMutate, onSuccess }: UseGatewayLiquidit
feeRate: feeRate,
query: {
enabled: Boolean(satsBalance && satsBalance.total > 0n && evmAddress),
- select: (data) => CurrencyAmount.fromRawAmount(BITCOIN, data.amount)
+ select: (data) => {
+ return data.amount ? CurrencyAmount.fromRawAmount(BITCOIN, data.amount) : null;
+ }
}
});
diff --git a/apps/evm/src/components/ChainAsset/ChainAsset.tsx b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
index 4a301ec9f..4fe6f8d84 100644
--- a/apps/evm/src/components/ChainAsset/ChainAsset.tsx
+++ b/apps/evm/src/components/ChainAsset/ChainAsset.tsx
@@ -8,7 +8,7 @@ import { ChainLogoProps } from '../ChainLogo/ChainLogo';
import { StyledChain, StyledWrapper } from './ChainAsset.style';
type Props = {
- chainId: ChainId | 'BTC';
+ chainId?: ChainId | 'BTC';
asset: ReactNode;
chainProps?: Omit;
chainLogo?: ReactNode;
@@ -21,7 +21,7 @@ type ChainAssetProps = Props & InheritAttrs;
const ChainAsset = ({ asset, chainId, chainLogo, chainProps, ...props }: ChainAssetProps) => (
{asset}
- {chainLogo || }
+ {chainLogo || (chainId ? : undefined)}
);
diff --git a/apps/evm/src/components/ConnectButton/ConnectButton.tsx b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
index bb07ffd5a..0a4b22b4d 100644
--- a/apps/evm/src/components/ConnectButton/ConnectButton.tsx
+++ b/apps/evm/src/components/ConnectButton/ConnectButton.tsx
@@ -3,12 +3,12 @@
import { useDynamicContext, useIsLoggedIn } from '@dynamic-labs/sdk-react-core';
import { Button } from '@gobob/ui';
import { Trans } from '@lingui/macro';
+import { useStore } from '@tanstack/react-store';
import { useState } from 'react';
import { useTheme } from 'styled-components';
import { useMediaQuery } from 'usehooks-ts';
import { Drawer } from 'vaul';
import { useAccount } from 'wagmi';
-import { useStore } from '@tanstack/react-store';
import { ProfileDrawer } from '../ProfileDrawer';
import { ProfileTag } from '../ProfileTag';
@@ -24,11 +24,15 @@ const ConnectButton = (): JSX.Element => {
const isReceiveModalOpen = useStore(store, (state) => state.shared.isReceiveModalOpen);
- const { setShowAuthFlow, user } = useDynamicContext();
+ const [isOpen, setOpen] = useState(false);
+
+ const { setShowAuthFlow } = useDynamicContext();
+ const isLoggedIn = useIsLoggedIn();
+
const { address: evmAddress } = useAccount();
const { address: btcAddress } = useBtcAccount();
- const isLoggedIn = useIsLoggedIn();
- const [isOpen, setOpen] = useState(false);
+
+ const isLoading = isLoggedIn && !(evmAddress || btcAddress);
// const isAuthenticated = evmAddress || btcAddress;
@@ -46,8 +50,6 @@ const ConnectButton = (): JSX.Element => {
const handleClose = () => setOpen(false);
- const isLoading = isLoggedIn && !(evmAddress || btcAddress);
-
return (
{
>
-
+
+ Profile
diff --git a/apps/evm/src/components/CopyAddress/CopyAddress.tsx b/apps/evm/src/components/CopyAddress/CopyAddress.tsx
new file mode 100644
index 000000000..ee3b10569
--- /dev/null
+++ b/apps/evm/src/components/CopyAddress/CopyAddress.tsx
@@ -0,0 +1,71 @@
+'use client';
+
+import { Check, CopyClipboard, Flex, Span, SpanProps, Tooltip, UnstyledButton } from '@gobob/ui';
+import { useCopyToClipboard } from 'usehooks-ts';
+import { mergeProps } from '@react-aria/utils';
+import { Trans } from '@lingui/macro';
+import { useHover } from '@react-aria/interactions';
+
+import { useIntervalTooltip } from '@/hooks';
+
+type Props = {
+ address: string;
+ truncatedAddress?: string;
+ hideIcon?: boolean;
+ iconVisibility?: 'hide' | 'always' | 'hover';
+};
+type InheritAttrs = Omit;
+
+type CopyAddressProps = Props & InheritAttrs;
+
+const CopyAddress = ({ truncatedAddress, address, iconVisibility = 'always', ...props }: CopyAddressProps) => {
+ const [, copy] = useCopyToClipboard();
+ const { buttonProps, tooltipProps } = useIntervalTooltip();
+
+ const { isHovered, hoverProps } = useHover({ isDisabled: iconVisibility !== 'hover' });
+
+ const handleCopy = () => copy(address || '');
+
+ const showIcon = isHovered || iconVisibility === 'always';
+
+ return (
+
+
+ Copied
+
+ }
+ >
+
+
+ {truncatedAddress || address}
+ {showIcon && (
+
+
+
+ )}
+
+
+
+ );
+};
+
+export { CopyAddress };
diff --git a/apps/evm/src/components/CopyAddress/index.tsx b/apps/evm/src/components/CopyAddress/index.tsx
new file mode 100644
index 000000000..752cf0041
--- /dev/null
+++ b/apps/evm/src/components/CopyAddress/index.tsx
@@ -0,0 +1 @@
+export { CopyAddress } from './CopyAddress';
diff --git a/apps/evm/src/components/CopyButton/CopyButton.tsx b/apps/evm/src/components/CopyButton/CopyButton.tsx
new file mode 100644
index 000000000..1401a3af8
--- /dev/null
+++ b/apps/evm/src/components/CopyButton/CopyButton.tsx
@@ -0,0 +1,41 @@
+'use client';
+
+import { Button, ButtonProps, Check, CopyClipboard, Flex, IconProps, Tooltip } from '@gobob/ui';
+import { Trans } from '@lingui/macro';
+import { mergeProps } from '@react-aria/utils';
+import { useCopyToClipboard } from 'usehooks-ts';
+
+import { useIntervalTooltip } from '@/hooks';
+
+type Props = {
+ value: string;
+ iconProps?: IconProps;
+};
+type InheritAttrs = Omit;
+
+type CopyButtonProps = Props & InheritAttrs;
+
+const CopyButton = ({ value, iconProps, ...props }: CopyButtonProps) => {
+ const [, copy] = useCopyToClipboard();
+ const { buttonProps, tooltipProps } = useIntervalTooltip();
+
+ const handleCopy = () => copy(value || '');
+
+ return (
+
+
+ Copied
+
+ }
+ >
+
+
+
+
+ );
+};
+
+export { CopyButton };
diff --git a/apps/evm/src/components/CopyButton/index.tsx b/apps/evm/src/components/CopyButton/index.tsx
new file mode 100644
index 000000000..983aa363e
--- /dev/null
+++ b/apps/evm/src/components/CopyButton/index.tsx
@@ -0,0 +1 @@
+export { CopyButton } from './CopyButton';
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
index 8b0c34876..07fd4c6f2 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileBtcWallet.tsx
@@ -2,9 +2,14 @@
import { WalletIcon } from '@dynamic-labs/wallet-book';
import { BTC } from '@gobob/icons';
-import { Button, Card, ChevronRight, Flex, LinkSlash, Span, Tooltip } from '@gobob/ui';
+import { Button, Card, ChevronRight, Flex, LinkSlash, Span, Spinner, Tooltip } from '@gobob/ui';
import { truncateBtcAddress } from '@gobob/utils';
import { Trans } from '@lingui/macro';
+import { CurrencyAmount } from '@gobob/currency';
+import { BITCOIN } from '@gobob/tokens';
+import { useState } from 'react';
+
+import { CopyAddress } from '../CopyAddress';
import { StyledWalletCard } from './ProfileDrawer.style';
@@ -20,6 +25,14 @@ const ProfileBtcWallet = ({ onPressConnect, onUnlink }: ProfileBtcWalletProps):
const { address: btcAddress, connector: btcConnector } = useBtcAccount();
const btcWallet = useBtcDynamicWallet();
+ const [prevBtcWallet, setPrevBtcWallet] = useState(btcWallet?.id);
+ const [isDisconnecting, setDisconnecting] = useState(false);
+
+ if (btcWallet && btcWallet?.id !== prevBtcWallet) {
+ setPrevBtcWallet(btcWallet?.id);
+ setDisconnecting(false);
+ }
+
if (!btcConnector || !btcAddress || !btcWallet) {
return (
{
+ onUnlink(btcWallet.id);
+ setDisconnecting(true);
+ };
+
return (
- {(btcBalance?.total || 0).toString()} BTC
+ {CurrencyAmount.fromRawAmount(BITCOIN, btcBalance?.total || 0).toSignificant()} BTC
-
- {truncateBtcAddress(btcAddress)}
-
+
Unlink wallet}>
- onUnlink(btcWallet.id)}>
-
+
+ {isDisconnecting ? : }
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
index e4676b184..5a52ef58b 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileDrawer.tsx
@@ -1,7 +1,7 @@
'use client';
import { useDynamicContext, useDynamicModals } from '@dynamic-labs/sdk-react-core';
-import { Button, Card, Flex, P, Power, QrCode, SolidCreditCard } from '@gobob/ui';
+import { Button, Card, Flex, P, Power, QrCode, Skeleton, SolidCreditCard, Tooltip } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { useAccount } from 'wagmi';
@@ -20,7 +20,7 @@ type ProfileDrawerProps = {
};
const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
- const { setShowAuthFlow, user, handleLogOut } = useDynamicContext();
+ const { setShowAuthFlow, handleLogOut } = useDynamicContext();
const { address: evmAddress, chain } = useAccount();
const { address: btcAddress } = useBtcAccount();
const { handleUnlinkWallet, setSelectedTabIndex } = useDynamicContext();
@@ -28,7 +28,7 @@ const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
const chainId = chain?.id || L1_CHAIN;
- const { formatted } = useTotalBalance(chainId);
+ const { formatted, isPending: isBalancePending } = useTotalBalance(chainId);
const isAuthenticated = evmAddress || btcAddress;
@@ -72,16 +72,20 @@ const ProfileDrawer = ({ onClose }: ProfileDrawerProps): JSX.Element => {
return (
-
-
+
+
-
+
-
- {formatted}
-
+ {isBalancePending ? (
+
+ ) : (
+
+ {formatted}
+
+ )}
{
const { getBalance } = useBalances(chainId);
const { primaryWallet } = useDynamicContext();
+ const { address } = useAccount();
if (!primaryWallet) return null;
@@ -37,9 +40,13 @@ const ProfileEvmWallet = ({ chainId }: ProfileEvmWalletProps): JSX.Element | nul
-
- {truncateEthAddress(primaryWallet.address)}{' '}
-
+
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
index 1dcbb2a53..1f4be4141 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileTokenList.tsx
@@ -6,7 +6,7 @@ import { Trans } from '@lingui/macro';
import { ProfileTokenListItem } from './ProfileTokenListItem';
-import { useBalances, useBtcBalance, useTokens } from '@/hooks';
+import { useBalances, useBtcBalance, useBtcDynamicWallet, useTokens } from '@/hooks';
import { calculateAmountUSD } from '@/utils';
type ProfileTokenListProps = {
@@ -16,6 +16,9 @@ type ProfileTokenListProps = {
const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
const { data: tokens } = useTokens(chainId);
const { getBalance } = useBalances(chainId);
+
+ const btcWallet = useBtcDynamicWallet();
+
const { data: btcBalance } = useBtcBalance();
const { getPrice } = usePrices();
@@ -38,26 +41,33 @@ const ProfileTokenList = ({ chainId }: ProfileTokenListProps): JSX.Element => {
)}
-
- Tokens
-
+ {!!list?.length && (
+
+ Tokens
+
+ )}
{list?.map((item) => (
{
const format = useCurrencyFormatter();
return (
-
-
- {chainId ? (
- }
- chainId={chainId}
- chainProps={{ size: 'xs' }}
- />
- ) : (
-
- )}
-
- {name}
+
+ {chainId ? (
+ }
+ chainId={chainId}
+ chainProps={{ size: 'xs' }}
+ />
+ ) : (
+
+ )}
+
+ {name}
+ {balance !== undefined && amountUSD !== undefined ? (
{balance} {symbol} ({format(amountUSD)})
-
+ ) : (
+
+ )}
);
diff --git a/apps/evm/src/components/ProfileTag/ProfileTag.tsx b/apps/evm/src/components/ProfileTag/ProfileTag.tsx
index decb6e77d..446838ef6 100644
--- a/apps/evm/src/components/ProfileTag/ProfileTag.tsx
+++ b/apps/evm/src/components/ProfileTag/ProfileTag.tsx
@@ -1,37 +1,50 @@
'use client';
-import { UserProfile } from '@dynamic-labs/sdk-react-core';
-import { Flex, Skeleton, Span } from '@gobob/ui';
+import { useDynamicContext, useIsLoggedIn } from '@dynamic-labs/sdk-react-core';
+import { Flex, Skeleton, Span, SpanProps } from '@gobob/ui';
import { truncateBtcAddress, truncateEthAddress } from '@gobob/utils';
import ProfileAvatar from 'boring-avatars';
-import { Address } from 'viem';
+import { useAccount } from 'wagmi';
+
+import { ChainAsset } from '../ChainAsset';
+import { CopyAddress } from '../CopyAddress';
+
+import { useBtcAccount } from '@/hooks';
const sizeMap = {
s: {
icon: '1.5rem',
- text: 's'
+ text: 's',
+ chain: 'xxs'
},
md: {
icon: '2rem',
- text: 'md'
+ text: 'md',
+ chain: 'xs'
}
} as const;
const ProfileTag = ({
- evmAddress,
- btcAddress,
- user,
size = 's',
- isLoading,
- hideAddress
+ hideAddress,
+ labelProps,
+ isCopyEnabled
}: {
- btcAddress?: string;
- evmAddress?: Address;
- user?: UserProfile;
size?: 's' | 'md';
- isLoading?: boolean;
hideAddress?: boolean;
+ labelProps?: SpanProps;
+ isCopyEnabled?: boolean;
}) => {
+ const { user, primaryWallet, sdkHasLoaded } = useDynamicContext();
+
+ const { address: evmAddress, chain } = useAccount();
+ const { address: btcAddress } = useBtcAccount();
+ const isLoggedIn = useIsLoggedIn();
+
+ const fallbackEvmAddress = primaryWallet?.chain === 'EVM' ? primaryWallet.address : evmAddress;
+
+ const isLoading = !sdkHasLoaded || (isLoggedIn && !(fallbackEvmAddress || btcAddress));
+
if (isLoading) {
return (
@@ -41,18 +54,34 @@ const ProfileTag = ({
);
}
- const displayedAddress = evmAddress
- ? truncateEthAddress(evmAddress)
+ const address = fallbackEvmAddress || btcAddress;
+
+ const truncatedAddress = fallbackEvmAddress
+ ? truncateEthAddress(fallbackEvmAddress)
: btcAddress
? truncateBtcAddress(btcAddress)
: undefined;
return (
- {user?.userId ? : undefined}
- {!hideAddress && (
+ {user?.userId ? (
+ }
+ chainId={chain?.id}
+ chainProps={{ size: sizeMap[size].chain }}
+ />
+ ) : undefined}
+ {!hideAddress && isCopyEnabled ? (
+
+ ) : (
- {displayedAddress}
+ {truncatedAddress}
)}
diff --git a/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
index 560fc3dec..5133cd15d 100644
--- a/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
+++ b/apps/evm/src/components/ReceiveModal/ReceiveModal.tsx
@@ -2,7 +2,6 @@ import {
ArrowLeft,
Button,
Card,
- DocumentDuplicate,
Flex,
Modal,
ModalBody,
@@ -14,7 +13,6 @@ import {
} from '@gobob/ui';
import QRCode from 'react-qr-code';
import { useAccount } from 'wagmi';
-import { useCopyToClipboard } from 'usehooks-ts';
import { Trans } from '@lingui/macro';
import { useState } from 'react';
import { useStore } from '@tanstack/react-store';
@@ -26,6 +24,8 @@ import { ChainId } from '@gobob/chains';
import { Chain } from '../Chain';
import { ChainAsset } from '../ChainAsset/ChainAsset';
+import { CopyButton } from '../CopyButton';
+import { CopyAddress } from '../CopyAddress';
import { useBtcAccount } from '@/hooks';
import { L1_CHAIN, L2_CHAIN } from '@/constants';
@@ -44,7 +44,6 @@ const ReceiveModal = (): JSX.Element => {
const { primaryWallet } = useDynamicContext();
const { address: evmAddress } = useAccount();
const { address: btcAddress, connector: btcConnector } = useBtcAccount();
- const [, copy] = useCopyToClipboard();
const address = (step === ReceiveSteps.EVM ? evmAddress : btcAddress) || '';
@@ -55,7 +54,8 @@ const ReceiveModal = (): JSX.Element => {
? truncateBtcAddress(btcAddress)
: undefined;
- const handleClose = () =>
+ const handleClose = () => {
+ setStep(ReceiveSteps.Main);
store.setState((state) => ({
...state,
shared: {
@@ -63,6 +63,7 @@ const ReceiveModal = (): JSX.Element => {
isReceiveModalOpen: false
}
}));
+ };
return (
@@ -115,9 +116,13 @@ const ReceiveModal = (): JSX.Element => {
- copy(evmAddress)}>
-
-
+
setStep(ReceiveSteps.EVM)}>
@@ -149,9 +154,14 @@ const ReceiveModal = (): JSX.Element => {
- copy(btcAddress)}>
-
-
+
+
setStep(ReceiveSteps.BTC)}>
@@ -163,9 +173,14 @@ const ReceiveModal = (): JSX.Element => {
)}
{step !== ReceiveSteps.Main && (
<>
-
- {shortAddress}
-
+
{
+ const [isOpen, setOpen] = useState(false);
+
+ useInterval(
+ () => {
+ // Your custom logic here
+ setOpen(false);
+ },
+ // Delay in milliseconds or null to stop it
+ isOpen ? delay : null
+ );
+
+ return {
+ buttonProps: { onPress: () => setOpen(true) },
+ tooltipProps: {
+ isOpen
+ }
+ };
+};
+
+export { useIntervalTooltip };
diff --git a/apps/evm/src/hooks/useTotalBalance.ts b/apps/evm/src/hooks/useTotalBalance.ts
index 4e537d921..72b4e3d4e 100644
--- a/apps/evm/src/hooks/useTotalBalance.ts
+++ b/apps/evm/src/hooks/useTotalBalance.ts
@@ -2,30 +2,42 @@ import { ChainId } from '@gobob/chains';
import { usePrices } from '@gobob/hooks';
import { useCurrencyFormatter, useLocale } from '@gobob/ui';
import Big from 'big.js';
-import { useMemo } from 'react';
+import { CurrencyAmount } from '@gobob/currency';
+import { BITCOIN } from '@gobob/tokens';
import { useBalances } from './useBalances';
+import { useBtcBalance, useBtcDynamicWallet } from './btc';
+
+import { calculateAmountUSD } from '@/utils';
const useTotalBalance = (chainId: ChainId) => {
const { getPrice } = usePrices();
- const { balances } = useBalances(chainId);
+ const { balances, isPending: isEvmBalancePending } = useBalances(chainId);
+
+ const btcWallet = useBtcDynamicWallet();
+ const { data: btcBalance, isPending: isBtcBalancePending } = useBtcBalance();
+
const format = useCurrencyFormatter();
const { locale } = useLocale();
- return useMemo(() => {
- const total = Object.values(balances).reduce(
- (total, balance) => total.plus(new Big(balance.toExact()).mul(getPrice(balance.currency.symbol) || 0).toNumber()),
- new Big(0)
- );
-
- return {
- formatted: format(total.toNumber()),
- compact: Intl.NumberFormat(locale, { notation: 'compact', style: 'currency', currency: 'USD' }).format(
- total.toNumber()
- ),
- amount: total
- };
- }, [balances, format, getPrice, locale]);
+ const total = Object.values(balances).reduce(
+ (total, balance) => total.plus(calculateAmountUSD(balance, getPrice(balance.currency.symbol) || 0)),
+ new Big(
+ calculateAmountUSD(
+ CurrencyAmount.fromRawAmount(BITCOIN, btcBalance?.total.toString() || 0),
+ getPrice(BITCOIN.symbol)
+ )
+ )
+ );
+
+ return {
+ isPending: isEvmBalancePending || (btcWallet ? isBtcBalancePending : false),
+ formatted: format(total.toNumber()),
+ compact: Intl.NumberFormat(locale, { notation: 'compact', style: 'currency', currency: 'USD' }).format(
+ total.toNumber()
+ ),
+ amount: total
+ };
};
export { useTotalBalance };
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 78ec8499f..7a4dc7d4d 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -88,7 +88,7 @@
"devDependencies": {
"@gobob/test-utils": "workspace:^",
"@react-types/grid": "^3.2.0",
- "@react-types/shared": "^3.19.0",
+ "@react-types/shared": "catalog:",
"@react-types/tabs": "^3.3.2",
"@types/react-transition-group": "^4.4.6",
"@types/styled-components": "catalog:",
diff --git a/packages/ui/src/icons/CopyClipboard.tsx b/packages/ui/src/icons/CopyClipboard.tsx
new file mode 100644
index 000000000..678bc81f3
--- /dev/null
+++ b/packages/ui/src/icons/CopyClipboard.tsx
@@ -0,0 +1,16 @@
+import { forwardRef } from 'react';
+
+import { Icon, IconProps } from '../components';
+
+const CopyClipboard = forwardRef((props, ref) => (
+
+
+
+));
+
+CopyClipboard.displayName = 'CopyClipboard';
+
+export { CopyClipboard };
diff --git a/packages/ui/src/icons/index.ts b/packages/ui/src/icons/index.ts
index 928a73b98..4847d5498 100644
--- a/packages/ui/src/icons/index.ts
+++ b/packages/ui/src/icons/index.ts
@@ -22,6 +22,7 @@ export { ChevronLeft } from './ChevronLeft';
export { ChevronRight } from './ChevronRight';
export { Clock } from './Clock';
export { Cog } from './Cog';
+export { CopyClipboard } from './CopyClipboard';
export { CreditCard } from './CreditCard';
export { DocumentDuplicate } from './DocumentDuplicate';
export { EllipsisHorizontal } from './EllipsisHorizontal';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8e56c23ec..9b3856a36 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,9 @@ catalogs:
'@react-stately/list':
specifier: ^3.9.1
version: 3.11.0
+ '@react-types/shared':
+ specifier: ^3.19.0
+ version: 3.25.0
'@sentry/nextjs':
specifier: ^8.30.0
version: 8.30.0
@@ -278,10 +281,10 @@ importers:
version: 3.4.6(@dynamic-labs/rpc-providers@3.4.6(eventemitter3@5.0.1))(@zerodev/webauthn-key@5.3.3(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))
'@dynamic-labs/sdk-react-core':
specifier: ^v3.0.0-alpha.29
- version: 3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ version: 3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
'@dynamic-labs/wagmi-connector':
specifier: ^v3.0.0-alpha.29
- version: 3.4.6(jacem5rvdc6vjxfcms3lds4squ)
+ version: 3.4.6(svit3uz54pwx2nnmcxp7dz3jee)
'@gobob/chains':
specifier: workspace:^
version: link:../../packages/chains
@@ -377,7 +380,7 @@ importers:
version: 2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
wagmi:
specifier: 'catalog:'
- version: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
+ version: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
yup:
specifier: 'catalog:'
version: 0.32.11
@@ -447,7 +450,7 @@ importers:
dependencies:
'@binance/w3w-wagmi-connector-v2':
specifier: 1.2.4-alpha.0
- version: 1.2.4-alpha.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))
+ version: 1.2.4-alpha.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))
'@dynamic-labs/bitcoin':
specifier: ^3.6.2
version: 3.8.5(@dynamic-labs/logger@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.8.5(eventemitter3@5.0.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)
@@ -459,10 +462,10 @@ importers:
version: 3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@dynamic-labs/sdk-react-core':
specifier: ^3.6.2
- version: 3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ version: 3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
'@dynamic-labs/wagmi-connector':
specifier: ^3.6.2
- version: 3.8.5(v2rmvkuqnx3yukimu7o4nopegu)
+ version: 3.8.5(2yyrhe52wlsv7lkpd5ylcgbkjm)
'@dynamic-labs/wallet-book':
specifier: ^3.8.5
version: 3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -591,7 +594,7 @@ importers:
version: 2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
wagmi:
specifier: 'catalog:'
- version: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
+ version: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
yup:
specifier: 'catalog:'
version: 0.32.11
@@ -871,8 +874,8 @@ importers:
specifier: ^3.2.0
version: 3.2.6(react@18.3.1)
'@react-types/shared':
- specifier: ^3.19.0
- version: 3.23.1(react@18.3.1)
+ specifier: 'catalog:'
+ version: 3.25.0(react@18.3.1)
'@react-types/tabs':
specifier: ^3.3.2
version: 3.3.7(react@18.3.1)
@@ -4518,13 +4521,13 @@ packages:
peerDependencies:
react: ^18.2.0
- '@react-types/shared@3.23.1':
- resolution: {integrity: sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==}
+ '@react-types/shared@3.25.0':
+ resolution: {integrity: sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==}
peerDependencies:
react: ^18.2.0
- '@react-types/shared@3.25.0':
- resolution: {integrity: sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==}
+ '@react-types/shared@3.26.0':
+ resolution: {integrity: sha512-6FuPqvhmjjlpEDLTiYx29IJCbCNWPlsyO+ZUmCUXzhUv2ttShOXfw8CmeHWHftT/b2KweAWuzqSlfeXPR76jpw==}
peerDependencies:
react: ^18.2.0
@@ -14287,12 +14290,12 @@ snapshots:
hash.js: 1.1.7
js-base64: 3.7.7
- '@binance/w3w-wagmi-connector-v2@1.2.4-alpha.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))':
+ '@binance/w3w-wagmi-connector-v2@1.2.4-alpha.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))':
dependencies:
'@binance/w3w-ethereum-provider': 1.1.8-alpha.0(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(utf-8-validate@5.0.10)
'@binance/w3w-utils': 1.1.4
viem: 2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
- wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
+ wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
transitivePeerDependencies:
- bufferutil
- debug
@@ -14938,7 +14941,7 @@ snapshots:
'@dynamic-labs/sdk-api-core@0.0.570': {}
- '@dynamic-labs/sdk-react-core@3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)':
+ '@dynamic-labs/sdk-react-core@3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)':
dependencies:
'@dynamic-labs/assert-package-version': 3.4.6(eventemitter3@5.0.1)
'@dynamic-labs/iconic': 3.4.6(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -14960,14 +14963,14 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-focus-lock: 2.9.2(@types/react@18.3.3)(react@18.3.1)
- react-i18next: 13.5.0(i18next@23.4.6)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ react-i18next: 13.5.0(i18next@23.4.6)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
react-international-phone: 4.2.5(react@18.3.1)
yup: 0.32.11
transitivePeerDependencies:
- '@types/react'
- react-native
- '@dynamic-labs/sdk-react-core@3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)':
+ '@dynamic-labs/sdk-react-core@3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)':
dependencies:
'@dynamic-labs/assert-package-version': 3.8.5(eventemitter3@5.0.1)
'@dynamic-labs/iconic': 3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -14990,7 +14993,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-focus-lock: 2.9.2(@types/react@18.3.3)(react@18.3.1)
- react-i18next: 13.5.0(i18next@23.4.6)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ react-i18next: 13.5.0(i18next@23.4.6)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
react-international-phone: 4.2.5(react@18.3.1)
yup: 0.32.11
transitivePeerDependencies:
@@ -15045,35 +15048,35 @@ snapshots:
eventemitter3: 5.0.1
tldts: 6.0.16
- '@dynamic-labs/wagmi-connector@3.4.6(jacem5rvdc6vjxfcms3lds4squ)':
+ '@dynamic-labs/wagmi-connector@3.4.6(svit3uz54pwx2nnmcxp7dz3jee)':
dependencies:
'@dynamic-labs/assert-package-version': 3.4.6(eventemitter3@5.0.1)
'@dynamic-labs/ethereum-core': 3.8.5(@dynamic-labs/assert-package-version@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/logger@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/types@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/utils@3.4.6)(@dynamic-labs/wallet-book@3.4.6(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dynamic-labs/wallet-connector-core@3.4.6(@dynamic-labs/assert-package-version@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/logger@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/types@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/utils@3.4.6)(@dynamic-labs/wallet-book@3.4.6(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eventemitter3@5.0.1))(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))
'@dynamic-labs/logger': 3.4.6(eventemitter3@5.0.1)
'@dynamic-labs/rpc-providers': 3.4.6(eventemitter3@5.0.1)
- '@dynamic-labs/sdk-react-core': 3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ '@dynamic-labs/sdk-react-core': 3.4.6(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
'@dynamic-labs/types': 3.4.6(eventemitter3@5.0.1)
'@dynamic-labs/wallet-connector-core': 3.4.6(@dynamic-labs/assert-package-version@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/logger@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/types@3.4.6(eventemitter3@5.0.1))(@dynamic-labs/utils@3.4.6)(@dynamic-labs/wallet-book@3.4.6(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eventemitter3@5.0.1)
'@wagmi/core': 2.14.5(@tanstack/query-core@5.44.0)(@types/react@18.3.3)(react@18.3.1)(typescript@5.4.5)(use-sync-external-store@1.2.2(react@18.3.1))(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))
eventemitter3: 5.0.1
react: 18.3.1
viem: 2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
- wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
+ wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
- '@dynamic-labs/wagmi-connector@3.8.5(v2rmvkuqnx3yukimu7o4nopegu)':
+ '@dynamic-labs/wagmi-connector@3.8.5(2yyrhe52wlsv7lkpd5ylcgbkjm)':
dependencies:
'@dynamic-labs/assert-package-version': 3.8.5(eventemitter3@5.0.1)
'@dynamic-labs/ethereum-core': 3.8.5(@dynamic-labs/assert-package-version@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/logger@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/types@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/utils@3.8.5)(@dynamic-labs/wallet-book@3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@dynamic-labs/wallet-connector-core@3.8.5(@dynamic-labs/assert-package-version@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/logger@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/types@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/utils@3.8.5)(@dynamic-labs/wallet-book@3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eventemitter3@5.0.1))(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))
'@dynamic-labs/logger': 3.8.5(eventemitter3@5.0.1)
'@dynamic-labs/rpc-providers': 3.8.5(eventemitter3@5.0.1)
- '@dynamic-labs/sdk-react-core': 3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
+ '@dynamic-labs/sdk-react-core': 3.8.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)
'@dynamic-labs/types': 3.8.5(eventemitter3@5.0.1)
'@dynamic-labs/wallet-connector-core': 3.8.5(@dynamic-labs/assert-package-version@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/logger@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/rpc-providers@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/types@3.8.5(eventemitter3@5.0.1))(@dynamic-labs/utils@3.8.5)(@dynamic-labs/wallet-book@3.8.5(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eventemitter3@5.0.1)
'@wagmi/core': 2.14.5(@tanstack/query-core@5.44.0)(@types/react@18.3.3)(react@18.3.1)(typescript@5.4.5)(use-sync-external-store@1.2.2(react@18.3.1))(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))
eventemitter3: 5.0.1
react: 18.3.1
viem: 2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)
- wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.0(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
+ wagmi: 2.12.30(@tanstack/query-core@5.44.0)(@tanstack/react-query@5.44.0(react@18.3.1))(@types/node@20.14.2)(@types/react@18.3.3)(@upstash/redis@1.34.3)(@vercel/kv@3.0.0)(bufferutil@4.0.8)(jsdom@25.0.1(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(terser@5.31.1)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.21.40(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)
'@dynamic-labs/wallet-book@3.4.6(eventemitter3@5.0.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
@@ -16226,7 +16229,7 @@ snapshots:
dependencies:
'@ethereumjs/tx': 4.2.0
'@metamask/superstruct': 3.0.0
- '@noble/hashes': 1.5.0
+ '@noble/hashes': 1.6.1
'@scure/base': 1.1.9
'@types/debug': 4.1.12
debug: 4.3.7(supports-color@8.1.1)
@@ -17149,7 +17152,7 @@ snapshots:
'@react-stately/tree': 3.8.1(react@18.3.1)
'@react-types/accordion': 3.0.0-alpha.15(react@18.3.1)
'@react-types/button': 3.9.4(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
transitivePeerDependencies:
@@ -17161,7 +17164,7 @@ snapshots:
'@react-aria/link': 3.7.1(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/breadcrumbs': 3.7.5(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17172,7 +17175,7 @@ snapshots:
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/toggle': 3.7.4(react@18.3.1)
'@react-types/button': 3.10.0(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17182,7 +17185,7 @@ snapshots:
'@react-aria/overlays': 3.22.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/dialog': 3.5.10(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17191,7 +17194,7 @@ snapshots:
dependencies:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
clsx: 2.1.1
react: 18.3.1
@@ -17201,7 +17204,7 @@ snapshots:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/form': 3.0.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17218,7 +17221,7 @@ snapshots:
'@react-stately/selection': 3.17.0(react@18.3.1)
'@react-types/checkbox': 3.8.4(react@18.3.1)
'@react-types/grid': 3.2.9(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17237,7 +17240,7 @@ snapshots:
'@react-stately/virtualizer': 3.7.1(react@18.3.1)
'@react-types/checkbox': 3.8.1(react@18.3.1)
'@react-types/grid': 3.2.6(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17253,7 +17256,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/list': 3.11.0(react@18.3.1)
'@react-stately/tree': 3.8.1(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17269,7 +17272,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/list': 3.11.0(react@18.3.1)
'@react-stately/tree': 3.8.5(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17282,7 +17285,7 @@ snapshots:
'@internationalized/string': 3.2.3
'@react-aria/ssr': 3.9.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17294,7 +17297,7 @@ snapshots:
'@internationalized/string': 3.2.4
'@react-aria/ssr': 3.9.6(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17302,21 +17305,21 @@ snapshots:
dependencies:
'@react-aria/ssr': 3.9.6(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-aria/label@3.7.12(react@18.3.1)':
dependencies:
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-aria/label@3.7.8(react@18.3.1)':
dependencies:
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17326,7 +17329,7 @@ snapshots:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/link': 3.5.5(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17339,7 +17342,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/list': 3.11.0(react@18.3.1)
'@react-types/listbox': 3.4.9(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17365,7 +17368,7 @@ snapshots:
'@react-stately/tree': 3.8.1(react@18.3.1)
'@react-types/button': 3.10.0(react@18.3.1)
'@react-types/menu': 3.9.9(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17381,7 +17384,7 @@ snapshots:
'@react-stately/overlays': 3.6.7(react@18.3.1)
'@react-types/button': 3.9.4(react@18.3.1)
'@react-types/overlays': 3.8.7(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17392,7 +17395,7 @@ snapshots:
'@react-aria/label': 3.7.8(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/progress': 3.5.4(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17406,7 +17409,7 @@ snapshots:
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/radio': 3.10.4(react@18.3.1)
'@react-types/radio': 3.8.1(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17424,7 +17427,7 @@ snapshots:
'@react-stately/select': 3.6.4(react@18.3.1)
'@react-types/button': 3.9.4(react@18.3.1)
'@react-types/select': 3.9.4(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17436,7 +17439,7 @@ snapshots:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/selection': 3.17.0(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17448,7 +17451,7 @@ snapshots:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/selection': 3.17.0(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -17456,7 +17459,7 @@ snapshots:
'@react-aria/separator@3.3.13(react@18.3.1)':
dependencies:
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17493,7 +17496,7 @@ snapshots:
'@react-stately/virtualizer': 3.7.1(react@18.3.1)
'@react-types/checkbox': 3.8.1(react@18.3.1)
'@react-types/grid': 3.2.6(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/table': 3.9.5(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17506,7 +17509,7 @@ snapshots:
'@react-aria/selection': 3.18.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/tabs': 3.6.6(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/tabs': 3.3.7(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17535,7 +17538,7 @@ snapshots:
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/form': 3.0.3(react@18.3.1)
'@react-stately/utils': 3.10.1(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/textfield': 3.9.3(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17556,7 +17559,7 @@ snapshots:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-stately/tooltip': 3.4.9(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/tooltip': 3.4.9(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -17565,7 +17568,7 @@ snapshots:
dependencies:
'@react-aria/ssr': 3.9.6(react@18.3.1)
'@react-stately/utils': 3.10.4(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
clsx: 2.1.1
react: 18.3.1
@@ -17574,7 +17577,7 @@ snapshots:
dependencies:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18166,7 +18169,7 @@ snapshots:
'@react-stately/form@3.0.3(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18175,7 +18178,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/selection': 3.17.0(react@18.3.1)
'@react-types/grid': 3.2.6(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18184,7 +18187,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/selection': 3.17.0(react@18.3.1)
'@react-types/grid': 3.2.9(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18201,7 +18204,7 @@ snapshots:
dependencies:
'@react-stately/overlays': 3.6.7(react@18.3.1)
'@react-types/menu': 3.9.9(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18217,7 +18220,7 @@ snapshots:
'@react-stately/form': 3.0.3(react@18.3.1)
'@react-stately/utils': 3.10.1(react@18.3.1)
'@react-types/radio': 3.8.1(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18227,7 +18230,7 @@ snapshots:
'@react-stately/list': 3.11.0(react@18.3.1)
'@react-stately/overlays': 3.6.7(react@18.3.1)
'@react-types/select': 3.9.4(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18235,7 +18238,7 @@ snapshots:
dependencies:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/utils': 3.10.4(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18243,7 +18246,7 @@ snapshots:
dependencies:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/utils': 3.10.4(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18255,7 +18258,7 @@ snapshots:
'@react-stately/selection': 3.15.1(react@18.3.1)
'@react-stately/utils': 3.10.1(react@18.3.1)
'@react-types/grid': 3.2.6(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/table': 3.9.5(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18263,7 +18266,7 @@ snapshots:
'@react-stately/tabs@3.6.6(react@18.3.1)':
dependencies:
'@react-stately/list': 3.11.0(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@react-types/tabs': 3.3.7(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18287,7 +18290,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/selection': 3.15.1(react@18.3.1)
'@react-stately/utils': 3.10.1(react@18.3.1)
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18296,7 +18299,7 @@ snapshots:
'@react-stately/collections': 3.11.0(react@18.3.1)
'@react-stately/selection': 3.17.0(react@18.3.1)
'@react-stately/utils': 3.10.4(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
@@ -18313,126 +18316,126 @@ snapshots:
'@react-stately/virtualizer@3.7.1(react@18.3.1)':
dependencies:
'@react-aria/utils': 3.25.3(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-types/accordion@3.0.0-alpha.15(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/breadcrumbs@3.7.5(react@18.3.1)':
dependencies:
'@react-types/link': 3.5.5(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/button@3.10.0(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/button@3.9.4(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/checkbox@3.8.1(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/checkbox@3.8.4(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/dialog@3.5.10(react@18.3.1)':
dependencies:
'@react-types/overlays': 3.8.7(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/grid@3.2.6(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/grid@3.2.9(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/link@3.5.5(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/listbox@3.4.9(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/menu@3.9.9(react@18.3.1)':
dependencies:
'@react-types/overlays': 3.8.7(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/overlays@3.8.7(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/progress@3.5.4(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/radio@3.8.1(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/select@3.9.4(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
- '@react-types/shared@3.23.1(react@18.3.1)':
+ '@react-types/shared@3.25.0(react@18.3.1)':
dependencies:
react: 18.3.1
- '@react-types/shared@3.25.0(react@18.3.1)':
+ '@react-types/shared@3.26.0(react@18.3.1)':
dependencies:
react: 18.3.1
'@react-types/switch@3.5.3(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/table@3.9.5(react@18.3.1)':
dependencies:
'@react-types/grid': 3.2.6(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/tabs@3.3.7(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.23.1(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/textfield@3.9.3(react@18.3.1)':
dependencies:
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@react-types/tooltip@3.4.9(react@18.3.1)':
dependencies:
'@react-types/overlays': 3.8.7(react@18.3.1)
- '@react-types/shared': 3.25.0(react@18.3.1)
+ '@react-types/shared': 3.26.0(react@18.3.1)
react: 18.3.1
'@rnx-kit/chromium-edge-launcher@1.0.0':
@@ -23428,7 +23431,7 @@ snapshots:
debug: 4.3.7(supports-color@8.1.1)
enhanced-resolve: 5.17.0
eslint: 8.57.0
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
+ eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
fast-glob: 3.3.2
get-tsconfig: 4.8.1
is-bun-module: 1.2.1
@@ -23441,7 +23444,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0):
+ eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
@@ -23462,7 +23465,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
+ eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
hasown: 2.0.2
is-core-module: 2.13.1
is-glob: 4.0.3
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 6ece54806..cb551732e 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -36,6 +36,7 @@ catalog:
'@react-aria/utils': ^3.23.2
'@react-stately/collections': ^3.10.0
'@react-stately/list': ^3.9.1
+ '@react-types/shared': ^3.19.0
yup: ^0.32.11
From 91c746c77d5cd0bcec6dab284fa0cb081da6a8d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Thu, 12 Dec 2024 10:23:27 +0000
Subject: [PATCH 13/16] fix: build
---
apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts | 4 +---
apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx | 7 +++++++
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts b/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
index 1edef79be..5ba05b45e 100644
--- a/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
+++ b/apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
@@ -226,9 +226,7 @@ const useGateway = ({ params, onError, onMutate, onSuccess }: UseGatewayLiquidit
feeRate: feeRate,
query: {
enabled: Boolean(satsBalance && satsBalance.total > 0n && evmAddress),
- select: (data) => {
- return data.amount ? CurrencyAmount.fromRawAmount(BITCOIN, data.amount) : null;
- }
+ select: (data) => CurrencyAmount.fromRawAmount(BITCOIN, data.amount || 0)
}
});
diff --git a/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx b/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
index 230311a78..2a03e3718 100644
--- a/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
+++ b/apps/evm/src/components/ProfileDrawer/ProfileEvmWallet.tsx
@@ -21,8 +21,12 @@ const ProfileEvmWallet = ({ chainId }: ProfileEvmWalletProps): JSX.Element | nul
const { primaryWallet } = useDynamicContext();
const { address } = useAccount();
+ // const { switchChain } = useSwitchChain();
+
if (!primaryWallet) return null;
+ // const otherChain = chainId === L1_CHAIN ? L2_CHAIN : L1_CHAIN;
+
return (
+ {/* switchChain(otherChain)}>
+ Switch
+ */}
);
};
From 90d20ee02107d6381b6ca4b67f344e5de8ec1797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rui=20Sim=C3=A3o?=
Date: Thu, 12 Dec 2024 12:35:38 +0000
Subject: [PATCH 14/16] fix: connect button
---
.../assets/fonts/eurostar-black-extended.ttf | Bin 66232 -> 0 bytes
apps/evm/src/app/[lang]/index.css | 5 -
apps/evm/src/app/[lang]/layout.tsx | 17 +-
.../src/app/[lang]/sign-up/SignUp.style.tsx | 4 +-
apps/evm/src/app/[lang]/sign-up/SignUp.tsx | 3 +-
apps/evm/src/app/fonts.ts | 5 +
.../ConnectButton/ConnectButton.style.tsx | 44 +-
.../ConnectButton/ConnectButton.tsx | 10 +-
apps/evm/src/components/Layout/Header.tsx | 14 +-
apps/evm/src/components/Layout/Sidebar.tsx | 8 +-
apps/evm/src/components/Logo/Logo.tsx | 13 +-
.../ProfileDrawer/ProfileDrawer.tsx | 3 +-
.../src/components/ProfileTag/ProfileTag.tsx | 3 +-
apps/evm/src/locales/en.po | 73 +--
apps/evm/src/locales/zh.po | 73 +--
packages/ui/package.json | 2 +-
pnpm-lock.yaml | 519 +++++++++---------
pnpm-workspace.yaml | 1 -
18 files changed, 424 insertions(+), 373 deletions(-)
delete mode 100644 apps/evm/public/assets/fonts/eurostar-black-extended.ttf
create mode 100644 apps/evm/src/app/fonts.ts
diff --git a/apps/evm/public/assets/fonts/eurostar-black-extended.ttf b/apps/evm/public/assets/fonts/eurostar-black-extended.ttf
deleted file mode 100644
index 4965075157125667051001ac25af7922ee9c94f3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 66232
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