vega-frontend-monorepo/libs/cypress/src/lib/eip1193-bridge.ts
2023-07-31 17:08:55 +01:00

130 lines
4.3 KiB
TypeScript

import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge';
import { JsonRpcProvider } from '@ethersproject/providers';
import { Wallet } from '@ethersproject/wallet';
import { ethers } from 'ethers';
// Address of the above key
export class CustomizedBridge extends Eip1193Bridge {
chainId = Cypress.env('ETHEREUM_CHAIN_ID');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async sendAsync(...args: any) {
// eslint-disable-next-line no-console
console.debug('sendAsync called', ...args);
return this.send(...args);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
override async send(...args: any) {
// eslint-disable-next-line no-console
console.debug('send called', ...args);
const isCallbackForm =
typeof args[0] === 'object' && typeof args[1] === 'function';
let callback;
let method;
let params;
if (isCallbackForm) {
callback = args[1];
method = args[0].method;
params = args[0].params;
} else {
method = args[0];
params = args[1];
}
try {
// Mock out request accounts and chainId
if (method === 'eth_requestAccounts' || method === 'eth_accounts') {
const address = this.signer ? [await this.signer.getAddress()] : [];
if (isCallbackForm) {
callback({ result: address });
} else {
return Promise.resolve(address);
}
}
if (method === 'eth_chainId') {
if (isCallbackForm) {
callback(null, { result: '0x3' });
} else {
return Promise.resolve('0x3');
}
}
// Hacky, https://github.com/ethers-io/ethers.js/issues/1683#issuecomment-1016227588
// If from is present on eth_call it errors, removing it makes the library set
// from as the connected wallet which works fine
if (params && params.length && params[0].from && method === 'eth_call') {
delete params[0].from;
}
let result;
// For sending a transaction if we call send it will error
// as it wants gasLimit in sendTransaction but hexlify sets the property gas
// to gasLimit which makes sensd transaction error.
// This has taken the code from the super method for sendTransaction and altered
// it slightly to make it work with the gas limit issues.
if (
params &&
params.length &&
params[0].from &&
method === 'eth_sendTransaction'
) {
// Hexlify will not take gas, must be gasLimit, set this property to be gasLimit
params[0].gasLimit = params[0].gas;
delete params[0].gas;
// If from is present on eth_sendTransaction it errors, removing it makes the library set
// from as the connected wallet which works fine
delete params[0].from;
const req = ethers.providers.JsonRpcProvider.hexlifyTransaction(
params[0]
);
// Hexlify sets the gasLimit property to be gas again and send transaction requires gasLimit
req['gasLimit'] = req['gas'];
delete req['gas'];
if (!this.signer) {
throw new Error('No signer');
}
// Send the transaction
const tx = await this.signer.sendTransaction(req);
result = tx.hash;
} else {
// All other transactions the base class works for
result = await super.send(method, params);
}
// eslint-disable-next-line no-console
console.debug('result received', method, params, result);
if (isCallbackForm) {
callback(null, { result });
} else {
return result;
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
if (isCallbackForm) {
callback(error, null);
} else {
throw error;
}
}
}
}
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
const getProvider = () => {
const url = Cypress.env('ETHEREUM_PROVIDER_URL');
const chainId = Cypress.env('ETHEREUM_CHAIN_ID');
return new JsonRpcProvider(url, chainId);
};
export const createBridge = () => {
const provider = getProvider();
const privateKey = Wallet.fromMnemonic(
Cypress.env('ETH_WALLET_MNEMONIC'),
getAccount(0)
).privateKey;
const signer = new Wallet(privateKey, provider);
return new CustomizedBridge(signer, provider);
};