Compare commits

..
Author SHA1 Message Date
Artandbwallacee 2a0727ec4b chore(trading): scoped to teams games (#5920)
Co-authored-by: bwallacee <ben@vega.xyz>
2024-03-06 11:44:33 +00:00
18 changed files with 176 additions and 287 deletions
@@ -79,14 +79,14 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
});
it.skip('should have information on active nodes', function () {
it('should have information on active nodes', function () {
cy.getByTestId('node-information')
.first()
.should('contain.text', '2')
.and('contain.text', 'active nodes');
});
it.skip('should have information on consensus nodes', function () {
it('should have information on consensus nodes', function () {
cy.getByTestId('node-information')
.last()
.should('contain.text', '2')
+2 -4
View File
@@ -26,9 +26,9 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
const { token, staking, vesting } = useContracts();
const setAssociatedBalances = useRefreshAssociatedBalances();
const [balancesLoaded, setBalancesLoaded] = React.useState(false);
const vegaWalletStatus = useEagerConnect();
const vegaConnecting = useEagerConnect();
const loaded = balancesLoaded && vegaWalletStatus !== 'connecting';
const loaded = balancesLoaded && !vegaConnecting;
React.useEffect(() => {
const run = async () => {
@@ -169,5 +169,3 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
}
return <Suspense fallback={loading}>{children}</Suspense>;
};
AppLoader.displayName = 'AppLoader';
@@ -111,4 +111,3 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
</ContractsContext.Provider>
);
};
ContractsProvider.displayName = 'ContractsProvider';
+2
View File
@@ -50,6 +50,8 @@ def truncate_middle(market_id, start=6, end=4):
def change_keys(page: Page, vega: VegaServiceNull, key_name):
page.get_by_test_id("manage-vega-wallet").click()
page.get_by_test_id("key-" + vega.wallet.public_key(key_name)).click()
page.click(
f'data-testid=key-{vega.wallet.public_key(key_name)} >> .inline-flex')
page.reload()
+3 -3
View File
@@ -299,10 +299,10 @@ def test_leaderboard(competitions_page: Page, setup_teams_and_games):
def test_game_card(competitions_page: Page):
expect(competitions_page.get_by_test_id("active-rewards-card")).to_have_count(2)
expect(competitions_page.get_by_test_id("active-rewards-card")).to_have_count(1)
game_1 = competitions_page.get_by_test_id("active-rewards-card").first
expect(game_1).to_be_visible()
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Individual")
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Team")
expect(game_1.get_by_test_id("locked-for")).to_have_text("1 epoch")
expect(game_1.get_by_test_id("reward-value")).to_have_text("100.00")
expect(game_1.get_by_test_id("reward-asset")).to_have_text("VEGA")
@@ -311,7 +311,7 @@ def test_game_card(competitions_page: Page):
"Price maker fees paid • tDAI"
)
expect(game_1.get_by_test_id("assessed-over")).to_have_text("15 epochs")
expect(game_1.get_by_test_id("scope")).to_have_text("In team")
expect(game_1.get_by_test_id("scope")).to_have_text("All teams")
expect(game_1.get_by_test_id("staking-requirement")).to_have_text("0.00")
expect(game_1.get_by_test_id("average-position")).to_have_text("0.00")
+2 -2
View File
@@ -194,11 +194,11 @@ describe('isScopedToTeams', () => {
undefined,
makeDispatchStrategy(
EntityScope.ENTITY_SCOPE_INDIVIDUALS,
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM // individual in teams
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM // individual in teams but not a team game
),
'RecurringTransfer'
),
true,
false,
],
[
makeReward(
+1 -11
View File
@@ -14,7 +14,6 @@ import {
TransferStatus,
type DispatchStrategy,
EntityScope,
IndividualScope,
MarketState,
AccountType,
} from '@vegaprotocol/types';
@@ -75,20 +74,11 @@ export const isActiveReward = (node: RewardTransfer, currentEpoch: number) => {
/**
* Checks if given reward (transfer) is scoped to teams.
*
* A reward is scoped to teams if it's entity scope is set to teams or
* if the scope is set to individuals but the individuals are in a team.
*/
export const isScopedToTeams = (node: EnrichedRewardTransfer) =>
// scoped to teams
node.transfer.kind.dispatchStrategy?.entityScope ===
EntityScope.ENTITY_SCOPE_TEAMS ||
// or to individuals
(node.transfer.kind.dispatchStrategy?.entityScope ===
EntityScope.ENTITY_SCOPE_INDIVIDUALS &&
// but they have to be in a team
node.transfer.kind.dispatchStrategy?.individualScope ===
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM);
EntityScope.ENTITY_SCOPE_TEAMS;
/** Retrieves rewards (transfers) */
export const useRewards = ({
@@ -7,7 +7,6 @@
"Get MetaMask": "Get MetaMask",
"Get the Vega Wallet": "Get the Vega Wallet",
"I agree": "I agree",
"Once you have the added the extension, <0>refresh</0> you browser.": "Once you have the added the extension, <0>refresh</0> you browser.",
"Successfully connected": "Successfully connected",
"Transaction was not successful": "Transaction was not successful",
"Wallet rejected transaction": "Wallet rejected transaction"
@@ -17,8 +17,8 @@ export const InputError = ({
...props
}: InputErrorProps) => {
const effectiveClassName = classNames(
'text-sm block items-center first-letter:capitalize',
'mt-2 min-w-0 break-words',
'text-sm flex items-center first-letter:uppercase',
'mt-2',
{
'border-danger': intent === 'danger',
'border-warning': intent === 'warning',
@@ -1,9 +1,4 @@
import {
type ReactNode,
type FunctionComponent,
forwardRef,
useState,
} from 'react';
import { type ReactNode, type FunctionComponent, forwardRef } from 'react';
import {
ConnectorErrors,
isBrowserWalletInstalled,
@@ -17,7 +12,6 @@ import { useConnect } from '../../hooks/use-connect';
import { Links } from '../../constants';
import { ConnectorIcon } from './connector-icon';
import { useUserAgent } from '@vegaprotocol/react-helpers';
import { Trans } from 'react-i18next';
const vegaExtensionsLinks = {
chrome: Links.chromeExtension,
@@ -35,67 +29,48 @@ export const ConnectionOptions = ({
onConnect: (id: ConnectorType) => void;
}) => {
const t = useT();
const { connectors } = useConnect();
const error = useWallet((store) => store.error);
const [isInstalling, setIsInstalling] = useState(false);
const { connectors } = useConnect();
return (
<div className="flex flex-col items-start gap-4">
<h2 className="text-xl">{t('Connect to Vega')}</h2>
{isInstalling ? (
<p className="text-warning">
<Trans
i18nKey="Once you have the added the extension, <0>refresh</0> you browser."
components={[
<button
onClick={() => window.location.reload()}
className="underline underline-offset-4"
/>,
]}
/>
<ul
className="grid grid-cols-1 sm:grid-cols-2 gap-1 -mx-2"
data-testid="connectors-list"
>
{connectors.map((c) => {
const ConnectionOption = ConnectionOptionRecord[c.id];
const props = {
id: c.id,
name: c.name,
description: c.description,
showDescription: false,
onClick: () => onConnect(c.id),
};
if (ConnectionOption) {
return (
<li key={c.id}>
<ConnectionOption {...props} />
</li>
);
}
return (
<li key={c.id}>
<ConnectionOptionDefault {...props} />
</li>
);
})}
</ul>
{error && error.code !== ConnectorErrors.userRejected.code && (
<p
className="text-danger text-sm first-letter:uppercase"
data-testid="connection-error"
>
{error.message}
</p>
) : (
<>
<ul
className="grid grid-cols-1 sm:grid-cols-2 gap-1 -mx-2"
data-testid="connectors-list"
>
{connectors.map((c) => {
const ConnectionOption = ConnectionOptionRecord[c.id];
const props = {
id: c.id,
name: c.name,
description: c.description,
showDescription: false,
onClick: () => onConnect(c.id),
onInstall: () => setIsInstalling(true),
};
if (ConnectionOption) {
return (
<li key={c.id}>
<ConnectionOption {...props} />
</li>
);
}
return (
<li key={c.id}>
<ConnectionOptionDefault {...props} />
</li>
);
})}
</ul>
{error && error.code !== ConnectorErrors.userRejected.code && (
<p
className="text-danger text-sm first-letter:uppercase"
data-testid="connection-error"
>
{error.message}
{error.data ? `: ${error.data}` : ''}
</p>
)}
</>
)}
<a
href={Links.walletOverview}
@@ -115,7 +90,6 @@ interface ConnectionOptionProps {
description: string;
showDescription?: boolean;
onClick: () => void;
onInstall?: () => void;
}
const CONNECTION_OPTION_CLASSES =
@@ -168,7 +142,6 @@ export const ConnectionOptionInjected = ({
description,
showDescription = false,
onClick,
onInstall,
}: ConnectionOptionProps) => {
const t = useT();
const userAgent = useUserAgent();
@@ -185,11 +158,7 @@ export const ConnectionOptionInjected = ({
</span>
</ConnectionOptionButtonWithDescription>
) : (
<ConnectionOptionLinkWithDescription
id={id}
href={link}
onClick={onInstall}
>
<ConnectionOptionLinkWithDescription id={id} href={link}>
<span className="flex flex-col justify-start text-left">
<span className="capitalize leading-5">
{t('Get the Vega Wallet')}
@@ -214,7 +183,7 @@ export const ConnectionOptionInjected = ({
{name}
</ConnectionOptionButton>
) : (
<ConnectionOptionLink id={id} href={link} onClick={onInstall}>
<ConnectionOptionLink id={id} href={link}>
{t('Get the Vega Wallet')}
</ConnectionOptionLink>
)}
@@ -306,9 +275,8 @@ const ConnectionOptionLink = forwardRef<
children: ReactNode;
id: ConnectorType;
href: string;
onClick?: () => void;
}
>(({ children, id, href, onClick }, ref) => {
>(({ children, id, href }, ref) => {
return (
<a
href={href}
@@ -317,7 +285,6 @@ const ConnectionOptionLink = forwardRef<
className={CONNECTION_OPTION_CLASSES}
data-testid={`connector-${id}`}
ref={ref}
onClick={onClick}
>
<ConnectorIcon id={id} />
{children}
@@ -353,10 +320,8 @@ const ConnectionOptionLinkWithDescription = forwardRef<
children: ReactNode;
id: ConnectorType;
href: string;
onClick?: () => void;
}
>(({ children, id, href, onClick }, ref) => {
>(({ children, id, href }, ref) => {
return (
<a
ref={ref}
@@ -364,7 +329,6 @@ const ConnectionOptionLinkWithDescription = forwardRef<
href={href}
target="_blank"
rel="noreferrer"
onClick={onClick}
>
<span>
<ConnectorIcon id={id} />
@@ -1,20 +1,17 @@
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { useWallet } from './use-wallet';
import { useConnect } from './use-connect';
export function useEagerConnect() {
const current = useWallet((store) => store.current);
const status = useWallet((store) => store.status);
const { connect } = useConnect();
const [connecting, setConnecting] = useState(true);
useEffect(() => {
const attemptConnect = async () => {
// No stored config, or config was malformed or no risk accepted
if (!current) {
return;
}
if (status !== 'disconnected') {
setConnecting(false);
return;
}
@@ -22,13 +19,15 @@ export function useEagerConnect() {
await connect(current);
} catch {
console.warn(`Failed to connect with connector: ${current}`);
} finally {
setConnecting(false);
}
};
if (typeof window !== 'undefined') {
attemptConnect();
}
}, [status, connect, current]);
}, [connect, current, connecting]);
return status;
return connecting;
}
@@ -65,12 +65,12 @@ export const useSimpleTransaction = (opts?: Options) => {
if (err.code === ConnectorErrors.userRejected.code) {
setStatus('idle');
} else {
setError(`${err.message}${err.data ? `: ${err.data}` : ''}`);
setError(err.message);
setStatus('idle');
opts?.onError?.(err.message);
}
} else {
const msg = t('Something went wrong');
const msg = t('Wallet rejected transaction');
setError(msg);
setStatus('idle');
opts?.onError?.(msg);
@@ -7,7 +7,6 @@ import {
listKeysError,
noWalletError,
sendTransactionError,
userRejectedError,
} from '../errors';
import {
type TransactionParams,
@@ -15,19 +14,6 @@ import {
type VegaWalletEvent,
} from '../types';
interface InjectedError {
message: string;
code: number;
data:
| {
message: string;
code: number;
}
| string;
}
const USER_REJECTED_CODE = -4;
export class InjectedConnector implements Connector {
readonly id = 'injected';
readonly name = 'Vega Wallet';
@@ -99,55 +85,15 @@ export class InjectedConnector implements Connector {
sentAt: res.sentAt,
};
} catch (err) {
if (this.isInjectedError(err)) {
if (err.code === USER_REJECTED_CODE) {
throw userRejectedError();
}
if (typeof err.data === 'string') {
throw sendTransactionError(err.data);
} else {
throw sendTransactionError(err.data.message);
}
}
throw sendTransactionError();
}
}
on(event: VegaWalletEvent, callback: () => void) {
// Check for on/off in case user is on older versions which don't support it
// We can remove this check once FF is at the latest version
if (
typeof window.vega !== 'undefined' &&
typeof window.vega.on === 'function'
) {
window.vega.on(event, callback);
}
window.vega.on(event, callback);
}
off(event: VegaWalletEvent, callback: () => void) {
// Check for on/off in case user is on older versions which don't support it
// We can remove this check once FF is at the latest version
if (
typeof window.vega !== 'undefined' &&
typeof window.vega.off === 'function'
) {
window.vega.off(event, callback);
}
}
private isInjectedError(obj: unknown): obj is InjectedError {
if (
obj !== undefined &&
obj !== null &&
typeof obj === 'object' &&
'code' in obj &&
'message' in obj &&
'data' in obj
) {
return true;
}
return false;
window.vega.off(event, callback);
}
}
@@ -17,8 +17,6 @@ import {
type JsonRpcConnectorConfig = { url: string; token?: string };
const USER_REJECTED_CODE = 3001;
export class JsonRpcConnector implements Connector {
readonly id = 'jsonRpc';
readonly name = 'Command Line Wallet';
@@ -29,7 +27,7 @@ export class JsonRpcConnector implements Connector {
requestId: number = 0;
store: StoreApi<Store> | undefined;
pollRef: NodeJS.Timer | undefined;
ee: InstanceType<typeof EventEmitter>;
ee: EventEmitter;
constructor(config: JsonRpcConnectorConfig) {
this.url = config.url;
@@ -65,7 +63,7 @@ export class JsonRpcConnector implements Connector {
const token = response.headers.get('Authorization');
if (!response.ok) {
if ('error' in data && data.error.code === USER_REJECTED_CODE) {
if ('error' in data && data.error.code === 3001) {
throw userRejectedError();
}
throw connectError('response not ok');
@@ -139,7 +137,7 @@ export class JsonRpcConnector implements Connector {
if (!response.ok) {
if ('error' in data) {
if (data.error.code === USER_REJECTED_CODE) {
if (data.error.code === 3001) {
throw userRejectedError();
}
+97 -102
View File
@@ -1,3 +1,4 @@
import EventEmitter from 'eventemitter3';
import {
ConnectorError,
chainIdError,
@@ -5,13 +6,13 @@ import {
listKeysError,
noWalletError,
sendTransactionError,
userRejectedError,
} from '../errors';
import { type Transaction } from '../transaction-types';
import {
JsonRpcMethod,
type Connector,
type TransactionParams,
type VegaWalletEvent,
} from '../types';
enum EthereumMethod {
@@ -42,6 +43,7 @@ declare global {
type WindowEthereumProvider = {
isMetaMask: boolean;
request<T = unknown>(args: RequestArguments): Promise<T>;
selectedAddress: string | null;
};
interface Window {
@@ -50,16 +52,6 @@ declare global {
}
}
interface SnapRPCError {
code: number;
message: string;
data?: {
originalError: { code: number };
};
}
const USER_REJECTED_CODE = -4;
export class SnapConnector implements Connector {
readonly id = 'snap';
readonly name = 'MetaMask Snap';
@@ -69,6 +61,8 @@ export class SnapConnector implements Connector {
node: string;
version: string;
snapId: string;
pollRef: NodeJS.Timer | undefined;
ee: EventEmitter;
// Note: apps may not know which node is selected on start up so its up
// to the app to make sure class intances are renewed if the node changes
@@ -76,21 +70,14 @@ export class SnapConnector implements Connector {
this.node = config.node;
this.version = config.version;
this.snapId = config.snapId;
this.ee = new EventEmitter();
}
bindStore() {}
async connectWallet(desiredChainId: string) {
try {
const res = await this.requestSnap();
if (res[this.snapId].blocked) {
throw connectError('snap is blocked');
}
if (!res[this.snapId].enabled) {
throw connectError('snap is not enabled');
}
await this.requestSnap();
const { chainId } = await this.getChainId();
@@ -100,6 +87,7 @@ export class SnapConnector implements Connector {
);
}
this.startPoll();
return { success: true };
} catch (err) {
if (err instanceof ConnectorError) {
@@ -110,66 +98,57 @@ export class SnapConnector implements Connector {
}
}
async disconnectWallet() {}
async disconnectWallet() {
this.stopPoll();
}
// deprecated, pass chain on connect
async getChainId() {
try {
const data = await this.invokeSnap<{ chainID: string }>(
const res = await this.invokeSnap<{ chainID: string }>(
JsonRpcMethod.GetChainId,
{
networkEndpoints: [this.node],
}
);
if ('error' in data) {
throw chainIdError(data.error.message);
}
return { chainId: data.chainID };
return { chainId: res.chainID };
} catch (err) {
if (err instanceof ConnectorError) {
throw err;
}
this.stopPoll();
throw chainIdError();
}
}
async listKeys() {
try {
const data = await this.invokeSnap<{
const res = await this.invokeSnap<{
keys: Array<{ publicKey: string; name: string }>;
}>(JsonRpcMethod.ListKeys);
if ('error' in data) {
throw listKeysError(data.error.message);
}
return data.keys;
return res.keys;
} catch (err) {
if (err instanceof ConnectorError) {
throw err;
}
this.stopPoll();
throw listKeysError();
}
}
async isConnected() {
try {
// Check if metamask is unlocked
if (!window.ethereum.selectedAddress) {
throw noWalletError();
}
// If this throws its likely the snap is disabled or has been uninstalled
await this.listKeys();
return { connected: true };
} catch (err) {
this.stopPoll();
return { connected: false };
}
}
async sendTransaction(params: TransactionParams) {
try {
// If the transaction is invalid this will throw with SnapRPCError
// but if its rejected it will resolve with 'error' in data
const data = await this.invokeSnap<{
const res = await this.invokeSnap<{
transactionHash: string;
transaction: { signature: { value: string } };
receivedAt: string;
@@ -181,99 +160,115 @@ export class SnapConnector implements Connector {
networkEndpoints: [this.node],
});
if ('error' in data) {
if (data.error.code === USER_REJECTED_CODE) {
throw userRejectedError();
}
throw sendTransactionError(`${data.error.message}: ${data.error.data}`);
}
return {
transactionHash: data.transactionHash,
signature: data.transaction.signature.value,
receivedAt: data.receivedAt,
sentAt: data.sentAt,
transactionHash: res.transactionHash,
signature: res.transaction.signature.value,
receivedAt: res.receivedAt,
sentAt: res.sentAt,
};
} catch (err) {
if (err instanceof ConnectorError) {
throw err;
}
if (this.isSnapRPCError(err)) {
throw sendTransactionError(err.message);
}
throw sendTransactionError();
}
}
on() {}
off() {}
on(event: VegaWalletEvent, callback: () => void) {
this.ee.on(event, callback);
}
off(event: VegaWalletEvent, callback?: () => void) {
this.ee.off(event, callback);
}
////////////////////////////////////
// Snap methods
////////////////////////////////////
private startPoll() {
// This only event we need to poll for right now is client.disconnect,
// if more events get added we will need more logic here
this.pollRef = setInterval(async () => {
const result = await this.isConnected();
if (result.connected) return;
this.ee.emit('client.disconnected');
}, 2000);
}
private stopPoll() {
if (this.pollRef) {
clearInterval(this.pollRef);
}
}
/**
* Requests permission for a website to communicate with the specified snaps
* and attempts to install them if they're not already installed.
* If the installation of any snap fails, returns the error that caused the failure.
* More informations here: https://docs.metamask.io/snaps/reference/rpc-api/#wallet_requestsnaps
*/
private async requestSnap(): Promise<{
[snapId: string]: {
blocked: boolean;
enabled: boolean;
id: string;
version: string;
};
}> {
return window.ethereum.request({
method: EthereumMethod.RequestSnaps,
params: {
[this.snapId]: {
version: this.version,
},
private async requestSnap() {
await this.request(EthereumMethod.RequestSnaps, {
[this.snapId]: {
version: this.version,
},
});
}
// TODO: check if this is needed, its used in use-snap-status
//
//
// /**
// * Gets the list of all installed snaps.
// * More information here: https://docs.metamask.io/snaps/reference/rpc-api/#wallet_getsnaps
// */
// async getSnap() {
// const snaps = await this.request(EthereumMethod.GetSnaps);
// return Object.values(snaps).find(
// (s) => s.id === this.snapId && s.version === this.version
// );
// }
/**
* Calls a method on the specified snap, always vega in this case
* should always be npm:@vegaprotocol/snap
*/
private async invokeSnap<TResult>(
method: JsonRpcMethod,
params: SnapInvocationParams = {}
): Promise<TResult | { error: SnapRPCError }> {
// MetaMask in Firefox doesn't like undefined properties or some properties
// on __proto__ so we need to strip them out with JSON.strinfify
params = JSON.parse(JSON.stringify(params));
return window.ethereum.request({
method: EthereumMethod.InvokeSnap,
params: {
snapId: this.snapId,
request: {
method,
params,
},
params?: SnapInvocationParams
): Promise<TResult> {
return await this.request(EthereumMethod.InvokeSnap, {
snapId: this.snapId,
request: {
method,
params,
},
});
}
private isSnapRPCError(obj: unknown): obj is SnapRPCError {
if (
obj !== undefined &&
obj !== null &&
typeof obj === 'object' &&
'code' in obj &&
'message' in obj
) {
return true;
/**
* Calls window.ethereum.request with method and params
*/
private async request<TResult>(
method: EthereumMethod,
params?: object
): Promise<TResult> {
if (window.ethereum?.request && window.ethereum?.isMetaMask) {
// MetaMask in Firefox doesn't like undefined properties or some properties
// on __proto__ so we need to strip them out with JSON.strinfify
try {
params = JSON.parse(JSON.stringify(params));
} catch (err) {
throw sendTransactionError();
}
return window.ethereum.request({
method,
params,
});
}
return false;
throw noWalletError();
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ export class ConnectorError extends Error {
export const ConnectorErrors = {
userRejected: { message: 'user rejected', code: 0 },
noConnector: { message: 'not connected', code: 1 },
noConnector: { message: 'no connector', code: 1 },
connect: { message: 'failed to connect', code: 2 },
disconnect: { message: 'failed to disconnect', code: 3 },
chainId: { message: 'incorrect chain id', code: 4 },
+2 -1
View File
@@ -93,6 +93,7 @@ describe('disconnect', () => {
expect(result).toEqual({ status: 'disconnected' });
expect(config.store.getState()).toMatchObject({
status: 'disconnected',
error: noConnectorError(),
current: undefined,
keys: [],
pubKey: undefined,
@@ -129,7 +130,7 @@ describe('refresh keys', () => {
it('handles invalid connector', async () => {
await config.refreshKeys();
expect(config.store.getState()).toMatchObject({
error: undefined,
error: noConnectorError(),
});
});
+7 -9
View File
@@ -132,20 +132,18 @@ export function createConfig(cfg: Config): Wallet {
store.setState(getInitialState(), true);
return { status: 'disconnected' as const };
} catch (err) {
store.setState(getInitialState(), true);
store.setState({
...getInitialState(),
error: err instanceof ConnectorError ? err : unknownError(),
});
return { status: 'disconnected' as const };
}
}
async function refreshKeys() {
const state = store.getState();
const connector = connectors.getState().find((x) => x.id === state.current);
// Only refresh keys if connnected. If you aren't connect when you connect
// you will get the latest keys
if (state.status !== 'connected') {
return;
}
const connector = connectors
.getState()
.find((x) => x.id === store.getState().current);
try {
if (!connector) {