Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de21212e85 |
@@ -2,10 +2,12 @@ import {
|
|||||||
RestConnector,
|
RestConnector,
|
||||||
JsonRpcConnector,
|
JsonRpcConnector,
|
||||||
ViewConnector,
|
ViewConnector,
|
||||||
|
BrowserConnector,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
export const rest = new RestConnector();
|
export const rest = new RestConnector();
|
||||||
export const jsonRpc = new JsonRpcConnector();
|
export const jsonRpc = new JsonRpcConnector();
|
||||||
|
export const browser = new BrowserConnector();
|
||||||
|
|
||||||
let view: ViewConnector;
|
let view: ViewConnector;
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
@@ -19,4 +21,5 @@ export const Connectors = {
|
|||||||
rest,
|
rest,
|
||||||
jsonRpc,
|
jsonRpc,
|
||||||
view,
|
view,
|
||||||
|
browser,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import capitalize from 'lodash/capitalize';
|
||||||
|
import { createDocsLinks, t } from '@vegaprotocol/react-helpers';
|
||||||
|
import {
|
||||||
|
ButtonLink,
|
||||||
|
Diamond,
|
||||||
|
Link,
|
||||||
|
Loader,
|
||||||
|
Tick,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import type { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||||
|
import type { BrowserConnector } from '../connectors';
|
||||||
|
import { BrowserClientErrors } from '../connectors';
|
||||||
|
import { ConnectDialogTitle } from './connect-dialog-elements';
|
||||||
|
import { Status } from '../use-json-rpc-connect';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
|
|
||||||
|
export const ServiceErrors = {
|
||||||
|
NO_HEALTHY_NODE: 1000,
|
||||||
|
REQUEST_PROCESSING: -32000,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BrowserConnectorForm = ({
|
||||||
|
connector,
|
||||||
|
appChainId,
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
reset,
|
||||||
|
}: {
|
||||||
|
connector: BrowserConnector;
|
||||||
|
appChainId: string;
|
||||||
|
status: Status;
|
||||||
|
error: WalletClientError | null;
|
||||||
|
onConnect: () => void;
|
||||||
|
reset: () => void;
|
||||||
|
}) => {
|
||||||
|
if (status === Status.Idle) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Connecting
|
||||||
|
status={status}
|
||||||
|
error={error}
|
||||||
|
connector={connector}
|
||||||
|
appChainId={appChainId}
|
||||||
|
reset={reset}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Connecting = ({
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
connector,
|
||||||
|
appChainId,
|
||||||
|
reset,
|
||||||
|
}: {
|
||||||
|
status: Status;
|
||||||
|
error: WalletClientError | null;
|
||||||
|
connector: BrowserConnector;
|
||||||
|
appChainId: string;
|
||||||
|
reset: () => void;
|
||||||
|
}) => {
|
||||||
|
if (status === Status.Error) {
|
||||||
|
return <Error error={error} appChainId={appChainId} onTryAgain={reset} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === Status.CheckingVersion) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogTitle>{t('Checking wallet version')}</ConnectDialogTitle>
|
||||||
|
<Center>
|
||||||
|
<Loader />
|
||||||
|
</Center>
|
||||||
|
<p className="text-center">
|
||||||
|
{t('Checking your wallet is compatible with this app')}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === Status.GettingChainId) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogTitle>{t('Verifying chain')}</ConnectDialogTitle>
|
||||||
|
<Center>
|
||||||
|
<Loader />
|
||||||
|
</Center>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === Status.Connected) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogTitle>{t('Successfully connected')}</ConnectDialogTitle>
|
||||||
|
<Center>
|
||||||
|
<Tick />
|
||||||
|
</Center>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === Status.Connecting || status === Status.GettingPerms) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogTitle>{t('Connecting...')}</ConnectDialogTitle>
|
||||||
|
<Center>
|
||||||
|
<Diamond />
|
||||||
|
</Center>
|
||||||
|
<p className="text-center">
|
||||||
|
{t(
|
||||||
|
"Approve the connection from your Browser wallet app. If you have multiple wallets you'll need to choose which to connect with."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Center = ({ children }: { children: ReactNode }) => {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center my-6">{children}</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Error = ({
|
||||||
|
error,
|
||||||
|
appChainId,
|
||||||
|
onTryAgain,
|
||||||
|
}: {
|
||||||
|
error: WalletClientError | null;
|
||||||
|
appChainId: string;
|
||||||
|
onTryAgain: () => void;
|
||||||
|
}) => {
|
||||||
|
let title = t('Something went wrong');
|
||||||
|
let text: ReactNode | undefined = t('An unknown error occurred');
|
||||||
|
let tryAgain: ReactNode | null = (
|
||||||
|
<p className="text-center">
|
||||||
|
<ButtonLink onClick={onTryAgain}>{t('Try again')}</ButtonLink>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
const { VEGA_DOCS_URL } = useEnvironment();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error.code === BrowserClientErrors.NO_SERVICE.code) {
|
||||||
|
title = t('No wallet detected');
|
||||||
|
text = t(
|
||||||
|
'No Vega Wallet application running. Please install the vega wallet browser extension.'
|
||||||
|
);
|
||||||
|
} else if (error.code === BrowserClientErrors.WRONG_NETWORK.code) {
|
||||||
|
title = t('Wrong network');
|
||||||
|
text = t(
|
||||||
|
'To complete your wallet connection, set your wallet network in your app to "%s".',
|
||||||
|
appChainId
|
||||||
|
);
|
||||||
|
} else if (error.code === ServiceErrors.NO_HEALTHY_NODE) {
|
||||||
|
title = error.title;
|
||||||
|
text = (
|
||||||
|
<>
|
||||||
|
{capitalize(error.message)}
|
||||||
|
{'. '}
|
||||||
|
{VEGA_DOCS_URL && (
|
||||||
|
<Link
|
||||||
|
href={createDocsLinks(VEGA_DOCS_URL).VEGA_WALLET_CONCEPTS_URL}
|
||||||
|
>
|
||||||
|
{t('Read the docs to troubleshoot')}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else if (error.code === ServiceErrors.REQUEST_PROCESSING) {
|
||||||
|
title = t('Connection in progress');
|
||||||
|
text = t('Approve the connection from your Vega wallet app.');
|
||||||
|
tryAgain = null;
|
||||||
|
} else if (error.code === 0) {
|
||||||
|
title = t('Wrong network');
|
||||||
|
text = (
|
||||||
|
<>
|
||||||
|
{t(
|
||||||
|
`To complete your wallet connection, set your wallet network in your
|
||||||
|
app to %s.`,
|
||||||
|
appChainId
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else if (error.code === BrowserClientErrors.INVALID_WALLET.code) {
|
||||||
|
title = error.title;
|
||||||
|
const errorData = error.message?.split('\n ') || [];
|
||||||
|
text = (
|
||||||
|
<span className="flex flex-col">
|
||||||
|
{errorData.map((str, i) => (
|
||||||
|
<span key={i}>{str}</span>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
title = t(error.title);
|
||||||
|
text = t(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogTitle>{title}</ConnectDialogTitle>
|
||||||
|
<p className="text-center mb-2 first-letter:uppercase">{text}</p>
|
||||||
|
{tryAgain}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -13,9 +13,14 @@ import type { WalletClientError } from '@vegaprotocol/wallet-client';
|
|||||||
import { ExternalLinks, t, useChainIdQuery } from '@vegaprotocol/react-helpers';
|
import { ExternalLinks, t, useChainIdQuery } from '@vegaprotocol/react-helpers';
|
||||||
import type { VegaConnector } from '../connectors';
|
import type { VegaConnector } from '../connectors';
|
||||||
import { ViewConnector } from '../connectors';
|
import { ViewConnector } from '../connectors';
|
||||||
import { JsonRpcConnector, RestConnector } from '../connectors';
|
import {
|
||||||
|
JsonRpcConnector,
|
||||||
|
RestConnector,
|
||||||
|
BrowserConnector,
|
||||||
|
} from '../connectors';
|
||||||
import { RestConnectorForm } from './rest-connector-form';
|
import { RestConnectorForm } from './rest-connector-form';
|
||||||
import { JsonRpcConnectorForm } from './json-rpc-connector-form';
|
import { JsonRpcConnectorForm } from './json-rpc-connector-form';
|
||||||
|
import { BrowserConnectorForm } from './browser-connector-form';
|
||||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||||
import {
|
import {
|
||||||
ConnectDialogContent,
|
ConnectDialogContent,
|
||||||
@@ -24,11 +29,12 @@ import {
|
|||||||
} from './connect-dialog-elements';
|
} from './connect-dialog-elements';
|
||||||
import type { Status } from '../use-json-rpc-connect';
|
import type { Status } from '../use-json-rpc-connect';
|
||||||
import { useJsonRpcConnect } from '../use-json-rpc-connect';
|
import { useJsonRpcConnect } from '../use-json-rpc-connect';
|
||||||
|
import { useBrowserConnect } from '../use-browser-connect';
|
||||||
import { ViewConnectorForm } from './view-connector-form';
|
import { ViewConnectorForm } from './view-connector-form';
|
||||||
|
|
||||||
export const CLOSE_DELAY = 1700;
|
export const CLOSE_DELAY = 1700;
|
||||||
type Connectors = { [key: string]: VegaConnector };
|
type Connectors = { [key: string]: VegaConnector };
|
||||||
type WalletType = 'jsonRpc' | 'hosted' | 'view';
|
type WalletType = 'jsonRpc' | 'hosted' | 'view' | 'browser';
|
||||||
|
|
||||||
export interface VegaConnectDialogProps {
|
export interface VegaConnectDialogProps {
|
||||||
connectors: Connectors;
|
connectors: Connectors;
|
||||||
@@ -117,7 +123,7 @@ export const VegaConnectDialog = ({
|
|||||||
size="small"
|
size="small"
|
||||||
onChange={updateVegaWalletDialog}
|
onChange={updateVegaWalletDialog}
|
||||||
>
|
>
|
||||||
{renderContent()}
|
<div id="wallet-dialog-000">{renderContent()}</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -148,6 +154,8 @@ const ConnectDialogContainer = ({
|
|||||||
}, [closeDialog]);
|
}, [closeDialog]);
|
||||||
|
|
||||||
const { connect, ...jsonRpcState } = useJsonRpcConnect(delayedOnConnect);
|
const { connect, ...jsonRpcState } = useJsonRpcConnect(delayedOnConnect);
|
||||||
|
const { connect: connectBW, ...browserState } =
|
||||||
|
useBrowserConnect(delayedOnConnect);
|
||||||
|
|
||||||
const handleSelect = (type: WalletType, isHosted = false) => {
|
const handleSelect = (type: WalletType, isHosted = false) => {
|
||||||
let connector;
|
let connector;
|
||||||
@@ -174,6 +182,10 @@ const ConnectDialogContainer = ({
|
|||||||
if (connector instanceof JsonRpcConnector) {
|
if (connector instanceof JsonRpcConnector) {
|
||||||
connect(connector, appChainId);
|
connect(connector, appChainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connector instanceof BrowserConnector) {
|
||||||
|
connectBW(connector, appChainId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return selectedConnector !== undefined && walletType !== undefined ? (
|
return selectedConnector !== undefined && walletType !== undefined ? (
|
||||||
@@ -181,6 +193,7 @@ const ConnectDialogContainer = ({
|
|||||||
type={walletType}
|
type={walletType}
|
||||||
connector={selectedConnector}
|
connector={selectedConnector}
|
||||||
jsonRpcState={jsonRpcState}
|
jsonRpcState={jsonRpcState}
|
||||||
|
browserState={browserState}
|
||||||
onConnect={closeDialog}
|
onConnect={closeDialog}
|
||||||
appChainId={appChainId}
|
appChainId={appChainId}
|
||||||
reset={reset}
|
reset={reset}
|
||||||
@@ -212,6 +225,13 @@ const ConnectorList = ({
|
|||||||
<ConnectDialogTitle>{t('Connect')}</ConnectDialogTitle>
|
<ConnectDialogTitle>{t('Connect')}</ConnectDialogTitle>
|
||||||
<CustomUrlInput walletUrl={walletUrl} setWalletUrl={setWalletUrl} />
|
<CustomUrlInput walletUrl={walletUrl} setWalletUrl={setWalletUrl} />
|
||||||
<ul data-testid="connectors-list" className="mb-6">
|
<ul data-testid="connectors-list" className="mb-6">
|
||||||
|
<li className="mb-4 last:mb-0">
|
||||||
|
<ConnectionOption
|
||||||
|
type="browser"
|
||||||
|
text={t('Connect Browser wallet')}
|
||||||
|
onClick={() => onSelect('browser')}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
<li className="mb-4 last:mb-0">
|
<li className="mb-4 last:mb-0">
|
||||||
<ConnectionOption
|
<ConnectionOption
|
||||||
type="jsonRpc"
|
type="jsonRpc"
|
||||||
@@ -247,6 +267,7 @@ const SelectedForm = ({
|
|||||||
connector,
|
connector,
|
||||||
appChainId,
|
appChainId,
|
||||||
jsonRpcState,
|
jsonRpcState,
|
||||||
|
browserState,
|
||||||
reset,
|
reset,
|
||||||
onConnect,
|
onConnect,
|
||||||
}: {
|
}: {
|
||||||
@@ -257,6 +278,10 @@ const SelectedForm = ({
|
|||||||
status: Status;
|
status: Status;
|
||||||
error: WalletClientError | null;
|
error: WalletClientError | null;
|
||||||
};
|
};
|
||||||
|
browserState: {
|
||||||
|
status: Status;
|
||||||
|
error: WalletClientError | null;
|
||||||
|
};
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
onConnect: () => void;
|
onConnect: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -322,6 +347,24 @@ const SelectedForm = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connector instanceof BrowserConnector) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConnectDialogContent>
|
||||||
|
<BrowserConnectorForm
|
||||||
|
connector={connector}
|
||||||
|
status={browserState.status}
|
||||||
|
error={browserState.error}
|
||||||
|
onConnect={onConnect}
|
||||||
|
appChainId={appChainId}
|
||||||
|
reset={reset}
|
||||||
|
/>
|
||||||
|
</ConnectDialogContent>
|
||||||
|
<ConnectDialogFooter />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error('No connector selected');
|
throw new Error('No connector selected');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -334,6 +377,7 @@ const ConnectionOption = ({
|
|||||||
text: string;
|
text: string;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const id = type === 'browser' ? 'vega-wallet-connect' : undefined;
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
@@ -341,6 +385,7 @@ const ConnectionOption = ({
|
|||||||
fill={true}
|
fill={true}
|
||||||
variant={['hosted', 'view'].includes(type) ? 'default' : 'primary'}
|
variant={['hosted', 'view'].includes(type) ? 'default' : 'primary'}
|
||||||
data-testid={`connector-${type}`}
|
data-testid={`connector-${type}`}
|
||||||
|
id={id}
|
||||||
>
|
>
|
||||||
<span className="-mx-6 flex text-left justify-between items-center">
|
<span className="-mx-6 flex text-left justify-between items-center">
|
||||||
{text}
|
{text}
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import type { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||||
|
import { WalletClient } from '@vegaprotocol/wallet-client';
|
||||||
|
import { clearConfig, getConfig, setConfig } from '../storage';
|
||||||
|
import type { Transaction, VegaConnector } from './vega-connector';
|
||||||
|
import { WalletError } from './vega-connector';
|
||||||
|
|
||||||
|
export const BrowserClientErrors = {
|
||||||
|
NO_SERVICE: new WalletError(t('No service'), 100),
|
||||||
|
INVALID_WALLET: new WalletError(t('Wallet version invalid'), 103),
|
||||||
|
WRONG_NETWORK: new WalletError(
|
||||||
|
t('Wrong network'),
|
||||||
|
104,
|
||||||
|
t('App is configured to work with a different chain')
|
||||||
|
),
|
||||||
|
UNKNOWN: new WalletError(
|
||||||
|
t('Something went wrong'),
|
||||||
|
105,
|
||||||
|
t('Unknown error occurred')
|
||||||
|
),
|
||||||
|
NO_CLIENT: new WalletError(t('No client found.'), 106),
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export class BrowserConnector implements VegaConnector {
|
||||||
|
url: null;
|
||||||
|
reqId = 0;
|
||||||
|
client?: WalletClient;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.url = null;
|
||||||
|
const cfg = getConfig();
|
||||||
|
|
||||||
|
if (cfg && cfg.connector === 'browser') {
|
||||||
|
this.initialize();
|
||||||
|
this.connectWallet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
if (!this.client) {
|
||||||
|
try {
|
||||||
|
this.client = new WalletClient({
|
||||||
|
type: 'browser',
|
||||||
|
firefoxId: '62739efdd16a15a5ff4527bcd08fe6302b18b752@temporary-addon',
|
||||||
|
chromeId: 'pebgkinfegfpnkamklihgpeolleghngl',
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
throw BrowserClientErrors.NO_SERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChainId() {
|
||||||
|
if (!this.client) {
|
||||||
|
throw BrowserClientErrors.NO_CLIENT;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return await this.client.GetChainId();
|
||||||
|
} catch (err) {
|
||||||
|
const {
|
||||||
|
code = BrowserClientErrors.UNKNOWN.code,
|
||||||
|
message = BrowserClientErrors.UNKNOWN.message,
|
||||||
|
title,
|
||||||
|
} = err as WalletClientError;
|
||||||
|
throw new WalletError(title, code, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async connectWallet() {
|
||||||
|
if (!this.client) {
|
||||||
|
throw BrowserClientErrors.NO_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.client.ConnectWallet();
|
||||||
|
return null;
|
||||||
|
} catch (err) {
|
||||||
|
const {
|
||||||
|
code = BrowserClientErrors.UNKNOWN.code,
|
||||||
|
message = BrowserClientErrors.UNKNOWN.message,
|
||||||
|
title,
|
||||||
|
} = err as WalletClientError;
|
||||||
|
throw new WalletError(title, code, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect actually calling list_keys here, not to be confused with connect_wallet
|
||||||
|
// which retrieves the session token
|
||||||
|
async connect() {
|
||||||
|
if (!this.client) {
|
||||||
|
throw BrowserClientErrors.NO_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await this.client.ListKeys();
|
||||||
|
return result.keys;
|
||||||
|
} catch (err) {
|
||||||
|
const {
|
||||||
|
code = BrowserClientErrors.UNKNOWN.code,
|
||||||
|
message = BrowserClientErrors.UNKNOWN.message,
|
||||||
|
title,
|
||||||
|
} = err as WalletClientError;
|
||||||
|
throw new WalletError(title, code, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async disconnect() {
|
||||||
|
if (!this.client) {
|
||||||
|
throw BrowserClientErrors.NO_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.client.DisconnectWallet();
|
||||||
|
clearConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendTx(pubKey: string, transaction: Transaction) {
|
||||||
|
if (!this.client) {
|
||||||
|
throw BrowserClientErrors.NO_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await this.client.SendTransaction({
|
||||||
|
publicKey: pubKey,
|
||||||
|
sendingMode: 'TYPE_SYNC',
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
transactionHash: result.transactionHash,
|
||||||
|
sentAt: result.sentAt,
|
||||||
|
receivedAt: result.receivedAt,
|
||||||
|
signature: result.transaction.signature.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkCompat() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@ export * from './rest-connector';
|
|||||||
export * from './injected-connector';
|
export * from './injected-connector';
|
||||||
export * from './json-rpc-connector';
|
export * from './json-rpc-connector';
|
||||||
export * from './view-connector';
|
export * from './view-connector';
|
||||||
|
export * from './browser-connector';
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export class JsonRpcConnector implements VegaConnector {
|
|||||||
if (cfg && cfg.url) {
|
if (cfg && cfg.url) {
|
||||||
this.url = cfg.url;
|
this.url = cfg.url;
|
||||||
this.client = new WalletClient({
|
this.client = new WalletClient({
|
||||||
|
type: 'http',
|
||||||
address: cfg.url,
|
address: cfg.url,
|
||||||
token: cfg.token ?? undefined,
|
token: cfg.token ?? undefined,
|
||||||
onTokenChange: (token) => {
|
onTokenChange: (token) => {
|
||||||
@@ -53,6 +54,7 @@ export class JsonRpcConnector implements VegaConnector {
|
|||||||
set url(url: string) {
|
set url(url: string) {
|
||||||
this._url = url;
|
this._url = url;
|
||||||
this.client = new WalletClient({
|
this.client = new WalletClient({
|
||||||
|
type: 'http',
|
||||||
address: url,
|
address: url,
|
||||||
token: this.token ?? undefined,
|
token: this.token ?? undefined,
|
||||||
onTokenChange: (token) =>
|
onTokenChange: (token) =>
|
||||||
@@ -71,8 +73,7 @@ export class JsonRpcConnector implements VegaConnector {
|
|||||||
throw ClientErrors.NO_CLIENT;
|
throw ClientErrors.NO_CLIENT;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const { result } = await this.client.GetChainId();
|
return await this.client.GetChainId();
|
||||||
return result;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const {
|
const {
|
||||||
code = ClientErrors.UNKNOWN.code,
|
code = ClientErrors.UNKNOWN.code,
|
||||||
@@ -109,7 +110,7 @@ export class JsonRpcConnector implements VegaConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { result } = await this.client.ListKeys();
|
const result = await this.client.ListKeys();
|
||||||
return result.keys;
|
return result.keys;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const {
|
const {
|
||||||
@@ -135,7 +136,7 @@ export class JsonRpcConnector implements VegaConnector {
|
|||||||
throw ClientErrors.NO_CLIENT;
|
throw ClientErrors.NO_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { result } = await this.client.SendTransaction({
|
const result = await this.client.SendTransaction({
|
||||||
publicKey: pubKey,
|
publicKey: pubKey,
|
||||||
sendingMode: 'TYPE_SYNC',
|
sendingMode: 'TYPE_SYNC',
|
||||||
transaction,
|
transaction,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { LocalStorage } from '@vegaprotocol/react-helpers';
|
|||||||
|
|
||||||
interface ConnectorConfig {
|
interface ConnectorConfig {
|
||||||
token: string | null;
|
token: string | null;
|
||||||
connector: 'rest' | 'jsonRpc' | 'view';
|
connector: 'rest' | 'jsonRpc' | 'view' | 'browser';
|
||||||
url: string | null;
|
url: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||||
|
import type { BrowserConnector } from './connectors';
|
||||||
|
import { ClientErrors } from './connectors';
|
||||||
|
import { useVegaWallet } from './use-vega-wallet';
|
||||||
|
|
||||||
|
export enum Status {
|
||||||
|
Idle = 'Idle',
|
||||||
|
CheckingVersion = 'CheckingVersion',
|
||||||
|
GettingChainId = 'GettingChainId',
|
||||||
|
Connecting = 'Connecting',
|
||||||
|
GettingPerms = 'GettingPerms',
|
||||||
|
ListingKeys = 'ListingKeys',
|
||||||
|
Connected = 'Connected',
|
||||||
|
Error = 'Error',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useBrowserConnect = (onConnect: () => void) => {
|
||||||
|
const { connect } = useVegaWallet();
|
||||||
|
const [status, setStatus] = useState(Status.Idle);
|
||||||
|
const [error, setError] = useState<WalletClientError | null>(null);
|
||||||
|
|
||||||
|
const attemptConnect = useCallback(
|
||||||
|
async (connector: BrowserConnector, appChainId: string) => {
|
||||||
|
try {
|
||||||
|
connector.initialize();
|
||||||
|
// Check that the running wallet is compatible with this connector
|
||||||
|
setStatus(Status.CheckingVersion);
|
||||||
|
await connector.checkCompat();
|
||||||
|
|
||||||
|
// Check if wallet is configured for the same chain as the app
|
||||||
|
setStatus(Status.GettingChainId);
|
||||||
|
|
||||||
|
// Dont throw in when cypress is running as trading app relies on
|
||||||
|
// mocks which result in a mismatch between chainId for app and
|
||||||
|
// chainId for wallet
|
||||||
|
if (!('Cypress' in window)) {
|
||||||
|
const chainIdResult = await connector.getChainId();
|
||||||
|
console.log('CHAIN RES: ', chainIdResult);
|
||||||
|
if (chainIdResult.chainID !== appChainId) {
|
||||||
|
// Throw wallet error for consitent error handling
|
||||||
|
throw ClientErrors.WRONG_NETWORK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start connection flow. User will be prompted to select a wallet and enter
|
||||||
|
// its password in the wallet application, promise will resolve once successful
|
||||||
|
// or it will throw
|
||||||
|
setStatus(Status.Connecting);
|
||||||
|
await connector.connectWallet();
|
||||||
|
|
||||||
|
setStatus(Status.GettingPerms);
|
||||||
|
|
||||||
|
// Call connect in the wallet provider. The connector will be stored for
|
||||||
|
// future actions such as sending transactions
|
||||||
|
await connect(connector);
|
||||||
|
|
||||||
|
setStatus(Status.Connected);
|
||||||
|
onConnect();
|
||||||
|
} catch (err) {
|
||||||
|
console.log('ERROR!!!!!', err);
|
||||||
|
if (err instanceof WalletClientError) {
|
||||||
|
setError(err);
|
||||||
|
}
|
||||||
|
setStatus(Status.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onConnect, connect]
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
status,
|
||||||
|
error,
|
||||||
|
connect: attemptConnect,
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user