From fba310175391e93c4764eec377bf10cb9d7bd270 Mon Sep 17 00:00:00 2001 From: Matthew Russell Date: Tue, 22 Feb 2022 15:06:35 -0800 Subject: [PATCH] refactor so that consuming app chooses to render modal and what connectors to use --- apps/trading/lib/connectors.ts | 6 + apps/trading/pages/_app.page.tsx | 10 +- .../src/lib/vega-wallet/connect-dialog.tsx | 105 ++++++++++-------- ...ega-wallet-connectors.ts => connectors.ts} | 0 .../{vega-wallet-context.ts => context.ts} | 3 +- .../src/lib/vega-wallet/index.ts | 6 +- ...{vega-wallet-provider.tsx => provider.tsx} | 25 +---- .../lib/vega-wallet/rest-connector-form.tsx | 35 +++--- libs/storage/src/index.ts | 21 ++-- .../src/components/dialog/index.tsx | 21 +++- 10 files changed, 134 insertions(+), 98 deletions(-) create mode 100644 apps/trading/lib/connectors.ts rename libs/react-helpers/src/lib/vega-wallet/{vega-wallet-connectors.ts => connectors.ts} (100%) rename libs/react-helpers/src/lib/vega-wallet/{vega-wallet-context.ts => context.ts} (80%) rename libs/react-helpers/src/lib/vega-wallet/{vega-wallet-provider.tsx => provider.tsx} (63%) diff --git a/apps/trading/lib/connectors.ts b/apps/trading/lib/connectors.ts new file mode 100644 index 000000000..f42de85fb --- /dev/null +++ b/apps/trading/lib/connectors.ts @@ -0,0 +1,6 @@ +import { InjectedConnector, RestConnector } from '@vegaprotocol/react-helpers'; + +export const Connectors = { + injected: new InjectedConnector(), + rest: new RestConnector(), +}; diff --git a/apps/trading/pages/_app.page.tsx b/apps/trading/pages/_app.page.tsx index b73870b31..e8d3c1349 100644 --- a/apps/trading/pages/_app.page.tsx +++ b/apps/trading/pages/_app.page.tsx @@ -50,15 +50,19 @@ function VegaTradingApp({ Component, pageProps }: AppProps) { ); } -const VegaWalletButton = () => { - const { setConnectDialog, disconnect, publicKeys } = useVegaWallet(); +interface VegaWalletButtonProps { + setConnectDialog: (isOpen: boolean) => void; +} + +const VegaWalletButton = ({ setConnectDialog }: VegaWalletButtonProps) => { + const { disconnect, publicKeys } = useVegaWallet(); const isConnected = publicKeys !== null; const handleClick = () => { if (isConnected) { disconnect(); } else { - setConnectDialog(); + setConnectDialog(true); } }; diff --git a/libs/react-helpers/src/lib/vega-wallet/connect-dialog.tsx b/libs/react-helpers/src/lib/vega-wallet/connect-dialog.tsx index ea127ad69..07e99a055 100644 --- a/libs/react-helpers/src/lib/vega-wallet/connect-dialog.tsx +++ b/libs/react-helpers/src/lib/vega-wallet/connect-dialog.tsx @@ -1,63 +1,80 @@ -import { useState } from 'react'; +import { useCallback, useState } from 'react'; import { Dialog } from '@vegaprotocol/ui-toolkit'; -import { - InjectedConnector, - RestConnector, - VegaConnector, -} from './vega-wallet-connectors'; +import { VegaConnector } from './connectors'; import { RestConnectorForm } from './rest-connector-form'; import { useEffect } from 'react'; +import { RestConnector, useVegaWallet } from '.'; -export const Connectors = { - injected: new InjectedConnector(), - rest: new RestConnector(), -}; - -interface ConnectDialogProps { +interface VegaConnectDialogProps { + connectors: { [name: string]: VegaConnector }; dialogOpen: boolean; setDialogOpen: (isOpen: boolean) => void; - connect: (connector: VegaConnector) => void; } -export function ConnectDialog({ +export function VegaConnectDialog({ + connectors, dialogOpen, setDialogOpen, - connect, -}: ConnectDialogProps) { - const [isRestConnector, setIsRestConnector] = useState(false); +}: VegaConnectDialogProps) { + const { connect } = useVegaWallet(); + const [selectedConnector, setSelectedConnector] = + useState(null); + + const connectAndClose = useCallback( + (connector: VegaConnector) => { + connect(connector); + setDialogOpen(false); + }, + [connect, setDialogOpen] + ); useEffect(() => { - if (!dialogOpen) { - setIsRestConnector(false); + if ( + selectedConnector !== null && + selectedConnector instanceof RestConnector === false + ) { + connectAndClose(selectedConnector); } - }, [dialogOpen]); + }, [selectedConnector, connectAndClose]); return ( -
- {isRestConnector ? ( - - ) : ( -
- {Object.entries(Connectors).map(([key, connector]) => ( - - ))} -
- )} -
+ {selectedConnector instanceof RestConnector ? ( + { + connectAndClose(selectedConnector); + }} + /> + ) : ( +
+ {Object.entries(connectors).map(([key, connector]) => ( + + ))} +
+ )}
); } diff --git a/libs/react-helpers/src/lib/vega-wallet/vega-wallet-connectors.ts b/libs/react-helpers/src/lib/vega-wallet/connectors.ts similarity index 100% rename from libs/react-helpers/src/lib/vega-wallet/vega-wallet-connectors.ts rename to libs/react-helpers/src/lib/vega-wallet/connectors.ts diff --git a/libs/react-helpers/src/lib/vega-wallet/vega-wallet-context.ts b/libs/react-helpers/src/lib/vega-wallet/context.ts similarity index 80% rename from libs/react-helpers/src/lib/vega-wallet/vega-wallet-context.ts rename to libs/react-helpers/src/lib/vega-wallet/context.ts index 39472be04..cc6f0dd17 100644 --- a/libs/react-helpers/src/lib/vega-wallet/vega-wallet-context.ts +++ b/libs/react-helpers/src/lib/vega-wallet/context.ts @@ -1,11 +1,10 @@ import { VegaKey } from '@vegaprotocol/vegawallet-service-api-client'; import { createContext } from 'react'; -import { VegaConnector } from './vega-wallet-connectors'; +import { VegaConnector } from './connectors'; interface VegaWalletContextShape { publicKey: VegaKey | null; publicKeys: VegaKey[] | null; - setConnectDialog: (isOpen?: boolean) => void; connect: (connector: VegaConnector) => Promise; disconnect: () => Promise; connector: VegaConnector | null; diff --git a/libs/react-helpers/src/lib/vega-wallet/index.ts b/libs/react-helpers/src/lib/vega-wallet/index.ts index ff51a2552..b2c3fe5b3 100644 --- a/libs/react-helpers/src/lib/vega-wallet/index.ts +++ b/libs/react-helpers/src/lib/vega-wallet/index.ts @@ -1,3 +1,5 @@ -export * from './vega-wallet-provider'; -export * from './vega-wallet-context'; +export * from './provider'; +export * from './context'; export * from './hooks'; +export * from './connect-dialog'; +export * from './connectors'; diff --git a/libs/react-helpers/src/lib/vega-wallet/vega-wallet-provider.tsx b/libs/react-helpers/src/lib/vega-wallet/provider.tsx similarity index 63% rename from libs/react-helpers/src/lib/vega-wallet/vega-wallet-provider.tsx rename to libs/react-helpers/src/lib/vega-wallet/provider.tsx index 3a067e2ac..99dc78be0 100644 --- a/libs/react-helpers/src/lib/vega-wallet/vega-wallet-provider.tsx +++ b/libs/react-helpers/src/lib/vega-wallet/provider.tsx @@ -1,40 +1,31 @@ import { VegaKey } from '@vegaprotocol/vegawallet-service-api-client'; import { ReactNode, useCallback, useMemo, useRef, useState } from 'react'; -import { ConnectDialog } from './connect-dialog'; -import { VegaConnector } from './vega-wallet-connectors'; -import { VegaWalletContext } from './vega-wallet-context'; +import { VegaConnector } from './connectors'; +import { VegaWalletContext } from './context'; interface VegaWalletProviderProps { children: ReactNode; } export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => { - const [dialogOpen, setDialogOpen] = useState(false); const [publicKey, setPublicKey] = useState(null); const [publicKeys, setPublicKeys] = useState(null); const connector = useRef(null); - const setConnectDialog = useCallback((isOpen?: boolean) => { - setDialogOpen((curr) => { - if (isOpen === undefined) return !curr; - return isOpen; - }); - }, []); - const connect = useCallback(async (c: VegaConnector) => { connector.current = c; try { const res = await c.connect(); setPublicKeys(res); + setPublicKey(res[0]); } catch (err) { console.log('connect failed'); } }, []); const disconnect = useCallback(async () => { - if (!connector.current) return; try { - await connector.current.disconnect(); + await connector.current?.disconnect(); setPublicKeys(null); setPublicKey(null); connector.current = null; @@ -47,21 +38,15 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => { return { publicKey, publicKeys, - setConnectDialog, connect, disconnect, connector: connector.current, }; - }, [publicKey, publicKeys, connect, disconnect, setConnectDialog, connector]); + }, [publicKey, publicKeys, connect, disconnect, connector]); return ( {children} - ); }; diff --git a/libs/react-helpers/src/lib/vega-wallet/rest-connector-form.tsx b/libs/react-helpers/src/lib/vega-wallet/rest-connector-form.tsx index 3d43a1ea8..b48799b5a 100644 --- a/libs/react-helpers/src/lib/vega-wallet/rest-connector-form.tsx +++ b/libs/react-helpers/src/lib/vega-wallet/rest-connector-form.tsx @@ -1,6 +1,5 @@ import { useForm } from 'react-hook-form'; -import { useVegaWallet } from '.'; -import { Connectors } from './connect-dialog'; +import { RestConnector } from '.'; interface FormFields { wallet: string; @@ -8,23 +7,31 @@ interface FormFields { } interface RestConnectorFormProps { + connector: RestConnector; setDialogOpen: (isOpen: boolean) => void; + onAuthenticate: () => void; } -export function RestConnectorForm({ setDialogOpen }: RestConnectorFormProps) { - const { connect } = useVegaWallet(); - const { register, handleSubmit } = useForm(); +export function RestConnectorForm({ + connector, + setDialogOpen, + onAuthenticate, +}: RestConnectorFormProps) { + const { + register, + handleSubmit, + formState: { errors }, + } = useForm(); async function onSubmit(fields: FormFields) { try { - const success = await Connectors.rest.authenticate({ + const success = await connector.authenticate({ wallet: fields.wallet, passphrase: fields.passphrase, }); if (success) { - connect(Connectors.rest); - setDialogOpen(false); + onAuthenticate(); } else { throw new Error('Authentication failed'); } @@ -35,21 +42,21 @@ export function RestConnectorForm({ setDialogOpen }: RestConnectorFormProps) { return (
-
+
+ {errors.wallet?.message &&
{errors.wallet.message}
}
-
+
+ {errors.passphrase?.message &&
{errors.passphrase.message}
}
diff --git a/libs/storage/src/index.ts b/libs/storage/src/index.ts index 6f5add3fc..b2595514f 100644 --- a/libs/storage/src/index.ts +++ b/libs/storage/src/index.ts @@ -1,18 +1,19 @@ // TODO: fine for now however will leak state between tests (we don't really have) in future. Ideally should use a provider export const LocalStorage = { getItem: (key: string) => { - if (typeof window === 'undefined') return null; - try { - const item = window.localStorage.getItem(key); - return item ? JSON.parse(item) : null; - } catch (error) { - console.error(error); - } - }, - setItem: (key: string, value: any) => { if (typeof window === 'undefined') return; try { - window.localStorage.setItem(key, JSON.stringify(value)); + const item = window.localStorage.getItem(key); + return item; + } catch (error) { + console.error(error); + return null; + } + }, + setItem: (key: string, value: string) => { + if (typeof window === 'undefined') return; + try { + window.localStorage.setItem(key, value); } catch (error) { console.error(error); } diff --git a/libs/ui-toolkit/src/components/dialog/index.tsx b/libs/ui-toolkit/src/components/dialog/index.tsx index 71cbf6506..d2a05bb09 100644 --- a/libs/ui-toolkit/src/components/dialog/index.tsx +++ b/libs/ui-toolkit/src/components/dialog/index.tsx @@ -11,10 +11,25 @@ export function Dialog({ children, open, setOpen }: DialogProps) { return ( setOpen(x)}> - + {children}