add vega wallet manager component and re add current single pubkey to provider state

This commit is contained in:
Matthew Russell 2022-02-23 16:03:59 -08:00
parent 84af6177ad
commit e92e708cf1
3 changed files with 60 additions and 73 deletions

View File

@ -6,11 +6,7 @@ import { Connectors, rest } from '../lib/connectors';
import { LocalStorage } from '@vegaprotocol/storage'; import { LocalStorage } from '@vegaprotocol/storage';
export function Index() { export function Index() {
// Get keys from vega wallet immediately const { keypair, keypairs, selectPublicKey } = useVegaWallet();
useEagerConnect();
const { publicKeys } = useVegaWallet();
const { publicKey, onSelect } = useCurrentVegaKey();
return ( return (
<div className="m-24 "> <div className="m-24 ">
@ -28,14 +24,17 @@ export function Index() {
</div> </div>
</Callout> </Callout>
<h1>Vega wallet</h1> <h1>Vega wallet</h1>
{publicKey && <p>Current: {publicKey.pub}</p>} {keypair && <p>Current: {keypair.pub}</p>}
{publicKeys?.length && ( {keypairs?.length && (
<select <select
name="change-key" name="change-key"
value={publicKey?.pub} defaultValue="none"
onChange={(e) => onSelect(e.target.value)} onChange={(e) => selectPublicKey(e.target.value)}
> >
{publicKeys.map((pk) => ( <option value="none" disabled={true}>
Please select
</option>
{keypairs.map((pk) => (
<option key={pk.pub} value={pk.pub}> <option key={pk.pub} value={pk.pub}>
{pk.name} ({pk.pub}) {pk.name} ({pk.pub})
</option> </option>
@ -44,64 +43,9 @@ export function Index() {
)} )}
<hr /> <hr />
<h2>Public keys</h2> <h2>Public keys</h2>
<pre>{JSON.stringify(publicKeys, null, 2)}</pre> <pre>{JSON.stringify(keypairs, null, 2)}</pre>
</div> </div>
); );
} }
export default Index; export default Index;
function useEagerConnect() {
const { connect } = useVegaWallet();
useEffect(() => {
const cfg = LocalStorage.getItem('vega_wallet');
const cfgObj = JSON.parse(cfg);
// No stored config, user has never connected or manually cleared storage
if (!cfgObj || !cfgObj.connector) {
return;
}
const connector = Connectors[cfgObj.connector];
// Developer hasn't provided this connector
if (!connector) {
throw new Error(`Connector ${cfgObj?.connector} not configured`);
}
connect(Connectors[cfgObj.connector]);
}, [connect]);
}
function useCurrentVegaKey(): {
publicKey: VegaKeyExtended | null;
onSelect: (pk: string) => void;
} {
const { publicKeys } = useVegaWallet();
const [pk, setPk] = useState<string | null>(() =>
LocalStorage.getItem('vega_selected_publickey')
);
const publicKey = useMemo(() => {
if (!publicKeys?.length) return null;
const found = publicKeys.find((x) => x.pub === pk);
if (found) {
return found;
}
return null;
}, [pk, publicKeys]);
// on public key change set to localStorage
useEffect(() => {
LocalStorage.setItem('vega_selected_publickey', pk);
}, [pk]);
return {
publicKey,
onSelect: setPk,
};
}

View File

@ -7,8 +7,11 @@ export interface VegaKeyExtended extends VegaKey {
} }
export interface VegaWalletContextShape { export interface VegaWalletContextShape {
/** The current select public key */
keypair: VegaKeyExtended | null;
/** Public keys stored in users wallet */ /** Public keys stored in users wallet */
publicKeys: VegaKeyExtended[] | null; keypairs: VegaKeyExtended[] | null;
/** Calls connect on the supplied connector, storing the returned keys */ /** Calls connect on the supplied connector, storing the returned keys */
connect: (connector: VegaConnector) => Promise<void>; connect: (connector: VegaConnector) => Promise<void>;
@ -16,6 +19,9 @@ export interface VegaWalletContextShape {
/** Disconnects from the connector and clears public key state */ /** Disconnects from the connector and clears public key state */
disconnect: () => Promise<void>; disconnect: () => Promise<void>;
/** Sets the current selected public key */
selectPublicKey: (publicKey: string) => void;
/** Reference to the connector */ /** Reference to the connector */
connector: VegaConnector | null; connector: VegaConnector | null;
} }

View File

@ -1,4 +1,12 @@
import { ReactNode, useCallback, useMemo, useRef, useState } from 'react'; import { LocalStorage } from '@vegaprotocol/storage';
import {
ReactNode,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { VegaKeyExtended, VegaWalletContextShape } from '.'; import { VegaKeyExtended, VegaWalletContextShape } from '.';
import { VegaConnector } from './connectors'; import { VegaConnector } from './connectors';
import { VegaWalletContext } from './context'; import { VegaWalletContext } from './context';
@ -8,7 +16,16 @@ interface VegaWalletProviderProps {
} }
export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => { export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
const [publicKeys, setPublicKeys] = useState<VegaKeyExtended[] | null>(null); // Current selected publicKey, default with value from local storage
const [publicKey, setPublicKey] = useState<string | null>(() => {
const pk = LocalStorage.getItem('vega_selected_publickey');
return pk ? pk : null;
});
// Keypair objects retrieved from the connector
const [keypairs, setKeypairs] = useState<VegaKeyExtended[] | null>(null);
// Reference to the current connector instance
const connector = useRef<VegaConnector | null>(null); const connector = useRef<VegaConnector | null>(null);
const connect = useCallback(async (c: VegaConnector) => { const connect = useCallback(async (c: VegaConnector) => {
@ -28,7 +45,7 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
name: nameMeta?.value ? nameMeta.value : 'None', name: nameMeta?.value ? nameMeta.value : 'None',
}; };
}); });
setPublicKeys(publicKeysWithName); setKeypairs(publicKeysWithName);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -37,21 +54,41 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
const disconnect = useCallback(async () => { const disconnect = useCallback(async () => {
try { try {
await connector.current?.disconnect(); await connector.current?.disconnect();
setPublicKeys(null); setKeypairs(null);
connector.current = null; connector.current = null;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
}, []); }, []);
// Current selected keypair derived from publicKey state
const keypair = useMemo(() => {
const found = keypairs?.find((x) => x.pub === publicKey);
if (found) {
return found;
}
return null;
}, [publicKey, keypairs]);
// Whenever selected public key changes store it
useEffect(() => {
if (publicKey) {
LocalStorage.setItem('vega_selected_publickey', publicKey);
}
}, [publicKey]);
const contextValue = useMemo<VegaWalletContextShape>(() => { const contextValue = useMemo<VegaWalletContextShape>(() => {
return { return {
publicKeys, keypair,
keypairs,
selectPublicKey: setPublicKey,
connect, connect,
disconnect, disconnect,
connector: connector.current, connector: connector.current,
}; };
}, [publicKeys, connect, disconnect, connector]); }, [keypair, keypairs, setPublicKey, connect, disconnect, connector]);
return ( return (
<VegaWalletContext.Provider value={contextValue}> <VegaWalletContext.Provider value={contextValue}>