UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

189 lines 9.47 kB
import { isNullish, pick, strip0x, } from '@hyperlane-xyz/utils'; export var EtherscanLikeExplorerApiModule; (function (EtherscanLikeExplorerApiModule) { EtherscanLikeExplorerApiModule["LOGS"] = "logs"; EtherscanLikeExplorerApiModule["CONTRACT"] = "contract"; })(EtherscanLikeExplorerApiModule || (EtherscanLikeExplorerApiModule = {})); export var EtherscanLikeExplorerApiAction; (function (EtherscanLikeExplorerApiAction) { EtherscanLikeExplorerApiAction["GETSOURCECODE"] = "getsourcecode"; EtherscanLikeExplorerApiAction["VERIFY_IMPLEMENTATION"] = "verifysourcecode"; EtherscanLikeExplorerApiAction["VERIFY_PROXY"] = "verifyproxycontract"; EtherscanLikeExplorerApiAction["CHECK_IMPLEMENTATION_STATUS"] = "checkverifystatus"; EtherscanLikeExplorerApiAction["CHECK_PROXY_STATUS"] = "checkproxyverification"; EtherscanLikeExplorerApiAction["GET_CONTRACT_CREATION_CODE"] = "getcontractcreation"; EtherscanLikeExplorerApiAction["GET_LOGS"] = "getLogs"; })(EtherscanLikeExplorerApiAction || (EtherscanLikeExplorerApiAction = {})); export var EtherscanLikeExplorerApiErrors; (function (EtherscanLikeExplorerApiErrors) { EtherscanLikeExplorerApiErrors["ALREADY_VERIFIED"] = "Contract source code already verified"; EtherscanLikeExplorerApiErrors["ALREADY_VERIFIED_ALT"] = "Already Verified"; EtherscanLikeExplorerApiErrors["NOT_VERIFIED"] = "Contract source code not verified"; EtherscanLikeExplorerApiErrors["VERIFICATION_PENDING"] = "Pending in queue"; EtherscanLikeExplorerApiErrors["PROXY_FAILED"] = "A corresponding implementation contract was unfortunately not detected for the proxy address."; EtherscanLikeExplorerApiErrors["BYTECODE_MISMATCH"] = "Fail - Unable to verify. Compiled contract deployment bytecode does NOT match the transaction deployment bytecode."; EtherscanLikeExplorerApiErrors["UNABLE_TO_VERIFY"] = "Fail - Unable to verify"; EtherscanLikeExplorerApiErrors["UNKNOWN_UID"] = "Unknown UID"; EtherscanLikeExplorerApiErrors["NO_RECORD"] = "No records found"; EtherscanLikeExplorerApiErrors["NO_LOGS_FOUND"] = "No logs found"; })(EtherscanLikeExplorerApiErrors || (EtherscanLikeExplorerApiErrors = {})); // see https://etherscan.io/contract-license-types export var ExplorerLicenseType; (function (ExplorerLicenseType) { ExplorerLicenseType["NO_LICENSE"] = "1"; ExplorerLicenseType["UNLICENSED"] = "2"; ExplorerLicenseType["MIT"] = "3"; ExplorerLicenseType["GPL2"] = "4"; ExplorerLicenseType["GPL3"] = "5"; ExplorerLicenseType["LGPL2"] = "6"; ExplorerLicenseType["LGPL3"] = "7"; ExplorerLicenseType["BSD2"] = "8"; ExplorerLicenseType["BSD3"] = "9"; ExplorerLicenseType["MPL2"] = "10"; ExplorerLicenseType["OSL3"] = "11"; ExplorerLicenseType["APACHE2"] = "12"; ExplorerLicenseType["AGPL3"] = "13"; ExplorerLicenseType["BSL"] = "14"; })(ExplorerLicenseType || (ExplorerLicenseType = {})); function formatExplorerUrl({ apiUrl, apiKey }, params) { // hack for Blockscout API urls that in the explorer have the `eth-rpc` path set // as it will cause requests to fail with a not found error const urlObject = new URL(apiUrl.replace('eth-rpc', '')); for (const [key, value] of Object.entries(params)) { if (value !== undefined) { urlObject.searchParams.append(key, value.toString()); } } if (apiKey) { urlObject.searchParams.append('apikey', apiKey); } return urlObject.toString(); } async function handleEtherscanResponse(response) { const body = await response.json(); const explorerUrl = new URL(response.url); // Avoid throwing if no logs are found for the current address if (body.status === '0' && body.message !== EtherscanLikeExplorerApiErrors.NO_RECORD && body.message !== EtherscanLikeExplorerApiErrors.NO_LOGS_FOUND) { throw new Error(`Error while performing request to Etherscan like API at ${explorerUrl.host}: ${body.message} ${body.result}`); } return body.result; } function getFormPostRequestBody(input) { const formParams = new URLSearchParams(Object.entries(input).filter(([_key, value]) => !isNullish(value))); return { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: formParams, }; } export async function tryGetContractDeploymentTransaction(explorerOptions, { contractAddress }) { const options = { module: EtherscanLikeExplorerApiModule.CONTRACT, action: EtherscanLikeExplorerApiAction.GET_CONTRACT_CREATION_CODE, contractaddresses: contractAddress, }; const requestUrl = formatExplorerUrl(explorerOptions, options); const response = await fetch(requestUrl); const [deploymentTx] = await handleEtherscanResponse(response); return deploymentTx; } export async function getContractDeploymentTransaction(explorerOptions, requestOptions) { const deploymentTx = await tryGetContractDeploymentTransaction(explorerOptions, requestOptions); if (!deploymentTx) { throw new Error(`No deployment transaction found for contract ${requestOptions.contractAddress}`); } return deploymentTx; } export async function getLogsFromEtherscanLikeExplorerAPI({ apiUrl, apiKey: apikey }, options) { const data = { module: EtherscanLikeExplorerApiModule.LOGS, action: EtherscanLikeExplorerApiAction.GET_LOGS, address: options.address, fromBlock: options.fromBlock, toBlock: options.toBlock, topic0: options.topic0, }; const requestUrl = formatExplorerUrl({ apiUrl, apiKey: apikey }, data); const response = await fetch(requestUrl); const rawLogs = await handleEtherscanResponse(response); return rawLogs.map((rawLogs) => ({ address: rawLogs.address, blockNumber: Number(rawLogs.blockNumber), data: rawLogs.data, logIndex: Number(rawLogs.logIndex), topics: rawLogs.topics, transactionHash: rawLogs.transactionHash, transactionIndex: Number(rawLogs.transactionIndex), })); } export async function getContractSourceCode(explorerOptions, { contractAddress }) { const options = { action: EtherscanLikeExplorerApiAction.GETSOURCECODE, address: contractAddress, module: EtherscanLikeExplorerApiModule.CONTRACT, }; const requestUrl = formatExplorerUrl(explorerOptions, options); const response = await fetch(requestUrl); const [sourceCodeResults] = await handleEtherscanResponse(response); return sourceCodeResults; } /** * Wrapper function for the `https://api.etherscan.io/v2/api?chainid=1&module=contract&action=verifysourcecode&apikey=...` * endpoint request with the `codeformat` option set to `solidity-standard-json-input` */ export async function verifyContractSourceCodeViaStandardJsonInput(explorerOptions, verificationOptions) { const input = { module: EtherscanLikeExplorerApiModule.CONTRACT, action: EtherscanLikeExplorerApiAction.VERIFY_IMPLEMENTATION, codeformat: 'solidity-standard-json-input', compilerversion: verificationOptions.compilerVersion, contractaddress: verificationOptions.contractAddress, contractname: verificationOptions.contractName, sourceCode: JSON.stringify(verificationOptions.sourceCode), constructorArguements: strip0x(verificationOptions.constructorArguments ?? ''), licenseType: verificationOptions.licenseType, }; if (!isNullish(verificationOptions.zkCompilerVersion)) { input.zksolcversion = verificationOptions.zkCompilerVersion; } const params = pick(input, ['action', 'module']); const requestUrl = formatExplorerUrl(explorerOptions, params); const response = await fetch(requestUrl, getFormPostRequestBody(input)); return handleEtherscanResponse(response); } /** * Wrapper function for the `https://api.etherscan.io/v2/api?chainid=...&module=contract&action=verifyproxycontract&apikey=...` */ export async function verifyProxyContract(explorerOptions, { contractAddress, implementationAddress }) { const input = { action: EtherscanLikeExplorerApiAction.VERIFY_PROXY, module: EtherscanLikeExplorerApiModule.CONTRACT, address: contractAddress, expectedimplementation: implementationAddress, }; const params = pick(input, ['action', 'module']); const requestUrl = formatExplorerUrl(explorerOptions, params); const response = await fetch(requestUrl, getFormPostRequestBody(input)); return handleEtherscanResponse(response); } /** * Wrapper function for the * `https://api.etherscan.io/v2/api?chainid=...&module=contract&action=...&guid=...&apikey=...` * endpoint request with the `action` option set to `checkverifystatus` if `isProxy` is false * or set to `checkproxyverification` if set to true. */ export async function checkContractVerificationStatus(explorerOptions, { isProxy, verificationId }) { const input = { action: isProxy ? EtherscanLikeExplorerApiAction.CHECK_PROXY_STATUS : EtherscanLikeExplorerApiAction.CHECK_IMPLEMENTATION_STATUS, guid: verificationId, module: EtherscanLikeExplorerApiModule.CONTRACT, }; const requestUrl = formatExplorerUrl(explorerOptions, input); const response = await fetch(requestUrl); await handleEtherscanResponse(response); } //# sourceMappingURL=etherscan.js.map