chore: migrate to wallet client
This commit is contained in:
@@ -1,74 +1,11 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { z } from 'zod';
|
||||
import { WalletClient } from '@vegaprotocol/wallet-client';
|
||||
import { clearConfig, getConfig, setConfig } from '../storage';
|
||||
import { encodeTransaction } from '../utils';
|
||||
import type { Transaction, VegaConnector } from './vega-connector';
|
||||
import { WalletError } from './vega-connector';
|
||||
|
||||
const VERSION = 'v2';
|
||||
|
||||
enum Methods {
|
||||
ConnectWallet = 'client.connect_wallet',
|
||||
DisconnectWallet = 'client.disconnect_wallet',
|
||||
ListKeys = 'client.list_keys',
|
||||
SendTransaction = 'client.send_transaction',
|
||||
GetChainId = 'client.get_chain_id',
|
||||
}
|
||||
|
||||
const BaseSchema = z.object({
|
||||
id: z.string(),
|
||||
jsonrpc: z.literal('2.0'),
|
||||
});
|
||||
|
||||
const ConnectWalletSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
token: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const ListKeysSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
keys: z.array(
|
||||
z.object({
|
||||
publicKey: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const GetChainIdSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
chainID: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const SendTransactionSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
receivedAt: z.string(),
|
||||
sentAt: z.string(),
|
||||
transactionHash: z.string(),
|
||||
transaction: z.object({
|
||||
signature: z.object({
|
||||
value: z.string(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
type JsonRpcError = {
|
||||
message: string;
|
||||
code: number;
|
||||
data?: string;
|
||||
};
|
||||
|
||||
type Response =
|
||||
| z.infer<typeof ConnectWalletSchema>
|
||||
| z.infer<typeof ListKeysSchema>
|
||||
| z.infer<typeof GetChainIdSchema>
|
||||
| z.infer<typeof SendTransactionSchema>
|
||||
| { error: JsonRpcError };
|
||||
|
||||
export const ClientErrors = {
|
||||
NO_SERVICE: new WalletError(t('No service'), 100),
|
||||
NO_TOKEN: new WalletError(t('No token'), 101),
|
||||
@@ -91,46 +28,51 @@ export class JsonRpcConnector implements VegaConnector {
|
||||
url: string | null = null;
|
||||
token: string | null = null;
|
||||
reqId = 0;
|
||||
client?: WalletClient;
|
||||
|
||||
constructor() {
|
||||
const cfg = getConfig();
|
||||
if (cfg) {
|
||||
|
||||
if (cfg && cfg.url) {
|
||||
this.token = cfg.token;
|
||||
this.url = cfg.url;
|
||||
this.client = new WalletClient({
|
||||
hostname: cfg.url,
|
||||
token: cfg.token ?? undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async getChainId() {
|
||||
const result = await this.request(Methods.GetChainId);
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
if (!this.client) {
|
||||
throw new Error(
|
||||
'No client found. The connector needs to be initialized with a url.'
|
||||
);
|
||||
}
|
||||
const parseResult = GetChainIdSchema.safeParse(result);
|
||||
if (parseResult.success) {
|
||||
return parseResult.data.result;
|
||||
} else {
|
||||
try {
|
||||
const { result } = await this.client.GetChainId();
|
||||
return result;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
async connectWallet() {
|
||||
const result = await this.request(Methods.ConnectWallet, {
|
||||
hostname: window.location.host,
|
||||
});
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
if (!this.client) {
|
||||
throw new Error(
|
||||
'No client found. The connector needs to be initialized with a url.'
|
||||
);
|
||||
}
|
||||
const parseResult = ConnectWalletSchema.safeParse(result);
|
||||
|
||||
if (parseResult.success) {
|
||||
// store token and other config for eager connect and subsequent requests
|
||||
try {
|
||||
const { result } = await this.client.ConnectWallet();
|
||||
setConfig({
|
||||
token: parseResult.data.result.token,
|
||||
token: result.token,
|
||||
connector: 'jsonRpc',
|
||||
url: this.url,
|
||||
});
|
||||
return parseResult.data.result;
|
||||
} else {
|
||||
return result;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
@@ -138,69 +80,52 @@ export class JsonRpcConnector implements VegaConnector {
|
||||
// connect actually calling list_keys here, not to be confused with connect_wallet
|
||||
// which retrieves the session token
|
||||
async connect() {
|
||||
const cfg = getConfig();
|
||||
if (!cfg?.token) {
|
||||
throw ClientErrors.NO_TOKEN;
|
||||
if (!this.client) {
|
||||
throw new Error(
|
||||
'No client found. The connector needs to be initialized with a url.'
|
||||
);
|
||||
}
|
||||
const result = await this.request(Methods.ListKeys, {
|
||||
token: cfg.token,
|
||||
});
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
}
|
||||
const parseResult = ListKeysSchema.safeParse(result);
|
||||
if (parseResult.success) {
|
||||
return parseResult.data.result.keys;
|
||||
} else {
|
||||
|
||||
try {
|
||||
const { result } = await this.client.ListKeys({});
|
||||
return result.keys;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
const cfg = getConfig();
|
||||
|
||||
if (cfg?.token) {
|
||||
await this.request(Methods.DisconnectWallet, {
|
||||
token: cfg.token,
|
||||
});
|
||||
if (!this.client) {
|
||||
throw new Error(
|
||||
'No client found. The connector needs to be initialized with a url.'
|
||||
);
|
||||
}
|
||||
|
||||
await this.client.DisconnectWallet({});
|
||||
clearConfig();
|
||||
}
|
||||
|
||||
async sendTx(pubKey: string, transaction: Transaction) {
|
||||
const cfg = getConfig();
|
||||
if (!cfg?.token) {
|
||||
throw ClientErrors.NO_TOKEN;
|
||||
if (!this.client) {
|
||||
throw new Error(
|
||||
'No client found. The connector needs to be initialized with a url.'
|
||||
);
|
||||
}
|
||||
|
||||
const result = await this.request(Methods.SendTransaction, {
|
||||
token: cfg.token,
|
||||
publicKey: pubKey,
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
encodedTransaction: encodeTransaction(transaction),
|
||||
});
|
||||
try {
|
||||
const { result } = await this.client.SendTransaction({
|
||||
publicKey: pubKey,
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
transaction,
|
||||
});
|
||||
|
||||
if ('error' in result) {
|
||||
// In the case of sending a tx, error code 3001 indicates that the
|
||||
// user rejected the tx. Returning null will allow the dialog to close immediately
|
||||
if (result.error.code === 3001) {
|
||||
return null;
|
||||
} else {
|
||||
throw this.wrapError(result.error);
|
||||
}
|
||||
}
|
||||
|
||||
const parsedResult = SendTransactionSchema.safeParse(result);
|
||||
|
||||
if (parsedResult.success) {
|
||||
return {
|
||||
transactionHash: parsedResult.data.result.transactionHash,
|
||||
sentAt: parsedResult.data.result.sentAt,
|
||||
receivedAt: parsedResult.data.result.receivedAt,
|
||||
signature: parsedResult.data.result.transaction.signature.value,
|
||||
transactionHash: result.transactionHash,
|
||||
sentAt: result.sentAt,
|
||||
receivedAt: result.receivedAt,
|
||||
signature: result.transaction.signature.value,
|
||||
};
|
||||
} else {
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
@@ -224,29 +149,4 @@ export class JsonRpcConnector implements VegaConnector {
|
||||
throw ClientErrors.NO_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
private async request(method: Methods, params?: object): Promise<Response> {
|
||||
try {
|
||||
const result = await fetch(`${this.url}/api/${this.version}/requests`, {
|
||||
method: 'post',
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params,
|
||||
id: `${this.reqId++}`,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const json = await result.json();
|
||||
return json;
|
||||
} catch (err) {
|
||||
throw ClientErrors.NO_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
private wrapError(error: JsonRpcError) {
|
||||
return new WalletError(error.message, error.code, error.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"@sentry/nextjs": "^6.19.3",
|
||||
"@sentry/react": "^6.19.2",
|
||||
"@sentry/tracing": "^6.19.2",
|
||||
"@vegaprotocol/wallet-client": "^0.1.0",
|
||||
"@walletconnect/ethereum-provider": "^1.7.5",
|
||||
"@web3-react/core": "8.0.20-beta.0",
|
||||
"@web3-react/metamask": "8.0.16-beta.0",
|
||||
|
||||
@@ -7559,6 +7559,15 @@
|
||||
"@typescript-eslint/types" "5.40.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vegaprotocol/wallet-client@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-client/-/wallet-client-0.1.0.tgz#ef325eef83d064c2d536c8867735fe0cbf0b9b44"
|
||||
integrity sha512-0lM1UG3PL2QYIth6x4yAD810lGS9EbQA19cubBfn/csOZQGBs5EtNODqmBHZ544hKAJe98eChbqJwOF7qoExQA==
|
||||
dependencies:
|
||||
express "4.18.2"
|
||||
nanoid "3.3.4"
|
||||
node-fetch "2.6.7"
|
||||
|
||||
"@walletconnect/browser-utils@^1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951"
|
||||
@@ -12798,7 +12807,7 @@ expect@^29.0.0:
|
||||
jest-message-util "^29.1.2"
|
||||
jest-util "^29.1.2"
|
||||
|
||||
express@^4.17.1, express@^4.17.3:
|
||||
express@4.18.2, express@^4.17.1, express@^4.17.3:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
@@ -17333,7 +17342,7 @@ nan@^2.12.1:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
|
||||
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
|
||||
|
||||
nanoid@^3.3.1, nanoid@^3.3.4:
|
||||
nanoid@3.3.4, nanoid@^3.3.1, nanoid@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||
|
||||
Reference in New Issue
Block a user