diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 27330ce41..e3582998a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,6 +42,10 @@ jobs: if: matrix.project == 'eth-providers' run: yarn workspace @acala-network/eth-rpc-adapter run start:coverage + - name: generate typechain for eth-rpc-adapter tests + if: matrix.project == 'eth-rpc-adapter' + run: yarn workspace @acala-network/eth-rpc-adapter run typegen + - name: run tests run: yarn workspace @acala-network/${{ matrix.project }} run test:coverage diff --git a/.gitignore b/.gitignore index 88d80723e..fe1379dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,7 @@ lib **/.yarn/install-state.gz ## openzeppelin cache -**/.openzeppelin/ \ No newline at end of file +**/.openzeppelin/ + +## typechain files +**/types diff --git a/codecov.yml b/codecov.yml index d8a67846f..4fddbfe15 100644 --- a/codecov.yml +++ b/codecov.yml @@ -13,7 +13,7 @@ coverage: comment: layout: "reach, diff, flags, files" - behavior: default + behavior: new require_changes: false require_base: false require_head: false diff --git a/e2e-tests/e2e-hardhat/test/upgradeable-greeter.ts b/e2e-tests/e2e-hardhat/test/upgradeable-greeter.test.ts similarity index 100% rename from e2e-tests/e2e-hardhat/test/upgradeable-greeter.ts rename to e2e-tests/e2e-hardhat/test/upgradeable-greeter.test.ts diff --git a/packages/eth-rpc-adapter/package.json b/packages/eth-rpc-adapter/package.json index cb3af050a..7a5a4d99c 100644 --- a/packages/eth-rpc-adapter/package.json +++ b/packages/eth-rpc-adapter/package.json @@ -7,6 +7,7 @@ "scripts": { "build": "tsc", "ncc:pack": "ncc build src/index.ts -t --target es2020", + "typegen": "typechain --target=ethers-v5 --out-dir=./src/__tests__/types src/__tests__/abis/*.json", "dev": "ts-node-dev -T -r tsconfig-paths/register src/index.ts -l | pino-pretty --singleLine --colorize --ignore time,hostname,jsonrpc,dd", "clean": "rm -rf tsconfig.tsbuildinfo .nyc_output coverage/ lib/", "health-check": "./scripts/health-check.sh", @@ -47,6 +48,7 @@ "pm2": "^5.4.2", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", + "typechain": "^8.3.2", "vitest": "^2.1.1" }, "files": [ diff --git a/packages/eth-rpc-adapter/src/__tests__/abis/IERC20.json b/packages/eth-rpc-adapter/src/__tests__/abis/IERC20.json new file mode 100644 index 000000000..b3dca0b70 --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/abis/IERC20.json @@ -0,0 +1,260 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/interfaces/IERC20.sol\":\"IERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0x61db17aebc5d812c7002d15c1da954065e56abe49d64b14c034abe5604d70eb3\",\"urls\":[\"bzz-raw://b006685e753f9120469f10b09c159f222d4cb8b507a6c1f0c14ed50c883ebe66\",\"dweb:/ipfs/QmSyY7iTugbczPwfGK67etiyPULenYGzzRYbt8aabwwkUb\"]}},\"version\":1}", + "bytecode": "" +} diff --git a/packages/eth-rpc-adapter/src/__tests__/endpoint.test.ts b/packages/eth-rpc-adapter/src/__tests__/endpoint.test.ts index 93ced210b..d28957e5f 100644 --- a/packages/eth-rpc-adapter/src/__tests__/endpoint.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/endpoint.test.ts @@ -67,9 +67,7 @@ import { toDeterministic, waitForHeight, eth_estimateGas, -} from './utils'; -import { ADDRESS_ALICE, DETERMINISTIC_SETUP_DEX_ADDRESS, GAS_MONSTER_GAS_REQUIRED, @@ -81,8 +79,8 @@ import { deployHelloWorldData, evmAccounts, log22_0, - log22_1, -} from './consts'; + log22_1 } from './utils'; + const subql = new SubqlProvider(SUBQL_URL); diff --git a/packages/eth-rpc-adapter/src/__tests__/errors.test.ts b/packages/eth-rpc-adapter/src/__tests__/errors.test.ts index 396577d6c..3253fe33a 100644 --- a/packages/eth-rpc-adapter/src/__tests__/errors.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/errors.test.ts @@ -7,8 +7,7 @@ import ADDRESS from '@acala-network/contracts/utils/MandalaAddress'; import TokenABI from '@acala-network/contracts/build/contracts/Token.json'; import axios from 'axios'; -import { RPC_URL, eth_call, eth_chainId, eth_estimateGas, eth_getEthGas, eth_sendRawTransaction } from './utils'; -import { evmAccounts } from './consts'; +import { RPC_URL, eth_call, eth_chainId, eth_estimateGas, eth_getEthGas, eth_sendRawTransaction , evmAccounts } from './utils'; describe('errors', () => { const POOR_ACCOUNT = '0xa872f6cbd25a0e04a08b1e21098017a9e6194d101d75e13111f71410c59cd570'; diff --git a/packages/eth-rpc-adapter/src/__tests__/signer.test.ts b/packages/eth-rpc-adapter/src/__tests__/signer.test.ts index 60daa31cf..9136f65ce 100644 --- a/packages/eth-rpc-adapter/src/__tests__/signer.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/signer.test.ts @@ -1,10 +1,8 @@ -import { Eip1193Bridge } from '../eip1193-bridge'; import { EvmRpcProvider } from '@acala-network/eth-providers'; import { Wallet, verifyMessage } from '@ethersproject/wallet'; import { afterAll, describe, expect, it } from 'vitest'; -import dotenv from 'dotenv'; -dotenv.config(); +import { Eip1193Bridge } from '../eip1193-bridge'; const endpoint = process.env.ENDPOINT_URL || 'ws://127.0.0.1:9944'; diff --git a/packages/eth-rpc-adapter/src/__tests__/subscription.test.ts b/packages/eth-rpc-adapter/src/__tests__/subscription.test.ts new file mode 100644 index 000000000..7b7b07d57 --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/subscription.test.ts @@ -0,0 +1,162 @@ +import { ACA } from '@acala-network/contracts/utils/AcalaAddress'; +import { AcalaJsonRpcProvider, sleep } from '@acala-network/eth-providers'; +import { JsonRpcProvider } from '@ethersproject/providers'; +import { Wallet } from 'ethers'; +import { afterAll, beforeAll, beforeEach, describe, it } from 'vitest'; +import { expect } from 'chai'; +import { parseUnits } from 'ethers/lib/utils'; + +import { IERC20, IERC20__factory } from './types'; +import { SubsManager, evmAccounts, getAddrSelector } from './utils'; + +const oneAcaErc20 = parseUnits('1', 12); +const TRANSFER_SELECTOR = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; + +const ETH_RPC_URL = process.env.ENDPOINT_URL || 'http://localhost:8545'; +const ETH_RPC_URL_WS = ETH_RPC_URL.replace('http', 'ws'); + +describe('eth subscription', () => { + let deployer: Wallet; + let user: Wallet; + let provider: JsonRpcProvider; + let aca: IERC20; + + let subId0: string; + let subId1: string; + let subId2: string; + let subId3: string; + let sm: SubsManager; + + beforeAll(async () => { + console.log('setting up subscription ...'); + + provider = new AcalaJsonRpcProvider(ETH_RPC_URL); + deployer = new Wallet(evmAccounts[0].privateKey, provider); + user = new Wallet(evmAccounts[1].privateKey, provider); + aca = IERC20__factory.connect(ACA, deployer); + + sm = new SubsManager(ETH_RPC_URL_WS); + await sm.isReady; + + const userAddrSelector = getAddrSelector(user.address); + + const sub0 = sm.subscribeNewHeads(); + const sub1 = sm.subscribeLogs({}); + const sub2 = sm.subscribeLogs({ + topics: [ + TRANSFER_SELECTOR, + null, + [userAddrSelector], + ], + }); + const sub3 = sm.subscribeLogs({ + topics: [ + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55aaaaaaaaaaa', // shouldn't match + ], + }); + + ([subId0, subId1, subId2, subId3] = await Promise.all([sub0, sub1, sub2, sub3])); + + console.log('subscription finished!'); + }); + + beforeEach(() => { + sm.clear(); + }); + + afterAll(() => { + sm.close(); + }); + + it('get correct subscrption notification', async () => { + const receipt = await (await aca.transfer(user.address, oneAcaErc20.mul(8))).wait(); + const txBlockInfo = await provider.send('eth_getBlockByNumber', [receipt.blockNumber, false]); + + const msg0 = await sm.waitForMsg(subId0, data => data.hash === receipt.blockHash); // new block + const msg1 = await sm.waitForMsg(subId1); // ACA transfer + const msg2 = await sm.waitForMsg(subId2); // ACA transfer + const msg3 = await sm.waitForMsg(subId3); // no match + + expect(msg0).to.not.be.undefined; + expect(msg1).to.not.be.undefined; + expect(msg2).to.not.be.undefined; + expect(msg3).to.be.null; + + expect(msg0).to.deep.contains({ + jsonrpc: '2.0', + method: 'eth_subscription', + params: { + subscription: subId0, + result: txBlockInfo, + }, + }); + + const expectedLog = await provider.send('eth_getLogs', [{ blockHash: receipt.blockHash }]); + + expect(expectedLog.length).to.equal(1); + delete (expectedLog[0] as any).removed; + + expect(msg1).to.deep.contains({ + jsonrpc: '2.0', + method: 'eth_subscription', + params: { + subscription: subId1, + result: expectedLog[0], + }, + }); + + expect(msg2).to.deep.contains({ + jsonrpc: '2.0', + method: 'eth_subscription', + params: { + subscription: subId2, + result: expectedLog[0], + }, + }); + + }); + + it('unsubscribe works', async () => { + const unsubRes = await Promise.all([ + sm.unSubscribe(subId0), + sm.unSubscribe(subId1), + sm.unSubscribe(subId3), + sm.unSubscribe(Wallet.createRandom().address), + ]); + + expect(unsubRes).to.deep.equal([ + true, + true, + true, + false, + ]); + + // only sub2 is left + const receipt = await (await aca.transfer(user.address, oneAcaErc20.mul(3))).wait(); + const txBlockInfo = await provider.send('eth_getBlockByNumber', [receipt.blockNumber, false]); + + const msg0 = await sm.waitForMsg(subId0, data => data.hash === receipt.blockHash); // new block + const msg1 = await sm.waitForMsg(subId1); // ACA transfer + const msg2 = await sm.waitForMsg(subId2); // ACA transfer + const msg3 = await sm.waitForMsg(subId3); // no match + + // after unsubscribe they should not be notified anymore + expect(msg0).to.be.null; + expect(msg1).to.be.null; + expect(msg3).to.be.null; + + const expectedLog = await provider.send('eth_getLogs', [{ blockHash: txBlockInfo.hash }]); + + expect(expectedLog.length).to.equal(1); + delete (expectedLog[0] as any).removed; + + expect(msg2).to.deep.contains({ + jsonrpc: '2.0', + method: 'eth_subscription', + params: { + subscription: subId2, + result: expectedLog[0], + }, + }); + }); +}); diff --git a/packages/eth-rpc-adapter/src/__tests__/utils/SubsManager.ts b/packages/eth-rpc-adapter/src/__tests__/utils/SubsManager.ts new file mode 100644 index 000000000..538a3e08d --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/utils/SubsManager.ts @@ -0,0 +1,106 @@ +import { hexZeroPad } from 'ethers/lib/utils'; +import WebSocket from 'ws'; + +export class SubsManager { + curReqId = 0; + msgs: any[] = []; + ws: WebSocket; + isReady: Promise; + + constructor(url: string) { + this.ws = new WebSocket(url); + + this.isReady = new Promise(resolve => { + this.ws.on('open', () => { + this.ws.on('message', data => { + const parsedData = JSON.parse(data.toString()); + this.msgs.push(parsedData); + }); + resolve(); + }); + }); + } + + clear() { + this.msgs.length = 0; + } + + buildRequest(params: any[], method = 'eth_subscribe') { + return JSON.stringify({ + jsonrpc: '2.0', + id: ++this.curReqId, + method, + params, + }); + } + + async waitForMsg( + subId: string, + filterFn = (_msg: any) => true, + timeout = 5000, + ) { + return new Promise(resolve => { + const interval = setInterval(() => { + const msg = this.msgs + .filter(msg => msg.params?.subscription === subId) + .find(msg => filterFn(msg.params.result)); + + if (msg) { + clearInterval(interval); + resolve(msg); + } + }, 1000); + + setTimeout(() => { + clearInterval(interval); + resolve(null); + }, timeout); + }); + } + + async waitForSubs(reqId: number) { + return new Promise(resolve => { + const interval = setInterval(() => { + const msg = this.msgs.find(msg => msg.id === reqId); + + if (msg) { + clearInterval(interval); + resolve(msg); + } + }, 1000); + }); + } + + async subscribeNewHeads() { + this.ws.send( + this.buildRequest(['newHeads']) + ); + + const resp = await this.waitForSubs(this.curReqId); + return resp.result as string; + } + + async subscribeLogs(params: any) { + this.ws.send( + this.buildRequest(['logs', params]) + ); + + const resp = await this.waitForSubs(this.curReqId); + return resp.result as string; + } + + async unSubscribe(subId: string) { + this.ws.send( + this.buildRequest([subId], 'eth_unsubscribe') + ); + + const resp = await this.waitForSubs(this.curReqId); + return resp.result as string; + } + + close() { + this.ws.close(); + } +} + +export const getAddrSelector = (addr: string) => hexZeroPad(addr, 32); diff --git a/packages/eth-rpc-adapter/src/__tests__/consts.ts b/packages/eth-rpc-adapter/src/__tests__/utils/consts.ts similarity index 98% rename from packages/eth-rpc-adapter/src/__tests__/consts.ts rename to packages/eth-rpc-adapter/src/__tests__/utils/consts.ts index 0ba702cd8..f57243a9c 100644 --- a/packages/eth-rpc-adapter/src/__tests__/consts.ts +++ b/packages/eth-rpc-adapter/src/__tests__/utils/consts.ts @@ -10,17 +10,6 @@ export interface LogHexified { logIndex: string; } -export const evmAccounts = [ - { - privateKey: '0xa872f6cbd25a0e04a08b1e21098017a9e6194d101d75e13111f71410c59cd57f', - evmAddress: '0x75E480dB528101a381Ce68544611C169Ad7EB342', - }, - { - privateKey: '0x4daddf7d5d2a9059e8065cb3ec50beabe2c23c7d6b3e380c1de8c40269acd85c', - evmAddress: '0xb00cB924ae22b2BBb15E10c17258D6a2af980421', - }, -]; - export const ADDRESS_ALICE = '0x82a258cb20e2adb4788153cd5eb5839615ece9a0'; export const DETERMINISTIC_SETUP_DEX_ADDRESS = '0x532394de2ca885b7e0306a2e258074cca4e42449'; diff --git a/packages/eth-rpc-adapter/src/__tests__/utils/evmAccounts.ts b/packages/eth-rpc-adapter/src/__tests__/utils/evmAccounts.ts new file mode 100644 index 000000000..90f7eb24f --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/utils/evmAccounts.ts @@ -0,0 +1,22 @@ +export const evmAccounts = [ + { + privateKey: '0xa872f6cbd25a0e04a08b1e21098017a9e6194d101d75e13111f71410c59cd57f', + evmAddress: '0x75E480dB528101a381Ce68544611C169Ad7EB342', + defaultSubstrateAddress: '5EMjsczjoEZaNbWzoXDcZtZDSHN1SLmu4ArJcEJVorNDfUH3', + }, + { + privateKey: '0xefb03e3f4fd8b3d7f9b14de6c6fb95044e2321d6bcb9dfe287ba987920254044', + evmAddress: '0xe3234f433914d4cfCF846491EC5a7831ab9f0bb3', + defaultSubstrateAddress: '5EMjsd17gquqfcU6NJ7bT7A7DTGpMhM3J6TwwYRGmkMBknM8', + }, + { + privateKey: '0x4daddf7d5d2a9059e8065cb3ec50beabe2c23c7d6b3e380c1de8c40269acd85c', + evmAddress: '0xb00cB924ae22b2BBb15E10c17258D6a2af980421', + defaultSubstrateAddress: '5EMjsczwT7eJ4qYuJVQQgVYdkTArXmeLZbm9JM1QzQeQvGbi', + }, + { + privateKey: '0x01392cd1a09fc0f4857742f0f0daa3ebd5a0f44a7dab48c23ccd331717b97b10', + evmAddress: '0x0085560b24769dAC4ed057F1B2ae40746AA9aAb6', + defaultSubstrateAddress: '5EMjsczLHBZqbroMR4nZH6NvQQWHsVRFU9fbwQ14vBQCQx9H', + }, +]; diff --git a/packages/eth-rpc-adapter/src/__tests__/utils/index.ts b/packages/eth-rpc-adapter/src/__tests__/utils/index.ts new file mode 100644 index 000000000..4fc73a37b --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/utils/index.ts @@ -0,0 +1,4 @@ +export * from './SubsManager'; +export * from './test-utils'; +export * from './evmAccounts'; +export * from './consts'; diff --git a/packages/eth-rpc-adapter/src/__tests__/utils.ts b/packages/eth-rpc-adapter/src/__tests__/utils/test-utils.ts similarity index 99% rename from packages/eth-rpc-adapter/src/__tests__/utils.ts rename to packages/eth-rpc-adapter/src/__tests__/utils/test-utils.ts index 8ebd236eb..727b09fb6 100644 --- a/packages/eth-rpc-adapter/src/__tests__/utils.ts +++ b/packages/eth-rpc-adapter/src/__tests__/utils/test-utils.ts @@ -7,7 +7,7 @@ import { parseEther } from 'ethers/lib/utils'; import axios from 'axios'; import { ERC20_ABI, ERC20_BYTECODE, GASMONSTER_ABI, GASMONSTER_BYTECODE, LogHexified } from './consts'; -import { JsonRpcError } from '../server'; +import { JsonRpcError } from '../../server'; export const NODE_RPC_URL = process.env.ENDPOINT_URL || 'ws://127.0.0.1:9944'; export const KARURA_ETH_RPC_URL = process.env.KARURA_ETH_RPC_URL || 'http://127.0.0.1:8546'; diff --git a/packages/eth-rpc-adapter/vitest.config.ts b/packages/eth-rpc-adapter/vitest.config.ts index becca8f07..1517a6fc1 100644 --- a/packages/eth-rpc-adapter/vitest.config.ts +++ b/packages/eth-rpc-adapter/vitest.config.ts @@ -6,7 +6,10 @@ export default mergeConfig( { test: { // include: ['**/*.test.ts'], // TODO: run all tests - include: ['src/__tests__/signer.test.ts'], + include: [ + 'src/__tests__/signer.test.ts', + 'src/__tests__/subscription.test.ts', + ], }, } ); diff --git a/yarn.lock b/yarn.lock index 08a0a2552..e9f88cd86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -99,6 +99,7 @@ __metadata: pm2: ^5.4.2 ts-node: ^10.9.1 ts-node-dev: ^2.0.0 + typechain: ^8.3.2 vitest: ^2.1.1 ws: ~8.2.3 yargs: 16.2.0 @@ -15135,7 +15136,7 @@ __metadata: languageName: node linkType: hard -"typechain@npm:^8.3.1": +"typechain@npm:^8.3.1, typechain@npm:^8.3.2": version: 8.3.2 resolution: "typechain@npm:8.3.2" dependencies: