Ethers-Opt Examples
This page demonstrates class methods that would override ethers.js class objects.
For existing ethers.js class objects refer ethers.js V6 documentation for more info.
WARNING
Following examples does not document every available features / functions from Ethers-Opt. I would recommend referring test cases and source code to find available codes.
WARNING
Any Ethers-Opt code are subject to change especially when API changes on the upstream ethers.js code. So please follow changes on their repository as well if you seek to use this library.
Table of Contents
- Fixtures
- Prover
- Batcher
- Block Hashes
- Block Receipts
- Browser Provider
- Events
- Fee Estimator
- Multicall
- OP Stack (Optimism)
- Permit
- Proof
- Provider
- Signer
- Trace Block
- Utils
- Price
- ENS
Fixtures
ts
import { getSigners, deployERC20 } from 'ethers-opt/fixtures';
// Get signers wrapped for test/development
const [owner, bob] = await getSigners();
// Deploy a test ERC20 token
const token = await deployERC20(owner, "MyToken", "MTK", 18, 1000000);
console.log(await token.symbol()); // "MTK"
Prover
ts
import { ERC20__factory, Provider } from 'ethers-opt';
import { verifyERC20Proof, verifyChainlinkProof } from 'ethers-opt/prover';
const provider = new Provider('https://1rpc.io/eth');
const usdt = ERC20__factory.connect('0xdAC17F958D2ee523a2206206994597C13D831ec7', provider);
const vitalik = await provider.resolveName('vitalik.eth');
const vitalikBalance = await usdt.balanceOf(vitalik);
// To verify ERC20 balance proof (needs correct balance slot index, here we try 0):
const proofResult = await verifyERC20Proof(usdt, 0, vitalik, vitalikBalance);
console.log(proofResult?.tokenBalance);
Batcher
ts
import { EthersBatcher } from 'ethers-opt';
const batcher = new EthersBatcher({ ratePerSecond: 10, batchSize: 2 });
const provider = /* your Provider */;
const blockNumbers = [10000000, 10000001];
const blocks = await batcher.getBlocks(provider, blockNumbers);
console.log(blocks.map(b => b.number));
Block Hashes
ts
import { fetchBlockHashes, compareBlockHashes, Provider } from 'ethers-opt';
const provider = new Provider('https://rpc.mevblocker.io');
// Fetch recent 10 block hashes
const hashes = await fetchBlockHashes(provider, undefined, 10);
console.log(hashes);
// Reorg detection
const a = [{ number: 1, hash: '0x1' }, { number: 2, hash: '0x2' }];
const b = [{ number: 1, hash: '0x1' }, { number: 2, hash: '0x3' }];
console.log(compareBlockHashes(a, b)); // 2
Block Receipts
ts
import { getBlockReceipts } from 'ethers-opt';
// Get all receipts for block 10000000
const provider = /* your Provider */;
const receipts = await getBlockReceipts(provider, 10000000);
console.log(receipts.length);
Browser Provider
ts
import { BrowserProvider } from 'ethers-opt';
// In browser context:
const [browserProvider] = await BrowserProvider.discoverProviders();
const signer = await browserProvider.getSigner('your-address');
console.log(await signer.getAddress());
Events
ts
import { multiQueryFilter } from 'ethers-opt';
// Get all Transfer events for a contract
const events = await multiQueryFilter({
contract: myErc20Instance,
event: 'Transfer'
});
console.log(events.map(e => e.blockNumber));
Fee Estimator
ts
import { formatFeeHistory, getGasPrice } from 'ethers-opt';
const feeHistoryRaw = await provider.send('eth_feeHistory', [10, "latest", [10, 25]]);
const formatted = formatFeeHistory(feeHistoryRaw, 10);
console.log(formatted.baseFeePerGasAvg);
// Extract gas price from fee data
const feeData = await provider.getFeeData();
const gasPrice = getGasPrice(feeData);
console.log(gasPrice);
Multicall
ts
import { multicall, Provider } from 'ethers-opt';
const provider = new Provider('...');
const multicallContract = provider.multicall;
const results = await multicall(multicallContract, [
{ contract: myErc20Instance, name: 'symbol' },
{ contract: myErc20Instance, name: 'decimals' },
{ contract: myErc20Instance, name: 'totalSupply' }
]);
console.log(results); // [ 'TST', 18n, 1000000n ]
OP Stack (Optimism)
ts
import { getL1Fee, OpGasPriceOracle__factory } from 'ethers-opt';
const opOracle = OpGasPriceOracle__factory.connect(
"0x420000000000000000000000000000000000000F",
provider
);
const l1Fee = await getL1Fee(opOracle, {
to: '0x...',
data: '0x'
});
console.log(l1Fee);
Permit
ts
import { permit } from 'ethers-opt';
const sig = await permit(tokenContract, spenderAddress, 123n, Date.now() + 3600);
// Use as input to token.permit function on-chain
console.log(sig);
Proof
ts
import { getProof, getStorageAt } from 'ethers-opt';
const proof = await getProof(provider, tokenAddress, [storageSlot], blockNumber);
console.log(proof);
const storageValue = await getStorageAt(provider, tokenAddress, storageSlot, blockNumber);
console.log(storageValue);
Provider
ts
import { Provider } from 'ethers-opt';
// Static network + Multicall out of the box
const provider = new Provider('https://rpc.mevblocker.io', undefined, { chainId: 1 });
const feeData = await provider.getFeeData();
console.log(feeData);
const receipts = await provider.getBlockReceipts();
console.log(receipts);
Signer
ts
import { ProxySigner } from 'ethers-opt';
// From mnemonic (dev setup)
const signer = ProxySigner.fromMnemonic(
'test test test test test test test test test test test junk',
provider
);
console.log(await signer.getAddress());
// Populate max value tx
const balance = await provider.getBalance(signer.address);
const tx = await signer.populateTransaction({ to: '0x...', value: balance });
console.log(tx);
Trace Block
ts
import { traceBlock, traceTransaction, Provider } from 'ethers-opt';
const provider = new Provider('https://rpc.mevblocker.io');
const traces = await traceBlock(provider, 10000000);
console.log(traces);
const callTrace = await traceTransaction(provider, '0xTxHash...');
console.log(callTrace);
Utils
ts
import { sleep, digest, rBytes, hexToBytes, bytesToHex, createBatchRateConfig } from 'ethers-opt';
await sleep(100); // Wait 100ms
const hash = await digest(new Uint8Array([1,2,3]));
console.log(bytesToHex(hash));
const rand = rBytes(16);
console.log(rand);
console.log(createBatchRateConfig(1000, 10, 0)); // { concurrency: 100, batchSize: 10, delays: 0 }
Price
ts
import { getRateToEth, getChainlinkPrice, Provider } from 'ethers-opt';
const provider = new Provider('https://rpc.mevblocker.io');
// 1inch offchain - ERC20 price to ETH (in wei)
const priceToEth = await getRateToEth(oracle, usdtInstance);
console.log(priceToEth);
// Chainlink price in USD as float
const ethUsd = await getChainlinkPrice(provider, "ETH");
console.log(ethUsd);
ENS
ts
import { Provider, EnsResolver } from 'ethers-opt';
const provider = new Provider('https://rpc.mevblocker.io');
const ensResolver = await EnsResolver.fromName(provider, 'vitalik.eth');
console.log(await ensResolver.getAddress());
const ensAddr = await provider.lookupAddress('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
console.log(ensAddr); // "vitalik.eth" (if reverse record set)