From 92808fd8ec749b9340e94a434f99eb7ca490ecd2 Mon Sep 17 00:00:00 2001 From: Nejc Date: Wed, 21 Jun 2023 15:47:46 +0800 Subject: [PATCH 01/12] feat: wallet connect WIP --- package.json | 4 +- src/GlobalStateProvider.tsx | 86 +- src/app.tsx | 2 +- src/components/ChainSelector.tsx | 10 +- src/components/Layout/Nav.tsx | 4 +- src/components/Layout/NetworkId.tsx | 2 +- src/components/Layout/index.tsx | 35 +- src/components/Layout/links.tsx | 4 +- src/components/Wallet/WalletConnect/index.tsx | 84 ++ .../Wallet/WalletConnect/wallet-connect.svg | 1 + .../{OpenWallet.tsx => Wallet/index.tsx} | 40 +- src/config/index.ts | 4 + src/index.css | 5 + src/main.tsx | 7 +- src/pages/bridge/Issue.tsx | 2 +- src/pages/bridge/Redeem.tsx | 2 +- src/pages/bridge/TransferDialog.tsx | 4 +- src/pages/bridge/Transfers.tsx | 4 +- src/pages/dashboard/Dashboard.tsx | 5 +- src/pages/stats/index.tsx | 2 +- yarn.lock | 870 +++++++++++++++++- 21 files changed, 1021 insertions(+), 156 deletions(-) create mode 100644 src/components/Wallet/WalletConnect/index.tsx create mode 100644 src/components/Wallet/WalletConnect/wallet-connect.svg rename src/components/{OpenWallet.tsx => Wallet/index.tsx} (68%) diff --git a/package.json b/package.json index c6b5af73..b6fccb18 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "@talismn/connect-wallets": "^1.2.3", "@tanstack/react-query": "^4.24.10", "@tanstack/react-table": "^8.7.9", + "@walletconnect/modal": "^2.4.7", + "@walletconnect/universal-provider": "^2.8.1", "big.js": "^6.2.1", "bn.js": "^5.2.1", "bs58": "^5.0.0", @@ -105,4 +107,4 @@ "npm": "please-use-yarn", "yarn": ">=1.22.19" } -} +} \ No newline at end of file diff --git a/src/GlobalStateProvider.tsx b/src/GlobalStateProvider.tsx index 7a1ff41c..00196692 100644 --- a/src/GlobalStateProvider.tsx +++ b/src/GlobalStateProvider.tsx @@ -1,7 +1,8 @@ import { WalletAccount, getWalletBySource } from '@talismn/connect-wallets'; import { createContext } from 'preact'; -import { StateUpdater, useCallback, useContext, useEffect, useMemo, useState } from 'preact/compat'; -import { useLocation } from 'react-router-dom'; +import { useCallback, useContext, useEffect, useMemo } from 'preact/compat'; +import { useState } from 'react'; +import { useParams } from 'react-router-dom'; import { config } from './config'; import { storageKeys } from './constants/localStorage'; import { useLocalStorage } from './hooks/useLocalStorage'; @@ -9,58 +10,49 @@ import { TenantName } from './models/Tenant'; import { ThemeName } from './models/Theme'; import { storageService } from './services/storage/local'; -export interface GlobalStateValues { +export interface GlobalState { + dAppName: string; tenantName: TenantName; tenantRPC?: string; - wallet?: WalletAccount; -} - -export interface GlobalState { - state: Partial; - setState: StateUpdater>; - walletAccount: WalletAccount | undefined; + walletAccount?: WalletAccount; setWalletAccount: (data: WalletAccount) => void; removeWalletAccount: () => void; getThemeName: () => ThemeName; - dAppName: string; } -export const defaultState: GlobalStateValues = { - tenantName: TenantName.Amplitude, - tenantRPC: undefined, -}; +export const defaultTenant = TenantName.Pendulum; const GlobalStateContext = createContext(undefined); -const GlobalStateProvider = ({ - children, - value = defaultState, -}: { - children: ReactNode; - value?: Partial; -}) => { - const { pathname } = useLocation(); - const [state, setState] = useState(() => { - if (value) return value; - if (pathname) { +const GlobalStateProvider = ({ children }: { children: ReactNode }) => { + const params = useParams(); + const [walletAccount, setWallet] = useState(undefined); + //const { pathname } = useLocation(); + + const tenantName = useMemo(() => { + return params.network && Object.values(TenantName).includes(params.network) + ? (params.network as TenantName) + : defaultTenant; + /* if (pathname) { const [network] = pathname.split('/').filter(Boolean); const tenantName = Object.values(TenantName).includes(network) ? (network as TenantName) : TenantName.Pendulum; + if (tenantName) { return { tenantName, tenantRPC: config.tenants[tenantName].rpc, }; } - } - return defaultState; - }); - const dAppName = state.tenantName || TenantName.Amplitude; + } */ + }, [params.network]); + + const dAppName = tenantName; const getThemeName = useCallback( - () => (state.tenantName ? config.tenants[state.tenantName]?.theme || ThemeName.Amplitude : ThemeName.Amplitude), - [state?.tenantName], + () => (tenantName ? config.tenants[tenantName]?.theme || ThemeName.Amplitude : ThemeName.Amplitude), + [tenantName], ); const { @@ -68,13 +60,18 @@ const GlobalStateProvider = ({ set, clear, } = useLocalStorage({ - key: `${storageKeys.ACCOUNT}-${state.tenantName}`, + key: `${storageKeys.ACCOUNT}-${tenantName}`, }); + const removeWalletAccount = useCallback(() => { + clear(); + setWallet(undefined); + }, [clear]); + useEffect(() => { const run = async () => { storageService.removeExpired(); - if (!account) return; + if (!account) removeWalletAccount(); const name = storageService.get('@talisman-connect/selected-wallet-name'); if (!name) return; const wallet = getWalletBySource(name); @@ -83,28 +80,25 @@ const GlobalStateProvider = ({ await wallet.enable(dAppName || TenantName.Amplitude); const selectedWallet = (await wallet.getAccounts()).find((a) => a.address === account); if (!selectedWallet) return; - setState((prev) => ({ ...prev, wallet: selectedWallet })); + setWallet(selectedWallet); }; run(); - }, [account, dAppName, state.tenantName]); + }, [account, removeWalletAccount, dAppName]); - const providerValue = useMemo( + const providerValue = useMemo( () => ({ - state, - setState, - walletAccount: state.wallet, + walletAccount, + tenantName: tenantName, + tenantRPC: config.tenants[tenantName].rpc, setWalletAccount: (wallet: WalletAccount | undefined) => { set(wallet?.address); - setState((prev) => ({ ...prev, wallet })); - }, - removeWalletAccount: () => { - clear(); - setState((prev) => ({ ...prev, wallet: undefined })); + setWallet(wallet); }, + removeWalletAccount, getThemeName, dAppName, }), - [clear, dAppName, getThemeName, set, state], + [dAppName, getThemeName, removeWalletAccount, set, tenantName, walletAccount], ); return {children}; diff --git a/src/app.tsx b/src/app.tsx index 5207c8ce..148fa00e 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,12 +1,12 @@ import { Navigate, Route, Routes } from 'react-router-dom'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; +import TermsAndConditions from './TermsAndConditions'; import Layout from './components/Layout'; import { defaultPageLoader } from './components/Loader/Page'; import { NotFound } from './components/NotFound'; import { SuspenseLoad } from './components/Suspense'; import { config } from './config'; -import TermsAndConditions from './TermsAndConditions'; /** * Components need to be default exports inside the file for suspense loading to work properly diff --git a/src/components/ChainSelector.tsx b/src/components/ChainSelector.tsx index b696ba15..871964ce 100644 --- a/src/components/ChainSelector.tsx +++ b/src/components/ChainSelector.tsx @@ -17,16 +17,16 @@ const ChainSelector = ({ tenantName }: { tenantName: TenantName | undefined }): {options.map((option, i) => ( diff --git a/src/components/Layout/Nav.tsx b/src/components/Layout/Nav.tsx index 2b833207..a324128b 100644 --- a/src/components/Layout/Nav.tsx +++ b/src/components/Layout/Nav.tsx @@ -17,7 +17,7 @@ const CollapseMenu = ({ children: JSX.Element | null; }) => { const { pathname } = useLocation(); - const { tenantName } = useGlobalState().state; + const { tenantName } = useGlobalState(); const isPendulum = tenantName === TenantName.Pendulum; const isActive = useMemo(() => { @@ -69,7 +69,7 @@ export type NavProps = { }; const Nav = memo(({ onClick }: NavProps) => { - const { state } = useGlobalState(); + const state = useGlobalState(); return (