UNPKG

@ensdomains/unruggable-gateways

Version:

Trustless Ethereum Multichain CCIP-Read Gateway

104 lines (103 loc) 3.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LATEST_BLOCK_TAG = exports.MAINNET_BLOCK_SEC = exports.EVM_BLOCKHASH_DEPTH = exports.NULL_CODE_HASH = exports.ABI_CODER = void 0; exports.toUnpaddedHex = toUnpaddedHex; exports.toPaddedHex = toPaddedHex; exports.withResolvers = withResolvers; exports.isBlockTag = isBlockTag; exports.fetchBlock = fetchBlock; exports.fetchBlockFromHash = fetchBlockFromHash; exports.fetchBlockNumber = fetchBlockNumber; exports.fetchBlockTag = fetchBlockTag; exports.isEthersError = isEthersError; exports.isRevert = isRevert; exports.isRPCError = isRPCError; const abi_1 = require("ethers/abi"); const hash_1 = require("ethers/hash"); exports.ABI_CODER = abi_1.AbiCoder.defaultAbiCoder(); // https://adraffy.github.io/keccak.js/test/demo.html#algo=keccak-256&s=&escape=1&encoding=utf8 // "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" exports.NULL_CODE_HASH = (0, hash_1.id)(''); exports.EVM_BLOCKHASH_DEPTH = 256; // TODO: make this a function of Chain exports.MAINNET_BLOCK_SEC = 12; exports.LATEST_BLOCK_TAG = 'latest'; // hex-prefixed w/o zero-padding function toUnpaddedHex(x) { return '0x' + BigInt(x).toString(16); } // hex-prefixed left-pad w/truncation function toPaddedHex(x, width = 32) { const i = x === '0x' ? 0n : BigInt.asUintN(width << 3, BigInt(x)); return '0x' + i.toString(16).padStart(width << 1, '0'); } // manual polyfill: ES2024 function withResolvers() { let resolve; let reject; const promise = new Promise((ful, rej) => { resolve = ful; reject = rej; }); return { promise, resolve, reject }; } function isBlockTag(x) { return typeof x === 'string' && !x.startsWith('0x'); } async function fetchBlock(provider, relBlockTag = exports.LATEST_BLOCK_TAG) { if (!isBlockTag(relBlockTag)) { let i = BigInt(relBlockTag); if (i < 0) i += await fetchBlockNumber(provider); relBlockTag = toUnpaddedHex(i); } const json = await provider.send('eth_getBlockByNumber', [ relBlockTag, false, ]); if (!json) throw new Error(`no block: ${relBlockTag}`); return json; } async function fetchBlockFromHash(provider, blockHash) { const block = await provider.send('eth_getBlockByHash', [blockHash, false]); if (!block) throw new Error(`no blockhash: ${blockHash}`); return block; } // avoid an rpc if possible // use negative (-100) for offset from "latest" (#-100) async function fetchBlockNumber(provider, relBlockTag = exports.LATEST_BLOCK_TAG) { if (relBlockTag === exports.LATEST_BLOCK_TAG) { return BigInt(await provider.send('eth_blockNumber', [])); } else if (isBlockTag(relBlockTag)) { const info = await fetchBlock(provider, relBlockTag); return BigInt(info.number); } else { let i = BigInt(relBlockTag); if (i < 0) i += await fetchBlockNumber(provider); return i; } } // avoid an rpc if possible // convert negative (-100) => absolute (#-100) async function fetchBlockTag(provider, relBlockTag = exports.LATEST_BLOCK_TAG) { return isBlockTag(relBlockTag) ? relBlockTag : fetchBlockNumber(provider, relBlockTag); } function isEthersError(err) { return err instanceof Error && 'code' in err && 'shortMessage' in err; } function isRevert(err) { return isEthersError(err) && err.code === 'CALL_EXCEPTION'; } function isRPCError(err, code) { return (isEthersError(err) && err.error instanceof Object && 'code' in err.error && err.error.code === code); }