UNPKG

blockchain-api

Version:

API utilities for interacting with the Exatechl2 blockchain

220 lines (218 loc) 8.79 kB
"use strict"; /** * Contract Operations */ Object.defineProperty(exports, "__esModule", { value: true }); exports.getContractInfo = getContractInfo; exports.isContractVerified = isContractVerified; exports.getContractAbi = getContractAbi; exports.findValidContracts = findValidContracts; const rpc_1 = require("../../core/rpc"); const explorerApi_1 = require("../../core/explorerApi"); const transactions_1 = require("../transactions/transactions"); const blocks_1 = require("../blocks/blocks"); const formatters_1 = require("../../utils/formatters"); const registry_1 = require("../../utils/registry"); const contract_utils_1 = require("./contract-utils"); const logger_1 = require("../../utils/logger"); const initializeSystemContracts = () => { const systemContracts = [ { address: '0x00000000000000000000000000000000000a4b05', name: 'Core System Contract' } ]; systemContracts.forEach(contract => { (0, registry_1.registerSystemContract)(contract.address, contract.name); }); }; initializeSystemContracts(); /** * @param {string} address * @returns {Promise<ContractInfo>} */ async function getContractInfo(address) { try { const isContractAddress = await (0, contract_utils_1.checkIsContract)(address); if (!isContractAddress) { throw new Error(`Address ${address} is not a contract`); } const bytecode = await (0, contract_utils_1.getContractBytecode)(address); const balance = await (0, rpc_1.callRpc)('eth_getBalance', [address, 'latest']); if ((0, contract_utils_1.isSystemContract)(address.toLowerCase())) { return { address, bytecode, creator: "System Contract", creationTx: null, creationTimestamp: null, balance, isVerified: false }; } let creator = null; let creationTx = null; let creationTimestamp = null; let isVerified = false; try { const contractFromExplorer = await (0, explorerApi_1.callExplorerApi)(`contracts/${address}`); if (contractFromExplorer && contractFromExplorer.data) { const contractData = contractFromExplorer.data; creator = contractData.creator_address || null; creationTx = contractData.creation_transaction || null; creationTimestamp = contractData.creation_timestamp || null; isVerified = contractData.is_verified || false; logger_1.logger.debug(`Got contract info from Explorer DB for ${address}`); } } catch (e) { logger_1.logger.warn(`Could not fetch contract info from Explorer DB: ${e.message}`); } return { address, bytecode, creator, creationTx, creationTimestamp, balance, isVerified }; } catch (error) { logger_1.logger.error('Error getting contract info:', error); throw error; } } /** * * @param {string} address * @returns {Promise<boolean>} */ async function isContractVerified(address) { try { const isContractAddress = await (0, contract_utils_1.checkIsContract)(address); if (!isContractAddress) { return false; } try { const contractFromExplorer = await (0, explorerApi_1.callExplorerApi)(`contracts/${address}`); if (contractFromExplorer && contractFromExplorer.data) { return contractFromExplorer.data.is_verified || false; } } catch (e) { logger_1.logger.warn(`Could not fetch verification status from Explorer DB: ${e}`); } return false; } catch (error) { logger_1.logger.error('Error checking contract verification:', error); return false; } } /** * * @param {string} address * @returns {Promise<object | null>} */ async function getContractAbi(address) { try { const isVerified = await isContractVerified(address); if (!isVerified) { return null; } try { const abiFromExplorer = await (0, explorerApi_1.callExplorerApi)(`contracts/${address}/abi`); if (abiFromExplorer && abiFromExplorer.data && abiFromExplorer.data.abi) { return JSON.parse(abiFromExplorer.data.abi); } } catch (e) { logger_1.logger.warn(`Could not fetch ABI from Explorer DB: ${e}`); } return null; } catch (error) { logger_1.logger.error('Error getting contract ABI:', error); return null; } } /** * * @param {number} maxResults * @param {number} maxBlocks * @returns {Promise<string[]>} */ async function findValidContracts(maxResults = 5, maxBlocks = 10) { try { const latestBlockHex = await (0, blocks_1.getLatestBlockNumber)(); const latestBlock = (0, formatters_1.parseHexToDecimal)(latestBlockHex); const contractAddresses = []; const processedAddresses = new Set(); for (let i = 0; i < maxBlocks; i++) { if (contractAddresses.length >= maxResults) { break; } const blockNumber = latestBlock - i; if (blockNumber < 0) break; try { const block = await (0, blocks_1.getBlockByNumber)(blockNumber, true); if (block && block.transactions && Array.isArray(block.transactions)) { const contractCreations = block.transactions .filter(tx => (0, contract_utils_1.isTransactionObject)(tx) && !tx.to); for (const tx of contractCreations) { if ((0, contract_utils_1.isTransactionObject)(tx)) { try { const receipt = await (0, transactions_1.getTransactionReceipt)(tx.hash); if (receipt && receipt.contractAddress && !processedAddresses.has(receipt.contractAddress)) { const isContract = await (0, contract_utils_1.checkIsContract)(receipt.contractAddress); if (isContract) { contractAddresses.push(receipt.contractAddress); processedAddresses.add(receipt.contractAddress); if (contractAddresses.length >= maxResults) { break; } } } } catch (e) { logger_1.logger.warn(`Error processing transaction ${tx.hash}:`, e); } } } if (contractAddresses.length < maxResults) { const contractInteractions = block.transactions .filter(tx => (0, contract_utils_1.isTransactionObject)(tx) && tx.to); for (const tx of contractInteractions) { if ((0, contract_utils_1.isTransactionObject)(tx) && tx.to) { if (processedAddresses.has(tx.to)) { continue; } try { const isContract = await (0, contract_utils_1.checkIsContract)(tx.to); if (isContract) { contractAddresses.push(tx.to); processedAddresses.add(tx.to); if (contractAddresses.length >= maxResults) { break; } } } catch (e) { logger_1.logger.warn(`Error checking if address is contract ${tx.to}:`, e); } } } } } } catch (e) { logger_1.logger.warn(`Error processing block ${blockNumber}:`, e); continue; } } return contractAddresses; } catch (error) { logger_1.logger.error('Error finding valid contracts:', error); return []; } }