From 256088fc08586a2688c80eaa4f7b95d1a601afb6 Mon Sep 17 00:00:00 2001 From: Yasin Date: Thu, 11 Jul 2024 19:29:15 +0300 Subject: [PATCH 1/6] tests: evm rpc calls --- integration_test/evm_rpc/README.md | 9 + integration_test/evm_rpc/package.json | 27 ++ integration_test/evm_rpc/rpcCalls.ts | 368 +++++++++++++++++++++ integration_test/evm_rpc/testConfig.json | 6 + integration_test/evm_rpc/tsconfig.json | 12 + integration_test/evm_rpc/utils/cmdUtils.js | 74 +++++ integration_test/evm_rpc/utils/cmdUtils.ts | 35 ++ integration_test/evm_rpc/utils/evmUtils.js | 39 +++ integration_test/evm_rpc/utils/evmUtils.ts | 23 ++ integration_test/evm_rpc/utils/seiUtils.js | 92 ++++++ integration_test/evm_rpc/utils/seiUtils.ts | 70 ++++ 11 files changed, 755 insertions(+) create mode 100644 integration_test/evm_rpc/README.md create mode 100644 integration_test/evm_rpc/package.json create mode 100644 integration_test/evm_rpc/rpcCalls.ts create mode 100644 integration_test/evm_rpc/testConfig.json create mode 100644 integration_test/evm_rpc/tsconfig.json create mode 100644 integration_test/evm_rpc/utils/cmdUtils.js create mode 100644 integration_test/evm_rpc/utils/cmdUtils.ts create mode 100644 integration_test/evm_rpc/utils/evmUtils.js create mode 100644 integration_test/evm_rpc/utils/evmUtils.ts create mode 100644 integration_test/evm_rpc/utils/seiUtils.js create mode 100644 integration_test/evm_rpc/utils/seiUtils.ts diff --git a/integration_test/evm_rpc/README.md b/integration_test/evm_rpc/README.md new file mode 100644 index 000000000..6fceca930 --- /dev/null +++ b/integration_test/evm_rpc/README.md @@ -0,0 +1,9 @@ +## TS Tests for evm rpc calls + +Tests uses ethers v6 to make json rpc calls to evm rpcs. Tests are running against local sei chain. + +In order to run the tests you can run: + +``yarn install`` + +``yarn test`` \ No newline at end of file diff --git a/integration_test/evm_rpc/package.json b/integration_test/evm_rpc/package.json new file mode 100644 index 000000000..2982ba889 --- /dev/null +++ b/integration_test/evm_rpc/package.json @@ -0,0 +1,27 @@ +{ + "name": "evm_rpc", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "test": "mocha -r tsx rpcCalls.ts" + }, + "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "@noble/curves": "^1.4.2", + "@sei-js/core": "^3.2.1", + "@sei-js/proto": "^4.0.9", + "@types/chai": "^4.3.16", + "@types/mocha": "^10.0.7", + "chai": "^5.1.1", + "ethers": "^6.13.1", + "mocha": "^10.6.0", + "ts-mocha": "^10.0.0", + "tsx": "^4.16.2", + "viem": "^2.17.3" + }, + "devDependencies": {} +} diff --git a/integration_test/evm_rpc/rpcCalls.ts b/integration_test/evm_rpc/rpcCalls.ts new file mode 100644 index 000000000..229c0ea64 --- /dev/null +++ b/integration_test/evm_rpc/rpcCalls.ts @@ -0,0 +1,368 @@ +import ExpectStatic = Chai.ExpectStatic; +import {ethers, formatEther, toBeHex} from 'ethers'; +import { SigningStargateClient} from '@cosmjs/stargate'; +import {createEvmProvider, createEvmWallet, sendFundsFromEvmClient} from './utils/evmUtils'; +import { + associateWallet, + createSeiProvider, + createSeiWallet, generateEvmAddressFromMnemonic, + generateSeiAddressFromMnemonic, + sendFundsFromSeiClient +} from './utils/seiUtils'; +import {DirectSecp256k1HdWallet} from '@cosmjs/proto-signing'; +import {fundEvmWallet, fundSeiWallet, waitFor} from './utils/cmdUtils'; +import {seiprotocol} from '@sei-js/proto'; +import testConfig from './testConfig.json'; + +/** + * Runs against local sei chain. Generates two random accounts. + * Tests some of the rpc calls. + */ + +describe('Evm Rpc Calls', function (){ + let expect: ExpectStatic; + this.timeout( 4 * 60 * 1000); + const evmRpc = testConfig.evmRpc + const seiRpc = testConfig.seiRpc; + let evmClient: ethers.JsonRpcProvider; + let seiClient: SigningStargateClient; + let seiWallet: DirectSecp256k1HdWallet; + let evmWallet: ethers.HDNodeWallet; + let evmAddress: string; + let seiAddress: string; + let evmWalletSeiAddress: string; + const feeAccount = testConfig.feeAccount; + const chainId = testConfig.chainId; + + before('Tests set up', async () =>{ + const chai = await import('chai'); + ({expect} = chai); + seiWallet = await createSeiWallet(); + evmClient = await createEvmProvider(evmRpc); + seiClient = await createSeiProvider(seiRpc, seiWallet); + evmWallet = await createEvmWallet(evmClient); + evmWalletSeiAddress = await generateSeiAddressFromMnemonic(evmWallet); + await fundEvmWallet(evmWallet, evmRpc); + await fundSeiWallet(seiWallet); + await fundSeiWallet(evmWalletSeiAddress); + await waitFor(2); + evmAddress = await evmWallet.getAddress(); + seiAddress = (await seiWallet.getAccounts())[0].address; + }) + + describe('Association rpc tests', function (){ + let txHash: string; + + it('Evm users can associate accounts', async () =>{ + await associateWallet(evmClient, evmWallet); + const queriedSeiAddress = await evmClient.send('sei_getSeiAddress', [evmAddress]); + const seiQueryClient = await seiprotocol.ClientFactory + .createRPCQueryClient({rpcEndpoint: seiRpc}); + const {associated} = await seiQueryClient.seiprotocol.seichain.evm + .seiAddressByEVMAddress({evmAddress: evmAddress}); + const expectedSeiAddress = await generateSeiAddressFromMnemonic(evmWallet); + + expect(associated).to.be.true; + expect(queriedSeiAddress).to.be.eq(expectedSeiAddress); + }); + + it('Sei wallet can implicitly associate accounts', async () =>{ + const expectedSeiAddress = await generateSeiAddressFromMnemonic(evmWallet); + txHash = await sendFundsFromSeiClient(seiClient, seiAddress, expectedSeiAddress); + await waitFor(1); + const seiQueryClient = await seiprotocol.ClientFactory.createRPCQueryClient({rpcEndpoint: seiRpc}); + const {associated} = await seiQueryClient.seiprotocol.seichain.evm.eVMAddressBySeiAddress({seiAddress: seiAddress}); + + const queriedEvmAddress = await evmClient.send('sei_getEVMAddress', [seiAddress]); + const expectedEvmAddress = await generateEvmAddressFromMnemonic(seiWallet); + + expect(associated).to.be.true; + expect(queriedEvmAddress).to.be.eq(expectedEvmAddress); + }); + + it('Users can query evm tx', async () =>{ + const evmAddress = await generateEvmAddressFromMnemonic(seiWallet); + const [txHash,blockNumber, blockHash] = + await sendFundsFromEvmClient(evmWallet, evmAddress); + await waitFor(1); + + const txRecord = await evmClient.send('sei_getCosmosTx', [txHash]); + expect(txRecord).not.to.be.null; + + const txRecordOnCosmos = await evmClient.send('sei_getEvmTx', [txRecord]); + expect(txRecordOnCosmos).not.to.be.null; + }); + }); + + /** + * eth_getBlockReceipts + * eth_getBlockTransactionCountByNumber + * eth_getBlockTransactionCountByHash + * eth_getBlockByHash + * eth_getBlockByNumber + */ + describe('Block json rpc calls test', function (){ + let blockNumber: string; + let blockHash: string; + let txHash: string; + let evmSeiAddress: string; + + it('Users will get the block receipts with block number', async () =>{ + evmSeiAddress = await generateEvmAddressFromMnemonic(seiWallet); + ([txHash, blockNumber, blockHash] = + await sendFundsFromEvmClient(evmWallet, evmSeiAddress) as string[]); + const [txReceipt] = await evmClient.send('eth_getBlockReceipts', [ethers.toQuantity(blockNumber)]); + + expect(txReceipt).to.haveOwnProperty('blockHash'); + expect(txReceipt).to.haveOwnProperty('blockNumber'); + expect(txReceipt).to.haveOwnProperty('gasUsed'); + + expect(txReceipt.transactionHash).to.be.eq(txHash); + expect(txReceipt.from).to.be.eq(evmAddress.toLowerCase()); + expect(txReceipt.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users will get the block receipts with block hash', async () =>{ + const [txReceipt] = await evmClient.send('eth_getBlockReceipts', [blockHash]); + + expect(txReceipt).to.haveOwnProperty('blockHash'); + expect(txReceipt).to.haveOwnProperty('blockNumber'); + expect(txReceipt).to.haveOwnProperty('gasUsed'); + + expect(txReceipt.transactionHash).to.be.eq(txHash); + expect(txReceipt.from).to.be.eq(evmAddress.toLowerCase()); + expect(txReceipt.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users will see get block transaction count by number', async () =>{ + const txCount = await evmClient.send('eth_getBlockTransactionCountByNumber', [ethers.toQuantity(blockNumber)]); + expect(parseInt(txCount)).to.be.eq(1) + }); + + it('Users will see transaction count by hash', async () =>{ + const txCount = await evmClient.send('eth_getBlockTransactionCountByHash', [blockHash]); + expect(parseInt(txCount)).to.be.eq(1) + }); + + it('Users will get block details by hash', async () =>{ + const block = await evmClient.send('eth_getBlockByHash', [blockHash, true]); + + expect(block.transactions).to.have.length(1); + expect(block.hash).to.be.eq(blockHash); + expect(parseInt(block.number)).to.be.eq(parseInt(blockNumber)); + }); + + it('Users will get block details by number', async () =>{ + const block = await evmClient.send('eth_getBlockByNumber', [ethers.toQuantity(blockNumber), false]); + + expect(block.transactions).to.have.length(1); + expect(block.hash).to.be.eq(blockHash); + expect(parseInt(block.number)).to.be.eq(parseInt(blockNumber)); + }); + }); + + /** + * eth_BlockNumber + * eth_ChainId + * eth_Coinbase + * eth_Accounts + * eth_GasPrice + * eth_feeHistory + * eth_maxPriorityFeePerGas + */ + describe('Users can query the chain info through json rpc calls', function() { + + it('Users can query latest block number', async () =>{ + const blockNumber = await evmClient.send('eth_blockNumber', []); + expect(parseInt(blockNumber)).to.be.above(0); + }); + + it('Users can query the fee account', async () =>{ + const coinbase = await evmClient.send('eth_coinbase', []); + expect(coinbase).to.be.eq(feeAccount); + }); + + it('Users can query chain id', async () =>{ + const queriedChainId = await evmClient.send('eth_chainId', []); + expect(parseInt(queriedChainId)).to.be.eq(chainId); + }); + + it('Users can query accounts', async () =>{ + const accounts = await evmClient.send('eth_accounts', []); + expect(accounts.length).to.be.eq(21); + }); + + it('Users can query gas price', async () =>{ + const gasPrice = await evmClient.send('eth_gasPrice', []); + expect(parseInt(gasPrice)).to.be.above(990000000); + }); + + it('Users can query fee history', async () =>{ + const blockCount = 10; // + const lastBlock = await evmClient.getBlockNumber(); + const rewardPercentiles = [10.0]; + const feeHistory = await evmClient.send('eth_feeHistory', + [ethers.toQuantity(blockCount), ethers.toQuantity(lastBlock), rewardPercentiles]); + + expect(Number(feeHistory.oldestBlock)).to.be.eq((lastBlock - blockCount) + 1); + expect(feeHistory.baseFeePerGas).to.have.length(blockCount); + expect(feeHistory.gasUsedRatio).to.have.length(blockCount); + }); + + it('Users can query max priority fee per gas', async () =>{ + const maxPriority = await evmClient.send('eth_maxPriorityFeePerGas', []); + expect(Number(maxPriority)).to.be.gte(0); + }) + }) + + /** + * eth_getNonce + * eth_getBalance + * eth_getBlockByNumber + * + */ + describe('State rpc call tests', () =>{ + let latestBlockNumber: number; + let latestBalance: string; + let previousBalance: string; + let previousNonce: number; + + before('Gets the latest block number', async () =>{ + latestBlockNumber = await evmClient.getBlockNumber(); + previousNonce = await evmClient.send('eth_getNonce', [evmAddress]); + }); + + it('Users can query their balance with block number', async() =>{ + const userBalance = await evmClient.getBalance(evmAddress); + latestBalance = await evmClient.send('eth_getBalance', [evmAddress,ethers.toQuantity(latestBlockNumber)]); + expect(userBalance.toString()).to.be.eq(BigInt(latestBalance).toString()); + }); + + it('Users can query their balance from a previous block number', async () =>{ + previousBalance = await evmClient.send('eth_getBalance', [evmAddress, ethers.toQuantity(latestBlockNumber - 3)]); + expect(previousBalance).not.to.be.eq('0x'); + }); + + it('Users can query their balance with block hash', async() =>{ + const {hash} = await evmClient.send('eth_getBlockByNumber', [ethers.toQuantity(latestBlockNumber), false]); + const latestBalanceWithHash = await evmClient.send('eth_getBalance', [evmAddress, hash]); + expect(latestBalanceWithHash).to.be.eq(latestBalance); + }); + + it('Users can query their balance from a previous block with a hash', async () =>{ + const {hash} = await evmClient.send('eth_getBlockByNumber', [ethers.toQuantity(latestBlockNumber - 3), false]); + const previousBalanceWithHash = await evmClient.send('eth_getBalance', [evmAddress, hash]); + expect(previousBalanceWithHash).to.be.eq(previousBalance); + }); + + it('Users can query balance after transfers', async () =>{ + const seiEvmAddress = await generateEvmAddressFromMnemonic(seiWallet); + const [hash, blockNumberOfTransfer] = + await sendFundsFromEvmClient(evmWallet, seiEvmAddress) as [string, string]; + await waitFor(2); + const latestBalanceAfterTransfer = await evmClient.send('eth_getBalance', [evmAddress, 'latest']); + const balanceDifference = BigInt(latestBalance) - BigInt(latestBalanceAfterTransfer); + const difference = formatEther(balanceDifference.toString()); + expect(Number(difference)).to.be.gte(0.1); + + const previousBalanceOnTransferBlock = await evmClient.send('eth_getBalance', + [evmAddress, ethers.toQuantity(Number(blockNumberOfTransfer) - 1)]); + expect(previousBalanceOnTransferBlock).to.be.eq(latestBalance); + }); + + //ToDo Check the code get in detail + it.skip('Users can query byte code of a contract', async () =>{ + const ibcPrecompileAddress = '0x0000000000000000000000000000000000001009'; + const byteCode = await evmClient.send('eth_getCode', [ibcPrecompileAddress, 'latest']); + console.log(byteCode); + }); + + + it('Users can query next nonce', async () =>{ + const nonce = await evmClient.send('eth_getNonce', [evmAddress]); + expect(nonce).to.be.eq(previousNonce + 1); + }); + }); + + /** + * eth_getTransactionReceipt + * eth_getTransactionByHash + * eth_getTransactionByBlockNumberAndIndex + * eth_getTransactionByBlockHashAndIndex + * eth_getTransactionCount + */ + describe('Tx Rpc Tests', function () { + let blockNumber: string; + let blockHash: string; + let evmSeiAddress: string; + let txHash: string; + let usertxCount: string; + + it('Users can get transaction receipt', async () =>{ + evmSeiAddress = await generateEvmAddressFromMnemonic(seiWallet); + const [txHash] = await sendFundsFromEvmClient(evmWallet, evmSeiAddress); + await waitFor(1); + const receipt = await evmClient.send('eth_getTransactionReceipt', [txHash]); + + blockNumber = receipt.blockNumber; + blockHash = receipt.blockHash; + + expect(receipt).to.haveOwnProperty('blockHash'); + expect(receipt).to.haveOwnProperty('blockNumber'); + expect(receipt).to.haveOwnProperty('gasUsed'); + + expect(receipt.from).to.be.eq(evmAddress.toLowerCase()); + expect(receipt.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users can get transaction by hash', async () =>{ + ([txHash] = await sendFundsFromEvmClient(evmWallet, evmSeiAddress) as [string]); + await waitFor(1); + const txDetails = await evmClient.send('eth_getTransactionByHash', [txHash]); + expect(txDetails).to.haveOwnProperty('blockHash'); + expect(txDetails).to.haveOwnProperty('blockNumber'); + + expect(txDetails.from).to.be.eq(evmAddress.toLowerCase()); + expect(txDetails.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users can query tx from block number and index', async () =>{ + const txDetails = await evmClient.send('eth_getTransactionByBlockNumberAndIndex', + [ethers.toQuantity(blockNumber), ethers.toQuantity(0)]); + + expect(txDetails).to.haveOwnProperty('blockHash'); + expect(txDetails).to.haveOwnProperty('blockNumber'); + + expect(txDetails.from).to.be.eq(evmAddress.toLowerCase()); + expect(txDetails.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users can query tx from block hash and index', async () =>{ + const txDetails = await evmClient.send('eth_getTransactionByBlockHashAndIndex', + [blockHash, ethers.toQuantity(0)]); + + expect(txDetails).to.haveOwnProperty('blockHash'); + expect(txDetails).to.haveOwnProperty('blockNumber'); + + expect(txDetails.from).to.be.eq(evmAddress.toLowerCase()); + expect(txDetails.to).to.be.eq(evmSeiAddress.toLowerCase()); + }); + + it('Users cant query unexisting indexes', async () =>{ + const txDetails = await evmClient.send('eth_getTransactionByBlockHashAndIndex', [blockHash, ethers.toQuantity(5)]); + expect(txDetails).to.be.null; + }); + + it('Users can query tx count from block number', async () =>{ + usertxCount = await evmClient.send('eth_getTransactionCount', [evmAddress, ethers.toQuantity(blockNumber)]); + expect(parseInt(usertxCount)).to.be.above(1); + }); + + it('Users can query tx count from block hash', async () =>{ + const txCount = await evmClient.send('eth_getTransactionCount', [evmAddress, blockHash]); + expect(parseInt(txCount)).to.be.above(1); + expect(parseInt(usertxCount)).to.be.eq(parseInt(txCount)); + }); + }); + +}) \ No newline at end of file diff --git a/integration_test/evm_rpc/testConfig.json b/integration_test/evm_rpc/testConfig.json new file mode 100644 index 000000000..7ad44ad5d --- /dev/null +++ b/integration_test/evm_rpc/testConfig.json @@ -0,0 +1,6 @@ +{ + "evmRpc": "http://127.0.0.1:8545", + "seiRpc": "http://127.0.0.1:26657", + "feeAccount": "0x27f7b8b8b5a4e71e8e9aa671f4e4031e3773303f", + "chainId": 713715 +} \ No newline at end of file diff --git a/integration_test/evm_rpc/tsconfig.json b/integration_test/evm_rpc/tsconfig.json new file mode 100644 index 000000000..eca36a891 --- /dev/null +++ b/integration_test/evm_rpc/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "module": "commonjs", /* Specify what module code is generated. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + "strict": true, /* Enable all strict type-checking options. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/integration_test/evm_rpc/utils/cmdUtils.js b/integration_test/evm_rpc/utils/cmdUtils.js new file mode 100644 index 000000000..b45b4e703 --- /dev/null +++ b/integration_test/evm_rpc/utils/cmdUtils.js @@ -0,0 +1,74 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.waitFor = exports.fundSeiWallet = exports.fundEvmWallet = void 0; +const util = __importStar(require("node:util")); +const exec = util.promisify(require('node:child_process').exec); +const proto_signing_1 = require("@cosmjs/proto-signing"); +function fundEvmWallet(receiverWallet, rpc) { + return __awaiter(this, void 0, void 0, function* () { + const { stdout } = yield exec('seid keys show admin --address'); + const address = yield receiverWallet.getAddress(); + yield exec(`seid tx evm send ${address} 10000000000000000000000 --from admin --fees 24000use --evm-rpc=${rpc}`); + console.log('Funded on evm'); + }); +} +exports.fundEvmWallet = fundEvmWallet; +function fundSeiWallet(receiverWallet) { + return __awaiter(this, void 0, void 0, function* () { + let address; + if (receiverWallet instanceof proto_signing_1.DirectSecp256k1HdWallet) { + const [accountData, _] = yield receiverWallet.getAccounts(); + address = accountData.address; + } + else { + address = receiverWallet; + } + const { stdout } = yield exec('seid keys show admin --address'); + const senderAddress = stdout.trim().replaceAll(' ', ''); + console.log('Funding sei address'); + yield exec(`seid tx bank send ${senderAddress} ${address} 10000000000usei --from admin --fees 24200usei -y`); + }); +} +exports.fundSeiWallet = fundSeiWallet; +function waitFor(seconds) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => { + return setTimeout(() => { + resolve(); + }, seconds * 1000); + }); + }); +} +exports.waitFor = waitFor; diff --git a/integration_test/evm_rpc/utils/cmdUtils.ts b/integration_test/evm_rpc/utils/cmdUtils.ts new file mode 100644 index 000000000..7125b6a32 --- /dev/null +++ b/integration_test/evm_rpc/utils/cmdUtils.ts @@ -0,0 +1,35 @@ +import * as util from 'node:util'; +const exec = util.promisify(require('node:child_process').exec); + +import {ethers} from 'ethers'; +import {DirectSecp256k1HdWallet} from '@cosmjs/proto-signing'; + + +export async function fundEvmWallet(receiverWallet: ethers.HDNodeWallet, rpc: string){ + const {stdout} = await exec('seid keys show admin --address'); + const address = await receiverWallet.getAddress(); + await exec(`seid tx evm send ${address} 10000000000000000000000 --from admin --fees 24000use --evm-rpc=${rpc}`); + console.log('Funded on evm'); +} + +export async function fundSeiWallet(receiverWallet: DirectSecp256k1HdWallet | string){ + let address: string; + if(receiverWallet instanceof DirectSecp256k1HdWallet){ + const [accountData, _] = await receiverWallet.getAccounts(); + address = accountData.address; + } else { + address = receiverWallet; + } + const {stdout} = await exec('seid keys show admin --address'); + const senderAddress = stdout.trim().replaceAll(' ', ''); + console.log('Funding sei address'); + await exec(`seid tx bank send ${senderAddress} ${address} 10000000000usei --from admin --fees 24200usei -y`); +} + +export async function waitFor(seconds: number){ + return new Promise((resolve) =>{ + return setTimeout(() =>{ + resolve(); + }, seconds * 1000) + }) +} \ No newline at end of file diff --git a/integration_test/evm_rpc/utils/evmUtils.js b/integration_test/evm_rpc/utils/evmUtils.js new file mode 100644 index 000000000..30213afdd --- /dev/null +++ b/integration_test/evm_rpc/utils/evmUtils.js @@ -0,0 +1,39 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sendFundsFromEvmClient = exports.createEvmWallet = exports.createEvmProvider = void 0; +const ethers_1 = require("ethers"); +function createEvmProvider(rpcUrl) { + return __awaiter(this, void 0, void 0, function* () { + return new ethers_1.ethers.JsonRpcProvider(rpcUrl); + }); +} +exports.createEvmProvider = createEvmProvider; +function createEvmWallet(evmClient) { + return __awaiter(this, void 0, void 0, function* () { + return ethers_1.ethers.Wallet.createRandom(evmClient); + }); +} +exports.createEvmWallet = createEvmWallet; +function sendFundsFromEvmClient(wallet, recipientAddress) { + return __awaiter(this, void 0, void 0, function* () { + const tx = { + to: recipientAddress, + value: ethers_1.ethers.parseUnits('0.1', 'ether'), + }; + // Send the transaction + const txResponse = yield wallet.sendTransaction(tx); + // Wait for the transaction to be mined + const receipt = yield txResponse.wait(); + return [receipt === null || receipt === void 0 ? void 0 : receipt.hash, receipt === null || receipt === void 0 ? void 0 : receipt.blockNumber, receipt === null || receipt === void 0 ? void 0 : receipt.blockHash]; + }); +} +exports.sendFundsFromEvmClient = sendFundsFromEvmClient; diff --git a/integration_test/evm_rpc/utils/evmUtils.ts b/integration_test/evm_rpc/utils/evmUtils.ts new file mode 100644 index 000000000..ec2808f26 --- /dev/null +++ b/integration_test/evm_rpc/utils/evmUtils.ts @@ -0,0 +1,23 @@ +import {ethers} from 'ethers'; + +export async function createEvmProvider(rpcUrl: string) { + return new ethers.JsonRpcProvider(rpcUrl) +} + +export async function createEvmWallet(evmClient: ethers.JsonRpcProvider) { + return ethers.Wallet.createRandom(evmClient); +} + +export async function sendFundsFromEvmClient(wallet: ethers.HDNodeWallet, recipientAddress: string) { + const tx = { + to: recipientAddress, + value: ethers.parseUnits('0.1', 'ether'), + }; + + // Send the transaction + const txResponse = await wallet.sendTransaction(tx); + + // Wait for the transaction to be mined + const receipt = await txResponse.wait(); + return [receipt?.hash, receipt?.blockNumber, receipt?.blockHash]; +} \ No newline at end of file diff --git a/integration_test/evm_rpc/utils/seiUtils.js b/integration_test/evm_rpc/utils/seiUtils.js new file mode 100644 index 000000000..08215ce77 --- /dev/null +++ b/integration_test/evm_rpc/utils/seiUtils.js @@ -0,0 +1,92 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sendFundsFromSeiClient = exports.generateSeiAddressFromMnemonic = exports.generateEvmAddressFromMnemonic = exports.signMessage = exports.associateWallet = exports.createSeiWallet = exports.createSeiProvider = void 0; +const crypto_1 = require("@cosmjs/crypto"); +const proto_signing_1 = require("@cosmjs/proto-signing"); +const stargate_1 = require("@cosmjs/stargate"); +const ethers_1 = require("ethers"); +const secp256k1_1 = require("@noble/curves/secp256k1"); +const viem_1 = require("viem"); +const cmdUtils_1 = require("./cmdUtils"); +function createSeiProvider(rpcUrl, wallet) { + return __awaiter(this, void 0, void 0, function* () { + return yield stargate_1.SigningStargateClient.connectWithSigner(rpcUrl, wallet); + }); +} +exports.createSeiProvider = createSeiProvider; +function createSeiWallet() { + return __awaiter(this, void 0, void 0, function* () { + return yield proto_signing_1.DirectSecp256k1HdWallet.generate(24, { + prefix: 'sei' + }); + }); +} +exports.createSeiWallet = createSeiWallet; +function associateWallet(evmProvider, evmWallet) { + return __awaiter(this, void 0, void 0, function* () { + const message = "account association"; + const signature = yield evmWallet.signMessage(message); + const { r, s } = secp256k1_1.secp256k1.Signature.fromCompact(signature.slice(2, 130)); + const v = (0, viem_1.hexToNumber)(`0x${signature.slice(130)}`); + const messageLength = Buffer.from(message, "utf8").length; + const messageToSign = `\x19Ethereum Signed Message:\n${messageLength}${message}`; + const request = { + r: (0, viem_1.numberToHex)(r), + s: (0, viem_1.numberToHex)(s), + v: (0, viem_1.numberToHex)(v - 27), + custom_message: messageToSign, + }; + yield evmProvider.send('sei_associate', [request]); + yield (0, cmdUtils_1.waitFor)(2); + }); +} +exports.associateWallet = associateWallet; +function signMessage(evmWallet) { + return __awaiter(this, void 0, void 0, function* () { + const customMessage = 'associate wallets'; + const sign = yield evmWallet.signMessage(customMessage); + const values = ethers_1.ethers.Signature.from(sign); + const { r, v, s } = values; + return { r, v, s }; + }); +} +exports.signMessage = signMessage; +function generateEvmAddressFromMnemonic(seiWallet) { + return __awaiter(this, void 0, void 0, function* () { + const evmWallet = ethers_1.ethers.HDNodeWallet.fromPhrase(seiWallet.mnemonic, '', 'm/44\'/118\'/0\'/0/0'); + return yield evmWallet.getAddress(); + }); +} +exports.generateEvmAddressFromMnemonic = generateEvmAddressFromMnemonic; +function generateSeiAddressFromMnemonic(evmWallet) { + return __awaiter(this, void 0, void 0, function* () { + const mnemonic = evmWallet.mnemonic.phrase; + const wallet = yield proto_signing_1.DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'sei', + hdPaths: [(0, crypto_1.stringToPath)('m/44\'/60\'/0\'/0/0')] + }); + return (yield wallet.getAccounts())[0].address; + }); +} +exports.generateSeiAddressFromMnemonic = generateSeiAddressFromMnemonic; +function sendFundsFromSeiClient(signingClient, senderWallet, receiverAddress) { + return __awaiter(this, void 0, void 0, function* () { + const fee = { + amount: (0, proto_signing_1.coins)(24000, "usei"), // fee amount + gas: "250000", // gas limit + }; + const transferAmount = (0, stargate_1.coin)('100000', 'usei'); + const receipt = yield signingClient.sendTokens(senderWallet, receiverAddress, [transferAmount], fee); + return receipt.transactionHash; + }); +} +exports.sendFundsFromSeiClient = sendFundsFromSeiClient; diff --git a/integration_test/evm_rpc/utils/seiUtils.ts b/integration_test/evm_rpc/utils/seiUtils.ts new file mode 100644 index 000000000..758800429 --- /dev/null +++ b/integration_test/evm_rpc/utils/seiUtils.ts @@ -0,0 +1,70 @@ +import {Random, stringToPath} from '@cosmjs/crypto'; +import {coins, DirectSecp256k1HdWallet} from '@cosmjs/proto-signing'; +import {coin, SigningStargateClient} from '@cosmjs/stargate'; +import {ethers, toBeHex} from 'ethers'; +import {cosmos} from '@sei-js/proto'; +import {secp256k1} from '@noble/curves/secp256k1'; +import {hexToNumber, numberToHex} from 'viem'; +import {waitFor} from './cmdUtils'; +import {Coin} from '@sei-js/proto/dist/types/codegen/cosmos/base/v1beta1/coin'; + +export async function createSeiProvider(rpcUrl: string, wallet: DirectSecp256k1HdWallet){ + return await SigningStargateClient.connectWithSigner(rpcUrl, wallet); +} + +export async function createSeiWallet(){ + return await DirectSecp256k1HdWallet.generate(24, { + prefix: 'sei' + }); +} + +export async function associateWallet(evmProvider: ethers.JsonRpcProvider, evmWallet: ethers.HDNodeWallet){ + const message = "account association"; + const signature = await evmWallet.signMessage( + message, + ); + const { r, s } = secp256k1.Signature.fromCompact(signature.slice(2, 130)); + const v = hexToNumber(`0x${signature.slice(130)}`); + + const messageLength = Buffer.from(message, "utf8").length; + const messageToSign = `\x19Ethereum Signed Message:\n${messageLength}${message}`; + const request = { + r: numberToHex(r), + s: numberToHex(s), + v: numberToHex(v - 27), + custom_message: messageToSign, + }; + await evmProvider.send('sei_associate', [request]); + await waitFor(2); +} + +export async function signMessage(evmWallet: ethers.HDNodeWallet){ + const customMessage = 'associate wallets'; + const sign = await evmWallet.signMessage(customMessage); + const values = ethers.Signature.from(sign); + const {r,v,s} = values; + return {r, v, s}; +} + +export async function generateEvmAddressFromMnemonic(seiWallet: DirectSecp256k1HdWallet){ + const evmWallet = ethers.HDNodeWallet.fromPhrase(seiWallet.mnemonic, '', 'm/44\'/118\'/0\'/0/0'); + return await evmWallet.getAddress() +} + +export async function generateSeiAddressFromMnemonic(evmWallet: ethers.HDNodeWallet){ + const mnemonic = evmWallet.mnemonic!.phrase; + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'sei', + hdPaths: [stringToPath('m/44\'/60\'/0\'/0/0')] + }); + return (await wallet.getAccounts())[0].address; +} + +export async function sendFundsFromSeiClient(signingClient: SigningStargateClient, senderWallet: string, receiverAddress: string){ + const fee = { + amount: coins(24000, "usei"), // fee amount + gas: "250000", // gas limit + }; const transferAmount = coin('100000', 'usei'); + const receipt = await signingClient.sendTokens(senderWallet, receiverAddress, [transferAmount], fee); + return receipt.transactionHash; +} \ No newline at end of file From f857e93745733155f2ec37c2494a1f9b8e682853 Mon Sep 17 00:00:00 2001 From: Yasin Date: Thu, 11 Jul 2024 19:41:04 +0300 Subject: [PATCH 2/6] chore: remove js files --- integration_test/evm_rpc/utils/cmdUtils.js | 74 ----------------- integration_test/evm_rpc/utils/evmUtils.js | 39 --------- integration_test/evm_rpc/utils/seiUtils.js | 92 ---------------------- 3 files changed, 205 deletions(-) delete mode 100644 integration_test/evm_rpc/utils/cmdUtils.js delete mode 100644 integration_test/evm_rpc/utils/evmUtils.js delete mode 100644 integration_test/evm_rpc/utils/seiUtils.js diff --git a/integration_test/evm_rpc/utils/cmdUtils.js b/integration_test/evm_rpc/utils/cmdUtils.js deleted file mode 100644 index b45b4e703..000000000 --- a/integration_test/evm_rpc/utils/cmdUtils.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.waitFor = exports.fundSeiWallet = exports.fundEvmWallet = void 0; -const util = __importStar(require("node:util")); -const exec = util.promisify(require('node:child_process').exec); -const proto_signing_1 = require("@cosmjs/proto-signing"); -function fundEvmWallet(receiverWallet, rpc) { - return __awaiter(this, void 0, void 0, function* () { - const { stdout } = yield exec('seid keys show admin --address'); - const address = yield receiverWallet.getAddress(); - yield exec(`seid tx evm send ${address} 10000000000000000000000 --from admin --fees 24000use --evm-rpc=${rpc}`); - console.log('Funded on evm'); - }); -} -exports.fundEvmWallet = fundEvmWallet; -function fundSeiWallet(receiverWallet) { - return __awaiter(this, void 0, void 0, function* () { - let address; - if (receiverWallet instanceof proto_signing_1.DirectSecp256k1HdWallet) { - const [accountData, _] = yield receiverWallet.getAccounts(); - address = accountData.address; - } - else { - address = receiverWallet; - } - const { stdout } = yield exec('seid keys show admin --address'); - const senderAddress = stdout.trim().replaceAll(' ', ''); - console.log('Funding sei address'); - yield exec(`seid tx bank send ${senderAddress} ${address} 10000000000usei --from admin --fees 24200usei -y`); - }); -} -exports.fundSeiWallet = fundSeiWallet; -function waitFor(seconds) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise((resolve) => { - return setTimeout(() => { - resolve(); - }, seconds * 1000); - }); - }); -} -exports.waitFor = waitFor; diff --git a/integration_test/evm_rpc/utils/evmUtils.js b/integration_test/evm_rpc/utils/evmUtils.js deleted file mode 100644 index 30213afdd..000000000 --- a/integration_test/evm_rpc/utils/evmUtils.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.sendFundsFromEvmClient = exports.createEvmWallet = exports.createEvmProvider = void 0; -const ethers_1 = require("ethers"); -function createEvmProvider(rpcUrl) { - return __awaiter(this, void 0, void 0, function* () { - return new ethers_1.ethers.JsonRpcProvider(rpcUrl); - }); -} -exports.createEvmProvider = createEvmProvider; -function createEvmWallet(evmClient) { - return __awaiter(this, void 0, void 0, function* () { - return ethers_1.ethers.Wallet.createRandom(evmClient); - }); -} -exports.createEvmWallet = createEvmWallet; -function sendFundsFromEvmClient(wallet, recipientAddress) { - return __awaiter(this, void 0, void 0, function* () { - const tx = { - to: recipientAddress, - value: ethers_1.ethers.parseUnits('0.1', 'ether'), - }; - // Send the transaction - const txResponse = yield wallet.sendTransaction(tx); - // Wait for the transaction to be mined - const receipt = yield txResponse.wait(); - return [receipt === null || receipt === void 0 ? void 0 : receipt.hash, receipt === null || receipt === void 0 ? void 0 : receipt.blockNumber, receipt === null || receipt === void 0 ? void 0 : receipt.blockHash]; - }); -} -exports.sendFundsFromEvmClient = sendFundsFromEvmClient; diff --git a/integration_test/evm_rpc/utils/seiUtils.js b/integration_test/evm_rpc/utils/seiUtils.js deleted file mode 100644 index 08215ce77..000000000 --- a/integration_test/evm_rpc/utils/seiUtils.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.sendFundsFromSeiClient = exports.generateSeiAddressFromMnemonic = exports.generateEvmAddressFromMnemonic = exports.signMessage = exports.associateWallet = exports.createSeiWallet = exports.createSeiProvider = void 0; -const crypto_1 = require("@cosmjs/crypto"); -const proto_signing_1 = require("@cosmjs/proto-signing"); -const stargate_1 = require("@cosmjs/stargate"); -const ethers_1 = require("ethers"); -const secp256k1_1 = require("@noble/curves/secp256k1"); -const viem_1 = require("viem"); -const cmdUtils_1 = require("./cmdUtils"); -function createSeiProvider(rpcUrl, wallet) { - return __awaiter(this, void 0, void 0, function* () { - return yield stargate_1.SigningStargateClient.connectWithSigner(rpcUrl, wallet); - }); -} -exports.createSeiProvider = createSeiProvider; -function createSeiWallet() { - return __awaiter(this, void 0, void 0, function* () { - return yield proto_signing_1.DirectSecp256k1HdWallet.generate(24, { - prefix: 'sei' - }); - }); -} -exports.createSeiWallet = createSeiWallet; -function associateWallet(evmProvider, evmWallet) { - return __awaiter(this, void 0, void 0, function* () { - const message = "account association"; - const signature = yield evmWallet.signMessage(message); - const { r, s } = secp256k1_1.secp256k1.Signature.fromCompact(signature.slice(2, 130)); - const v = (0, viem_1.hexToNumber)(`0x${signature.slice(130)}`); - const messageLength = Buffer.from(message, "utf8").length; - const messageToSign = `\x19Ethereum Signed Message:\n${messageLength}${message}`; - const request = { - r: (0, viem_1.numberToHex)(r), - s: (0, viem_1.numberToHex)(s), - v: (0, viem_1.numberToHex)(v - 27), - custom_message: messageToSign, - }; - yield evmProvider.send('sei_associate', [request]); - yield (0, cmdUtils_1.waitFor)(2); - }); -} -exports.associateWallet = associateWallet; -function signMessage(evmWallet) { - return __awaiter(this, void 0, void 0, function* () { - const customMessage = 'associate wallets'; - const sign = yield evmWallet.signMessage(customMessage); - const values = ethers_1.ethers.Signature.from(sign); - const { r, v, s } = values; - return { r, v, s }; - }); -} -exports.signMessage = signMessage; -function generateEvmAddressFromMnemonic(seiWallet) { - return __awaiter(this, void 0, void 0, function* () { - const evmWallet = ethers_1.ethers.HDNodeWallet.fromPhrase(seiWallet.mnemonic, '', 'm/44\'/118\'/0\'/0/0'); - return yield evmWallet.getAddress(); - }); -} -exports.generateEvmAddressFromMnemonic = generateEvmAddressFromMnemonic; -function generateSeiAddressFromMnemonic(evmWallet) { - return __awaiter(this, void 0, void 0, function* () { - const mnemonic = evmWallet.mnemonic.phrase; - const wallet = yield proto_signing_1.DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { - prefix: 'sei', - hdPaths: [(0, crypto_1.stringToPath)('m/44\'/60\'/0\'/0/0')] - }); - return (yield wallet.getAccounts())[0].address; - }); -} -exports.generateSeiAddressFromMnemonic = generateSeiAddressFromMnemonic; -function sendFundsFromSeiClient(signingClient, senderWallet, receiverAddress) { - return __awaiter(this, void 0, void 0, function* () { - const fee = { - amount: (0, proto_signing_1.coins)(24000, "usei"), // fee amount - gas: "250000", // gas limit - }; - const transferAmount = (0, stargate_1.coin)('100000', 'usei'); - const receipt = yield signingClient.sendTokens(senderWallet, receiverAddress, [transferAmount], fee); - return receipt.transactionHash; - }); -} -exports.sendFundsFromSeiClient = sendFundsFromSeiClient; From 1c3cf985671d1072d974ede0fc9ddf937daf28b2 Mon Sep 17 00:00:00 2001 From: Yasin Date: Thu, 11 Jul 2024 19:42:42 +0300 Subject: [PATCH 3/6] chore: remove js files --- integration_test/evm_rpc/rpcCalls.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/integration_test/evm_rpc/rpcCalls.ts b/integration_test/evm_rpc/rpcCalls.ts index 229c0ea64..5daa00d10 100644 --- a/integration_test/evm_rpc/rpcCalls.ts +++ b/integration_test/evm_rpc/rpcCalls.ts @@ -364,5 +364,4 @@ describe('Evm Rpc Calls', function (){ expect(parseInt(usertxCount)).to.be.eq(parseInt(txCount)); }); }); - }) \ No newline at end of file From 219687849415c47d47b545019ecb624c1537f1f3 Mon Sep 17 00:00:00 2001 From: Yasin Date: Thu, 11 Jul 2024 19:46:11 +0300 Subject: [PATCH 4/6] chore: fix typo --- integration_test/evm_rpc/utils/evmUtils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/integration_test/evm_rpc/utils/evmUtils.ts b/integration_test/evm_rpc/utils/evmUtils.ts index ec2808f26..b850f5f7b 100644 --- a/integration_test/evm_rpc/utils/evmUtils.ts +++ b/integration_test/evm_rpc/utils/evmUtils.ts @@ -14,10 +14,8 @@ export async function sendFundsFromEvmClient(wallet: ethers.HDNodeWallet, recipi value: ethers.parseUnits('0.1', 'ether'), }; - // Send the transaction const txResponse = await wallet.sendTransaction(tx); - // Wait for the transaction to be mined const receipt = await txResponse.wait(); return [receipt?.hash, receipt?.blockNumber, receipt?.blockHash]; } \ No newline at end of file From fe0652282b4d10a64355bf2e754e4615a58a80ef Mon Sep 17 00:00:00 2001 From: Yasin Date: Fri, 12 Jul 2024 00:34:41 +0300 Subject: [PATCH 5/6] tests: add contract deploy step --- integration_test/evm_rpc/rpcCalls.ts | 38 +++++++++++----------- integration_test/evm_rpc/utils/evmUtils.ts | 14 +++++++- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/integration_test/evm_rpc/rpcCalls.ts b/integration_test/evm_rpc/rpcCalls.ts index 5daa00d10..8b6c8be5e 100644 --- a/integration_test/evm_rpc/rpcCalls.ts +++ b/integration_test/evm_rpc/rpcCalls.ts @@ -1,7 +1,7 @@ import ExpectStatic = Chai.ExpectStatic; import {ethers, formatEther, toBeHex} from 'ethers'; import { SigningStargateClient} from '@cosmjs/stargate'; -import {createEvmProvider, createEvmWallet, sendFundsFromEvmClient} from './utils/evmUtils'; +import {createEvmProvider, createEvmWallet, deployToChain, sendFundsFromEvmClient} from './utils/evmUtils'; import { associateWallet, createSeiProvider, @@ -50,7 +50,7 @@ describe('Evm Rpc Calls', function (){ seiAddress = (await seiWallet.getAccounts())[0].address; }) - describe('Association rpc tests', function (){ + describe('Association rpc calls tests', function (){ let txHash: string; it('Evm users can associate accounts', async () =>{ @@ -101,7 +101,7 @@ describe('Evm Rpc Calls', function (){ * eth_getBlockByHash * eth_getBlockByNumber */ - describe('Block json rpc calls test', function (){ + describe('Block rpc calls test', function (){ let blockNumber: string; let blockHash: string; let txHash: string; @@ -170,7 +170,7 @@ describe('Evm Rpc Calls', function (){ * eth_feeHistory * eth_maxPriorityFeePerGas */ - describe('Users can query the chain info through json rpc calls', function() { + describe('Info rpc calls tests', function() { it('Users can query latest block number', async () =>{ const blockNumber = await evmClient.send('eth_blockNumber', []); @@ -221,7 +221,7 @@ describe('Evm Rpc Calls', function (){ * eth_getBlockByNumber * */ - describe('State rpc call tests', () =>{ + describe('State rpc calls tests', () =>{ let latestBlockNumber: number; let latestBalance: string; let previousBalance: string; @@ -270,17 +270,16 @@ describe('Evm Rpc Calls', function (){ expect(previousBalanceOnTransferBlock).to.be.eq(latestBalance); }); - //ToDo Check the code get in detail - it.skip('Users can query byte code of a contract', async () =>{ - const ibcPrecompileAddress = '0x0000000000000000000000000000000000001009'; - const byteCode = await evmClient.send('eth_getCode', [ibcPrecompileAddress, 'latest']); - console.log(byteCode); + it('Users can query byte code of a contract', async () =>{ + const {address, bytecode} = await deployToChain(evmWallet); + await waitFor(2); + const queriedByteCode = await evmClient.send('eth_getCode', [address, 'latest']); + expect(queriedByteCode).to.be.eq(bytecode); }); - it('Users can query next nonce', async () =>{ const nonce = await evmClient.send('eth_getNonce', [evmAddress]); - expect(nonce).to.be.eq(previousNonce + 1); + expect(nonce).to.be.eq(previousNonce + 2); }); }); @@ -315,6 +314,11 @@ describe('Evm Rpc Calls', function (){ expect(receipt.to).to.be.eq(evmSeiAddress.toLowerCase()); }); + it('Users can query tx count from block number', async () =>{ + usertxCount = await evmClient.send('eth_getTransactionCount', [evmAddress, ethers.toQuantity(blockNumber)]); + expect(parseInt(usertxCount)).to.be.gte(1); + }); + it('Users can get transaction by hash', async () =>{ ([txHash] = await sendFundsFromEvmClient(evmWallet, evmSeiAddress) as [string]); await waitFor(1); @@ -353,15 +357,11 @@ describe('Evm Rpc Calls', function (){ expect(txDetails).to.be.null; }); - it('Users can query tx count from block number', async () =>{ - usertxCount = await evmClient.send('eth_getTransactionCount', [evmAddress, ethers.toQuantity(blockNumber)]); - expect(parseInt(usertxCount)).to.be.above(1); - }); - it('Users can query tx count from block hash', async () =>{ - const txCount = await evmClient.send('eth_getTransactionCount', [evmAddress, blockHash]); + const block = await evmClient.send('eth_getBlockByNumber', ['latest', false]); + const txCount = await evmClient.send('eth_getTransactionCount', [evmAddress, block.hash]); expect(parseInt(txCount)).to.be.above(1); - expect(parseInt(usertxCount)).to.be.eq(parseInt(txCount)); + expect(parseInt(usertxCount)).to.be.eq(parseInt(txCount) - 1); }); }); }) \ No newline at end of file diff --git a/integration_test/evm_rpc/utils/evmUtils.ts b/integration_test/evm_rpc/utils/evmUtils.ts index b850f5f7b..b9d847d1d 100644 --- a/integration_test/evm_rpc/utils/evmUtils.ts +++ b/integration_test/evm_rpc/utils/evmUtils.ts @@ -1,4 +1,6 @@ import {ethers} from 'ethers'; +import abi from '../../../contracts/artifacts/src/BoxV2.sol/BoxV2.json'; + export async function createEvmProvider(rpcUrl: string) { return new ethers.JsonRpcProvider(rpcUrl) @@ -18,4 +20,14 @@ export async function sendFundsFromEvmClient(wallet: ethers.HDNodeWallet, recipi const receipt = await txResponse.wait(); return [receipt?.hash, receipt?.blockNumber, receipt?.blockHash]; -} \ No newline at end of file +} + + +export async function deployToChain(evmWallet: ethers.HDNodeWallet){ + const contractFactory = new ethers.ContractFactory(abi.abi, abi.bytecode, evmWallet); + const contract = await contractFactory.deploy(); + return { + address: contract.target, + bytecode: abi.deployedBytecode + }; +} From 5ef2ce7f0cbf7a7d148ba1537d622ee281fb9f8f Mon Sep 17 00:00:00 2001 From: Yasin Date: Thu, 1 Aug 2024 20:58:49 +0300 Subject: [PATCH 6/6] tests: update wrong assertion --- integration_test/evm_rpc/rpcCalls.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration_test/evm_rpc/rpcCalls.ts b/integration_test/evm_rpc/rpcCalls.ts index 8b6c8be5e..b876fc324 100644 --- a/integration_test/evm_rpc/rpcCalls.ts +++ b/integration_test/evm_rpc/rpcCalls.ts @@ -136,12 +136,12 @@ describe('Evm Rpc Calls', function (){ it('Users will see get block transaction count by number', async () =>{ const txCount = await evmClient.send('eth_getBlockTransactionCountByNumber', [ethers.toQuantity(blockNumber)]); - expect(parseInt(txCount)).to.be.eq(1) + expect(parseInt(txCount)).to.be.eq(1); }); it('Users will see transaction count by hash', async () =>{ const txCount = await evmClient.send('eth_getBlockTransactionCountByHash', [blockHash]); - expect(parseInt(txCount)).to.be.eq(1) + expect(parseInt(txCount)).to.be.eq(1); }); it('Users will get block details by hash', async () =>{ @@ -189,7 +189,7 @@ describe('Evm Rpc Calls', function (){ it('Users can query accounts', async () =>{ const accounts = await evmClient.send('eth_accounts', []); - expect(accounts.length).to.be.eq(21); + expect(accounts.length).to.be.above(0); }); it('Users can query gas price', async () =>{