@tevm/whatsabi
Version:
Utilities around whatsabi
315 lines (313 loc) • 11.6 kB
JavaScript
import * as chains from 'viem/chains';
import { whatsabi, loaders } from '@shazow/whatsabi';
import { getAddress } from '@tevm/utils';
import { createClient, http } from 'viem';
import { getCode } from 'viem/actions';
// src/contractUriPattern.js
var contractUriPattern = /^evm:\/\/(?<chainId>\d+)\/(?<address>0x[a-fA-F0-9]{40})(\?(?<query>.+))?$/;
var knownChains = {
[]: chains.mainnet,
[]: chains.optimism,
[]: chains.optimismSepolia,
[]: chains.arbitrum,
[]: chains.base,
[]: chains.baseSepolia,
[]: chains.polygon,
[]: chains.zora,
[]: chains.sepolia,
[]: chains.fuseSparknet,
[]: chains.funkiMainnet,
[]: chains.funkiSepolia,
[]: chains.flareTestnet,
[]: chains.evmosTestnet,
[]: chains.defichainEvm,
[]: chains.cyberTestnet,
[]: chains.blastSepolia,
[]: chains.areonNetwork,
[]: chains.arbitrumNova,
[]: chains.zoraTestnet,
[]: chains.zoraSepolia,
[]: chains.yooldoVerse,
[]: chains.taikoJolnir,
[]: chains.skaleNebula,
[]: chains.skaleExorde,
[]: chains.skaleEuropa,
[]: chains.rss3Sepolia,
[]: chains.rootPorcini,
[]: chains.reyaNetwork,
[]: chains.polygonAmoy,
[]: chains.palmTestnet,
[]: chains.neonMainnet,
[]: chains.moonbeamDev,
[]: chains.modeTestnet,
[]: chains.metisGoerli,
[]: chains.liskSepolia,
[]: chains.lineaGoerli,
[]: chains.kavaTestnet,
[]: chains.haqqMainnet,
[]: chains.flowTestnet,
[]: chains.flowMainnet,
[]: chains.ektaTestnet,
[]: chains.bobaSepolia,
[]: chains.bevmMainnet,
[]: chains.beamTestnet,
[]: chains.astarZkyoto,
[]: chains.apexTestnet,
[]: chains.zkLinkNovaSepoliaTestnet,
[]: chains.xdcTestnet,
[]: chains.xaiTestnet,
[]: chains.taikoKatla,
[]: chains.taikoHekla,
[]: chains.skaleTitan,
[]: chains.skaleRazor,
[]: chains.seiTestnet,
[]: chains.pulsechain,
[]: chains.pgnTestnet,
[]: chains.otimDevnet,
[]: chains.neonDevnet,
[]: chains.mevTestnet,
[]: chains.l3xTestnet,
[]: chains.jbcTestnet,
[]: chains.harmonyOne,
[]: chains.eosTestnet,
[]: chains.bxnTestnet,
[]: chains.btrTestnet,
[]: chains.bscTestnet,
[]: chains.bitTorrent,
[]: chains.baseGoerli,
[]: chains.astarZkEVM,
[]: chains.zetachain,
[]: chains.xrSepolia,
[]: chains.x1Testnet,
[]: chains.thaiChain,
[]: chains.shibarium,
[]: chains.seiDevnet,
[]: chains.satoshiVM,
[]: chains.rootstock,
[]: chains.moonriver,
[]: chains.metachain,
[]: chains.localhost,
[]: chains.etherlink,
[]: chains.dogechain,
[]: chains.crossbell,
[]: chains.avalanche,
[]: chains.zhejiang,
[]: chains.wanchain,
[]: chains.songbird,
[]: chains.sapphire,
[]: chains.redstone,
[]: chains.qTestnet,
[]: chains.qMainnet,
[]: chains.nautilus,
[]: chains.filecoin,
[]: chains.edgeware,
[]: chains.edgeless,
[]: chains.darwinia,
[]: chains.ancient8,
[]: chains.zilliqa,
[]: chains.vechain,
[]: chains.syscoin,
[]: chains.stratis,
[]: chains.shimmer,
[]: chains.phoenix,
[]: chains.nexilix,
[]: chains.metalL2,
[]: chains.mandala,
[]: chains.holesky,
[]: chains.hardhat,
[]: chains.fraxtal,
[]: chains.coreDao,
[]: chains.classic,
[]: chains.bahamut,
[]: chains.auroria,
[]: chains.zkSync,
[]: chains.zkFair,
[]: chains.xLayer,
[]: chains.unreal,
[]: chains.taraxa,
[]: chains.scroll,
[]: chains.rollux,
[]: chains.plinga,
[]: chains.merlin,
[]: chains.mantle,
[]: chains.klaytn,
[]: chains.karura,
[]: chains.hedera,
[]: chains.goerli,
[]: chains.gnosis,
[]: chains.fantom,
[]: chains.dchain,
[]: chains.cronos,
[]: chains.chiliz,
[]: chains.bronos,
[]: chains.bitkub,
[]: chains.aurora,
[]: chains.wemix,
[]: chains.tenet,
[]: chains.taiko,
[]: chains.spicy,
[]: chains.ronin,
[]: chains.opBNB,
[]: chains.oasys,
[]: chains.metis,
[]: chains.meter,
[]: chains.manta,
[]: chains.lycan,
[]: chains.lukso,
[]: chains.linea,
[]: chains.kroma,
[]: chains.iotex,
[]: chains.inEVM,
[]: chains.flare,
[]: chains.evmos,
[]: chains.degen,
[]: chains.cyber,
[]: chains.canto,
[]: chains.blast,
[]: chains.astar,
[]: chains.acala,
[]: chains.rss3,
[]: chains.root,
[]: chains.real,
[]: chains.palm,
[]: chains.nexi,
[]: chains.mode,
[]: chains.lyra,
[]: chains.lisk,
[]: chains.kava,
[]: chains.gobi,
[]: chains.fuse,
[]: chains.fibo,
[]: chains.ekta,
[]: chains.crab,
[]: chains.celo,
[]: chains.boba,
[]: chains.beam,
[]: chains.xdc,
[]: chains.xai,
[]: chains.sei,
[]: chains.pgn,
[]: chains.okc,
[]: chains.mev,
[]: chains.l3x,
[]: chains.koi,
[]: chains.kcc,
[]: chains.jbc,
[]: chains.bsc,
[]: chains.ham,
[]: chains.eos,
[]: chains.eon,
[]: chains.dfk,
[]: chains.bxn,
[]: chains.btr,
[]: chains.bob
};
var loadAbi = async ({ address, client, explorerUrl, followProxies, etherscanApiKey }) => {
var _a;
return whatsabi.autoload(address, {
provider: client,
followProxies,
abiLoader: new loaders.MultiABILoader([
new loaders.SourcifyABILoader({
chainId: ((_a = client.chain) == null ? void 0 : _a.id) ?? 1
}),
...explorerUrl !== void 0 ? [
new 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");
const address = 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 = createClient({
transport: 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 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
};
};
export { UnknownChainError, contractUriPattern, knownChains, loadAbi, parseUri, resolveContractUri };
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map