From ae76e45ce8cb248bb763273da00a67c266b83013 Mon Sep 17 00:00:00 2001 From: Botond Date: Thu, 22 Dec 2022 12:17:39 +0000 Subject: [PATCH] chore: migrate to wallet client --- .../src/connectors/json-rpc-connector.ts | 208 +++++------------- package.json | 1 + yarn.lock | 13 +- 3 files changed, 66 insertions(+), 156 deletions(-) diff --git a/libs/wallet/src/connectors/json-rpc-connector.ts b/libs/wallet/src/connectors/json-rpc-connector.ts index 330b55972..dd687e0c6 100644 --- a/libs/wallet/src/connectors/json-rpc-connector.ts +++ b/libs/wallet/src/connectors/json-rpc-connector.ts @@ -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 - | z.infer - | z.infer - | z.infer - | { 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 { - 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); - } } diff --git a/package.json b/package.json index de4466f4f..20fa3297e 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index a8a36da10..d87d1bbf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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==