@tevm/whatsabi
Version:
Utilities around whatsabi
342 lines (337 loc) • 16.6 kB
JavaScript
'use strict';
var chains = require('viem/chains');
var whatsabi = require('@shazow/whatsabi');
var utils = require('@tevm/utils');
var viem = require('viem');
var actions = require('viem/actions');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var chains__namespace = /*#__PURE__*/_interopNamespace(chains);
// src/contractUriPattern.js
var contractUriPattern = /^evm:\/\/(?<chainId>\d+)\/(?<address>0x[a-fA-F0-9]{40})(\?(?<query>.+))?$/;
var knownChains = {
[]: chains__namespace.mainnet,
[]: chains__namespace.optimism,
[]: chains__namespace.optimismSepolia,
[]: chains__namespace.arbitrum,
[]: chains__namespace.base,
[]: chains__namespace.baseSepolia,
[]: chains__namespace.polygon,
[]: chains__namespace.zora,
[]: chains__namespace.sepolia,
[]: chains__namespace.fuseSparknet,
[]: chains__namespace.funkiMainnet,
[]: chains__namespace.funkiSepolia,
[]: chains__namespace.flareTestnet,
[]: chains__namespace.evmosTestnet,
[]: chains__namespace.defichainEvm,
[]: chains__namespace.cyberTestnet,
[]: chains__namespace.blastSepolia,
[]: chains__namespace.areonNetwork,
[]: chains__namespace.arbitrumNova,
[]: chains__namespace.zoraTestnet,
[]: chains__namespace.zoraSepolia,
[]: chains__namespace.yooldoVerse,
[]: chains__namespace.taikoJolnir,
[]: chains__namespace.skaleNebula,
[]: chains__namespace.skaleExorde,
[]: chains__namespace.skaleEuropa,
[]: chains__namespace.rss3Sepolia,
[]: chains__namespace.rootPorcini,
[]: chains__namespace.reyaNetwork,
[]: chains__namespace.polygonAmoy,
[]: chains__namespace.palmTestnet,
[]: chains__namespace.neonMainnet,
[]: chains__namespace.moonbeamDev,
[]: chains__namespace.modeTestnet,
[]: chains__namespace.metisGoerli,
[]: chains__namespace.liskSepolia,
[]: chains__namespace.lineaGoerli,
[]: chains__namespace.kavaTestnet,
[]: chains__namespace.haqqMainnet,
[]: chains__namespace.flowTestnet,
[]: chains__namespace.flowMainnet,
[]: chains__namespace.ektaTestnet,
[]: chains__namespace.bobaSepolia,
[]: chains__namespace.bevmMainnet,
[]: chains__namespace.beamTestnet,
[]: chains__namespace.astarZkyoto,
[]: chains__namespace.apexTestnet,
[]: chains__namespace.zkLinkNovaSepoliaTestnet,
[]: chains__namespace.xdcTestnet,
[]: chains__namespace.xaiTestnet,
[]: chains__namespace.taikoKatla,
[]: chains__namespace.taikoHekla,
[]: chains__namespace.skaleTitan,
[]: chains__namespace.skaleRazor,
[]: chains__namespace.seiTestnet,
[]: chains__namespace.pulsechain,
[]: chains__namespace.pgnTestnet,
[]: chains__namespace.otimDevnet,
[]: chains__namespace.neonDevnet,
[]: chains__namespace.mevTestnet,
[]: chains__namespace.l3xTestnet,
[]: chains__namespace.jbcTestnet,
[]: chains__namespace.harmonyOne,
[]: chains__namespace.eosTestnet,
[]: chains__namespace.bxnTestnet,
[]: chains__namespace.btrTestnet,
[]: chains__namespace.bscTestnet,
[]: chains__namespace.bitTorrent,
[]: chains__namespace.baseGoerli,
[]: chains__namespace.astarZkEVM,
[]: chains__namespace.zetachain,
[]: chains__namespace.xrSepolia,
[]: chains__namespace.x1Testnet,
[]: chains__namespace.thaiChain,
[]: chains__namespace.shibarium,
[]: chains__namespace.seiDevnet,
[]: chains__namespace.satoshiVM,
[]: chains__namespace.rootstock,
[]: chains__namespace.moonriver,
[]: chains__namespace.metachain,
[]: chains__namespace.localhost,
[]: chains__namespace.etherlink,
[]: chains__namespace.dogechain,
[]: chains__namespace.crossbell,
[]: chains__namespace.avalanche,
[]: chains__namespace.zhejiang,
[]: chains__namespace.wanchain,
[]: chains__namespace.songbird,
[]: chains__namespace.sapphire,
[]: chains__namespace.redstone,
[]: chains__namespace.qTestnet,
[]: chains__namespace.qMainnet,
[]: chains__namespace.nautilus,
[]: chains__namespace.filecoin,
[]: chains__namespace.edgeware,
[]: chains__namespace.edgeless,
[]: chains__namespace.darwinia,
[]: chains__namespace.ancient8,
[]: chains__namespace.zilliqa,
[]: chains__namespace.vechain,
[]: chains__namespace.syscoin,
[]: chains__namespace.stratis,
[]: chains__namespace.shimmer,
[]: chains__namespace.phoenix,
[]: chains__namespace.nexilix,
[]: chains__namespace.metalL2,
[]: chains__namespace.mandala,
[]: chains__namespace.holesky,
[]: chains__namespace.hardhat,
[]: chains__namespace.fraxtal,
[]: chains__namespace.coreDao,
[]: chains__namespace.classic,
[]: chains__namespace.bahamut,
[]: chains__namespace.auroria,
[]: chains__namespace.zkSync,
[]: chains__namespace.zkFair,
[]: chains__namespace.xLayer,
[]: chains__namespace.unreal,
[]: chains__namespace.taraxa,
[]: chains__namespace.scroll,
[]: chains__namespace.rollux,
[]: chains__namespace.plinga,
[]: chains__namespace.merlin,
[]: chains__namespace.mantle,
[]: chains__namespace.klaytn,
[]: chains__namespace.karura,
[]: chains__namespace.hedera,
[]: chains__namespace.goerli,
[]: chains__namespace.gnosis,
[]: chains__namespace.fantom,
[]: chains__namespace.dchain,
[]: chains__namespace.cronos,
[]: chains__namespace.chiliz,
[]: chains__namespace.bronos,
[]: chains__namespace.bitkub,
[]: chains__namespace.aurora,
[]: chains__namespace.wemix,
[]: chains__namespace.tenet,
[]: chains__namespace.taiko,
[]: chains__namespace.spicy,
[]: chains__namespace.ronin,
[]: chains__namespace.opBNB,
[]: chains__namespace.oasys,
[]: chains__namespace.metis,
[]: chains__namespace.meter,
[]: chains__namespace.manta,
[]: chains__namespace.lycan,
[]: chains__namespace.lukso,
[]: chains__namespace.linea,
[]: chains__namespace.kroma,
[]: chains__namespace.iotex,
[]: chains__namespace.inEVM,
[]: chains__namespace.flare,
[]: chains__namespace.evmos,
[]: chains__namespace.degen,
[]: chains__namespace.cyber,
[]: chains__namespace.canto,
[]: chains__namespace.blast,
[]: chains__namespace.astar,
[]: chains__namespace.acala,
[]: chains__namespace.rss3,
[]: chains__namespace.root,
[]: chains__namespace.real,
[]: chains__namespace.palm,
[]: chains__namespace.nexi,
[]: chains__namespace.mode,
[]: chains__namespace.lyra,
[]: chains__namespace.lisk,
[]: chains__namespace.kava,
[]: chains__namespace.gobi,
[]: chains__namespace.fuse,
[]: chains__namespace.fibo,
[]: chains__namespace.ekta,
[]: chains__namespace.crab,
[]: chains__namespace.celo,
[]: chains__namespace.boba,
[]: chains__namespace.beam,
[]: chains__namespace.xdc,
[]: chains__namespace.xai,
[]: chains__namespace.sei,
[]: chains__namespace.pgn,
[]: chains__namespace.okc,
[]: chains__namespace.mev,
[]: chains__namespace.l3x,
[]: chains__namespace.koi,
[]: chains__namespace.kcc,
[]: chains__namespace.jbc,
[]: chains__namespace.bsc,
[]: chains__namespace.ham,
[]: chains__namespace.eos,
[]: chains__namespace.eon,
[]: chains__namespace.dfk,
[]: chains__namespace.bxn,
[]: chains__namespace.btr,
[]: chains__namespace.bob
};
var loadAbi = async ({ address, client, explorerUrl, followProxies, etherscanApiKey }) => {
var _a;
return whatsabi.whatsabi.autoload(address, {
provider: client,
followProxies,
abiLoader: new whatsabi.loaders.MultiABILoader([
new whatsabi.loaders.SourcifyABILoader({
chainId: ((_a = client.chain) == null ? void 0 : _a.id) ?? 1
}),
...explorerUrl !== void 0 ? [
new whatsabi.loaders.EtherscanABILoader({
baseURL: explorerUrl,
...etherscanApiKey !== void 0 ? { apiKey: etherscanApiKey } : {}
})
] : []
])
});
};
var parseUri = (uri) => {
var _a, _b, _c;
const match = contractUriPattern.exec(uri);
if (!match) {
return void 0;
}
const chainId = Number.parseInt(((_a = match.groups) == null ? void 0 : _a["chainId"]) ?? "1", 10);
const address = utils.getAddress(
/** @type {string}*/
(_b = match.groups) == null ? void 0 : _b["address"]
);
const query = (_c = match.groups) == null ? void 0 : _c["query"];
const params = new URLSearchParams(query || "");
return {
chainId: (
/** @type {import('./KnownChainIds.js').KnownChainIds}*/
chainId
),
address,
rpcUrl: params.get("rpcUrl") || void 0,
etherscanApiKey: params.get("etherscanApiKey") || void 0,
etherscanBaseUrl: params.get("etherscanBaseUrl") || void 0,
followProxies: params.get("followProxies") === "true" || void 0
};
};
var UnknownChainError = class extends Error {
/**
* @type {'UnknownChainError'}
* @override
*/
name = "UnknownChainError";
/**
* @type {'UnknownChainError'}
*/
_tag = "UnknownChainError";
/**
* @param {number} chainId
*/
constructor(chainId) {
super(
`Unknown chain ID: ${chainId}. No default rpc known. Please pass in a valid rpc url as a query string \`?rpcUrl=\${rpcUrl}\` or open a pr to viem to add your chain to viem/chains`
);
}
};
var resolveContractUri = async (contractUri, config) => {
var _a;
console.log("todo config", config);
const parsedUri = parseUri(contractUri);
if (!parsedUri) {
return void 0;
}
const chain = knownChains[parsedUri.chainId];
if (!chain && !parsedUri.rpcUrl) {
throw new UnknownChainError(parsedUri.chainId);
}
const client = viem.createClient({
transport: viem.http(parsedUri.rpcUrl),
chain
});
const explorerUrl = parsedUri.etherscanBaseUrl ?? ((_a = chain.blockExplorers) == null ? void 0 : _a.default.url);
const whatsabiResult = await loadAbi({
client,
explorerUrl,
address: parsedUri.address,
followProxies: parsedUri.followProxies ?? true,
etherscanApiKey: parsedUri.etherscanApiKey
});
const deployedBytecode = await actions.getCode(client, {
address: (
/** @type {import('@tevm/utils').Address}*/
whatsabiResult.address
)
});
if (!deployedBytecode) {
throw new Error("Could not fetch deployed bytecode");
}
return {
abi: (
/** @type {any}*/
whatsabiResult.abi
),
address: parsedUri.address,
deployedBytecode
// TODO we want to represent proxies in some way like listing the resolved addy
// ...{resolvedAddress: whatsabiResult.address},
// TODO if we can get a verified contract we should compile it with solc and return solc output too
};
};
exports.UnknownChainError = UnknownChainError;
exports.contractUriPattern = contractUriPattern;
exports.knownChains = knownChains;
exports.loadAbi = loadAbi;
exports.parseUri = parseUri;
exports.resolveContractUri = resolveContractUri;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map