import { create } from 'zustand'; import { Button, Dialog, FormGroup, Input, VegaIcon, VegaIconNames, } from '@vegaprotocol/ui-toolkit'; import { useCallback, useState } from 'react'; import type { WalletClientError } from '@vegaprotocol/wallet-client'; import { t } from '@vegaprotocol/i18n'; import type { VegaConnector } from '../connectors'; import { InjectedConnector } from '../connectors'; import { ViewConnector } from '../connectors'; import { JsonRpcConnector, RestConnector } from '../connectors'; import { RestConnectorForm } from './rest-connector-form'; import { JsonRpcConnectorForm } from './json-rpc-connector-form'; import { Networks, useEnvironment } from '@vegaprotocol/environment'; import { ConnectDialogContent, ConnectDialogFooter, ConnectDialogTitle, } from './connect-dialog-elements'; import type { Status as JsonRpcStatus } from '../use-json-rpc-connect'; import type { Status as InjectedStatus } from '../use-injected-connector'; import { useJsonRpcConnect } from '../use-json-rpc-connect'; import { ViewConnectorForm } from './view-connector-form'; import { useChainIdQuery } from './__generated__/ChainId'; import { useVegaWallet } from '../use-vega-wallet'; import { useInjectedConnector } from '../use-injected-connector'; import { InjectedConnectorForm } from './injected-connector-form'; export const CLOSE_DELAY = 1700; type Connectors = { [key: string]: VegaConnector }; export type WalletType = 'injected' | 'jsonRpc' | 'rest' | 'view'; export interface VegaConnectDialogProps { connectors: Connectors; riskMessage?: React.ReactNode; } export interface VegaWalletDialogStore { vegaWalletDialogOpen: boolean; updateVegaWalletDialog: (open: boolean) => void; openVegaWalletDialog: () => void; closeVegaWalletDialog: () => void; } export const useVegaWalletDialogStore = create()( (set) => ({ vegaWalletDialogOpen: false, updateVegaWalletDialog: (open: boolean) => set({ vegaWalletDialogOpen: open }), openVegaWalletDialog: () => set({ vegaWalletDialogOpen: true }), closeVegaWalletDialog: () => set({ vegaWalletDialogOpen: false }), }) ); export const VegaConnectDialog = ({ connectors, riskMessage, }: VegaConnectDialogProps) => { const { disconnect, acknowledgeNeeded } = useVegaWallet(); const vegaWalletDialogOpen = useVegaWalletDialogStore( (store) => store.vegaWalletDialogOpen ); const updateVegaWalletDialog = useVegaWalletDialogStore( (store) => (open: boolean) => { store.updateVegaWalletDialog(open); } ); const onVegaWalletDialogChange = useCallback( (open: boolean) => { updateVegaWalletDialog(open); if (!open && acknowledgeNeeded) { disconnect(); } }, [updateVegaWalletDialog, acknowledgeNeeded, disconnect] ); // Ensure we have a chain Id so we can compare with wallet chain id. // This value will already be in the cache, if it failed the app wont render const { data } = useChainIdQuery(); return ( {data && ( )} ); }; const ConnectDialogContainer = ({ connectors, appChainId, riskMessage, }: { connectors: Connectors; appChainId: string; riskMessage?: React.ReactNode; }) => { const { VEGA_WALLET_URL, VEGA_ENV, HOSTED_WALLET_URL } = useEnvironment(); const closeDialog = useVegaWalletDialogStore( (store) => store.closeVegaWalletDialog ); const [selectedConnector, setSelectedConnector] = useState(); const [walletUrl, setWalletUrl] = useState(VEGA_WALLET_URL || ''); const reset = useCallback(() => { setSelectedConnector(undefined); }, []); const delayedOnConnect = useCallback(() => { setTimeout(() => { closeDialog(); }, CLOSE_DELAY); }, [closeDialog]); const { connect: jsonRpcConnect, ...jsonRpcState } = useJsonRpcConnect(delayedOnConnect); const { connect: injectedConnect, ...injectedState } = useInjectedConnector(delayedOnConnect); const handleSelect = (type: WalletType) => { const connector = connectors[type]; // If type is rest user has selected the hosted wallet option. So here // we ensure that we are connecting to https://vega-hosted-wallet.on.fleek.co/ // otherwise use walletUrl which defaults to the localhost:1789 connector.url = type === 'rest' ? HOSTED_WALLET_URL : walletUrl; if (!connector) { // we should never get here unless connectors are not configured correctly throw new Error(`Connector type: ${type} not configured`); } setSelectedConnector(connector); // Immediately connect on selection if jsonRpc is selected, we can't do this // for rest because we need to show an authentication form if (connector instanceof JsonRpcConnector) { jsonRpcConnect(connector, appChainId); } else if (connector instanceof InjectedConnector) { injectedConnect(connector, appChainId); } }; return ( <> {selectedConnector !== undefined ? ( ) : ( )} ); }; const ConnectorList = ({ onSelect, walletUrl, setWalletUrl, isMainnet, }: { onSelect: (type: WalletType) => void; walletUrl: string; setWalletUrl: (value: string) => void; isMainnet: boolean; }) => { return ( <> {t('Connect')}
  • onSelect('jsonRpc')} />
  • {'vega' in window && (
  • onSelect('injected')} />
  • )} {!isMainnet && (
  • onSelect('rest')} />
  • )}
  • {t('OR')}
    onSelect('view')} />
); }; const SelectedForm = ({ connector, appChainId, jsonRpcState, injectedState, reset, onConnect, riskMessage, }: { connector: VegaConnector; appChainId: string; jsonRpcState: { status: JsonRpcStatus; error: WalletClientError | null; }; injectedState: { status: InjectedStatus; error: Error | null; }; reset: () => void; onConnect: () => void; riskMessage?: React.ReactNode; }) => { if (connector instanceof InjectedConnector) { return ( ); } if (connector instanceof RestConnector) { return ( <> {t('Connect')}
); } if (connector instanceof JsonRpcConnector) { return ( ); } if (connector instanceof ViewConnector) { return ( ); } throw new Error('No connector selected'); }; const ConnectionOption = ({ type, text, onClick, }: { type: WalletType; text: string; onClick: () => void; }) => { return ( ); }; const CustomUrlInput = ({ walletUrl, setWalletUrl, }: { walletUrl: string; setWalletUrl: (url: string) => void; }) => { const [urlInputExpanded, setUrlInputExpanded] = useState(false); return urlInputExpanded ? ( <>

{t('Custom wallet location')}

setWalletUrl(e.target.value)} name="wallet-url" />

{t('Choose wallet app to connect')}

) : (

{t( 'Choose wallet app to connect, or to change port or server URL enter a ' )} {' '} {t(' first')}

); };