chore: migrate to wallet client

This commit is contained in:
Botond
2022-12-29 21:07:28 -08:00
committed by Matthew Russell
parent 955e233c46
commit ae76e45ce8
3 changed files with 66 additions and 156 deletions
+54 -154
View File
@@ -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);
}
}
+1
View File
@@ -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",
+11 -2
View File
@@ -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==