A k6 extension to interact with EVM based blockchains.
-
Build or Install BlockSpeed
-
Check the examples folder to learn how to use it
You can visualize benchmark results in your local machines using the provided Grafana + InfluxDB instance:
docker-compose up -d
xk6 run --out influxdb=https://localhost:8086/blockspeed examples/multiple.js
Navigate to https://localhost:3000/d/BuduMUd4k/blockspeed?orgId=1
To build a k6
binary with this plugin, first ensure you have the prerequisites:
- Go toolchain
- If you're using SQLite, a build toolchain for your system that includes
gcc
or another C compiler. On Debian and derivatives install thebuild-essential
package. On Windows you can use tdm-gcc. Make sure thatgcc
is in yourPATH
. - Git
Then:
- Install
xk6
:
go install go.k6.io/xk6/cmd/xk6@latest
- Build the binary:
xk6 build --with github.com/distribworks/xk6-ethereum
The k6/x/ethereum
module contains the Ethereum extension to interact with Ethereum RPC API. To import the module add
import eth from 'k6/x/ethereum';
The class Client is an Ethereum RPC client that can perform several operations to an Ethereum node. The constructor takes the following arguments:
import eth from 'k6/x/ethereum';
const client = new eth.Client({
url: 'https://localhost:8545',
});
gasPrice() number
getBalance(address: string, blockNumber: number) number
blockNumber() number
getBlockByNumber(block: number, full: boolean) Block
getNonce(address: string) number
estimateGas(tx: Transaction) number
sendTransaction(tx: Transaction) string
sendRawTransaction(tx: Transaction) string
getTransactionReceipt(tx_hash: string) Receipt
waitForTransactionReceipt(tx_hash: string) => Promise<Receipt>
accounts() string[]
newContract(address: string, abi: string) Contract
deployContract(abi: string, bytecode: string, args[]) Receipt
Transaction
{
from: string
to: string
input: object
gas_price: number
gas_fee_cap: number
gas_tip_cap: number
gas: number
value: number
nonce: number
// eip-2930 values
chain_id: number
}
Receipt
{
transaction_hash: object
transaction_index: number
contract_address: string
block_hash: object
from: string
block_number: number
gas_used: number
cumulative_gas_used: number
logs_bloom: object
logs: Log[]
status: number
}
Log
{
removed: bool
log_index: number
transaction_index: number
transaction_hash: object
block_hash: object
block_number: number
address: string
topics: object[]
data: object
}
Contract{}
txn() Receipt
call() object
It exposes the following metrics:
- ethereum_block: Blocks in the chain during the test
- ethereum_req_duration: Time taken to perform an API call to the client
- ethereum_tps: Computation of Transactions Per Second mined
- ethereum_time_to_mine: Time it took since a transaction was sent to the client and it has been included in a block
import eth from 'k6/x/ethereum';
const client = new eth.Client({
url: 'https://localhost:8545',
// You can also specify a private key here
// privateKey: 'private key of your account',
// or a mnemonic
// mnemonic: 'my mnemonic'
});
// You can use an existing premined account
const root_address = "0x85da99c8a7c2c95964c8efd687e95e632fc533d6"
export function setup() {
return { nonce: client.getNonce(root_address) };
}
export default function (data) {
console.log(`nonce => ${data.nonce}`);
const gas = client.gasPrice();
console.log(`gas price => ${gas}`);
const bal = client.getBalance(root_address, client.blockNumber());
console.log(`bal => ${bal}`);
const tx = {
to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
value: Number(0.0001 * 1e18),
gas_price: gas,
nonce: data.nonce,
};
const txh = client.sendRawTransaction(tx)
console.log("tx hash => " + txh);
// Optional: wait for the transaction to be mined
// const receipt = client.waitForTransactionReceipt(txh).then((receipt) => {
// console.log("tx block hash => " + receipt.block_hash);
// console.log(typeof receipt.block_number);
// });
data.nonce = data.nonce + 1;
}