deth
Version:
Ethereum node focused on Developer Experience
76 lines (75 loc) • 3.54 kB
JavaScript
import { toEthersTransaction } from '../../model';
import { BadRequestHttpError } from '../errorHandler';
import { makeHexData, numberToQuantity, quantityToNumber, makeAddress } from '../../primitives';
// NOTE: we don't pass real blockOrTag value here but rather always use latest b/c it's not yet properly implemented
export const rpcExecutorFromCtx = (ctx) => {
return {
web3_clientVersion: () => ctx.cfg.blockchain.chainName,
net_version: () => ctx.cfg.blockchain.chainId.toString(),
// eth
eth_chainId: () => numberToQuantity(ctx.cfg.blockchain.chainId),
eth_gasPrice: () => ctx.chain.getGasPrice(),
eth_getBalance: ([address, blockTag]) => {
return ctx.chain.getBalance(address, 'latest');
},
eth_blockNumber: () => ctx.chain.getBlockNumber(),
eth_getCode: ([address, blockTag]) => ctx.chain.getCode(address, 'latest'),
eth_getTransactionCount: ([address, _blockTag]) => ctx.chain.getTransactionCount(address, 'latest'),
eth_getBlockByNumber: async ([blockTag, includeTransactions]) => {
const block = await ctx.chain.getBlock('latest', false);
return block;
},
// @TODO: as any b/c logs are not implemented properly right now...
eth_getTransactionReceipt: ([txHash]) => ctx.chain.getTransactionReceipt(txHash),
eth_sendRawTransaction: ([signedTx]) => ctx.chain.sendTransaction(signedTx),
eth_sendTransaction: async ([tx]) => {
const { from, nonce: _nonce, gas: _gas, ...restTx } = tx;
const wallet = ctx.walletManager.getWalletForAddress(from);
if (!wallet) {
throw new BadRequestHttpError([`Can't sign tx. ${from} is not unlocked!`]);
}
const nonce = (_nonce !== null && _nonce !== void 0 ? _nonce : (await ctx.chain.getTransactionCount(from, 'latest')));
const gas = (_gas !== null && _gas !== void 0 ? _gas : numberToQuantity(90000));
const signedTx = makeHexData(await wallet.sign(toEthersTransaction({ ...restTx, gas, nonce })));
return ctx.chain.sendTransaction(signedTx);
},
eth_call: ([tx, _blockTag]) => ctx.chain.call(tx, 'latest'),
eth_estimateGas: ([tx]) => ctx.chain.estimateGas(tx),
eth_getStorageAt: async ([address, pos, block]) => {
const result = await ctx.chain.getStorageAt(address, pos, block);
if (result === '0x') {
return '0x00';
}
return result;
},
eth_accounts: () => {
return ctx.walletManager.getWallets().map(w => makeAddress(w.address));
},
// ganache compatibility
evm_increaseTime: ([n]) => {
ctx.chain.skewClock(n);
return numberToQuantity(ctx.chain.options.value.clockSkew);
},
miner_start: () => {
ctx.chain.startAutoMining();
return true;
},
miner_stop: () => {
ctx.chain.stopAutoMining();
return true;
},
evm_mine: async () => {
await ctx.chain.mineBlock();
return numberToQuantity(0);
},
evm_snapshot: async () => {
return numberToQuantity(ctx.chain.makeSnapshot());
},
evm_revert: async ([_n]) => {
const n = quantityToNumber(_n);
console.log(`Reverting to ${n}`);
ctx.chain.revertToSnapshot(n);
return true;
},
};
};