130 lines
4.3 KiB
TypeScript
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);
|
|
};
|