UNPKG

@hashgraphonline/standards-sdk

Version:

The Hashgraph Online Standards SDK provides a complete implementation of the Hashgraph Consensus Standards (HCS), giving developers all the tools needed to build applications on Hedera.

178 lines (177 loc) • 5.48 kB
import { ContractId, AccountId } from "@hashgraph/sdk"; import { ethers } from "ethers"; import { Logger } from "./standards-sdk.es22.js"; class MapCache { constructor() { this.cache = /* @__PURE__ */ new Map(); } get(key) { return this.cache.get(key); } set(key, value) { this.cache.set(key, value); } delete(key) { this.cache.delete(key); } clear() { this.cache.clear(); } } class EVMBridge { constructor(network = "mainnet-public", mirrorNodeUrl = `mirrornode.hedera.com/api/v1/contracts/call`, cache) { this.network = network; this.mirrorNodeUrl = mirrorNodeUrl; this.cache = cache || new MapCache(); this.logger = Logger.getInstance({ module: "EVMBridge" }); } async executeCommands(evmConfigs, initialState = {}) { let stateData = { ...initialState }; const results = {}; for (const config of evmConfigs) { const cacheKey = `${config.c.contractAddress}-${config.c.abi.name}`; const cachedResult = await this.cache.get(cacheKey); if (cachedResult) { results[config.c.abi.name] = JSON.parse(cachedResult); Object.assign(stateData, results[config.c.abi.name]); continue; } try { const iface = new ethers.Interface([ { ...config.c.abi } ]); const command = iface.encodeFunctionData(config.c.abi.name); const contractId = ContractId.fromSolidityAddress( config.c.contractAddress ); const result = await this.readFromMirrorNode( command, AccountId.fromString("0.0.800"), contractId ); this.logger.info( `Result for ${config.c.contractAddress}:`, result?.result ); if (!result?.result) { this.logger.warn( `Failed to get result from mirror node for ${config.c.contractAddress}` ); results[config.c.abi.name] = "0"; Object.assign(stateData, results[config.c.abi.name]); continue; } const decodedResult = iface?.decodeFunctionResult( config.c.abi.name, result.result ); let processedResult = { values: [] // Initialize array for values }; if (decodedResult) { config.c.abi.outputs?.forEach((output, idx) => { const value = decodedResult[idx]; const formattedValue = formatValue(value, output.type); processedResult.values.push(formattedValue); if (output.name) { processedResult[output.name] = formattedValue; } }); } await this.cache.set(cacheKey, JSON.stringify(processedResult)); results[config.c.abi.name] = processedResult; stateData[config.c.abi.name] = processedResult; } catch (error) { this.logger.error( `Error executing command for ${config.c.contractAddress}:`, error ); results[config.c.abi.name] = "0"; Object.assign(stateData, results[config.c.abi.name]); } } return { results, stateData }; } async executeCommand(evmConfig, stateData = {}) { const { results, stateData: newStateData } = await this.executeCommands( [evmConfig], stateData ); return { result: results[evmConfig.c.abi.name], stateData: newStateData }; } async readFromMirrorNode(command, from, to) { try { const toAddress = to.toSolidityAddress(); const fromAddress = from.toSolidityAddress(); const response = await fetch( `https://${this.network}.${this.mirrorNodeUrl}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ block: "latest", data: command, estimate: false, gas: 3e5, gasPrice: 1e8, from: fromAddress.startsWith("0x") ? fromAddress : `0x${fromAddress}`, to: toAddress?.startsWith("0x") ? toAddress : `0x${toAddress}`, value: 0 }) } ); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { this.logger.error("Error reading from mirror node:", error); return null; } } // Add method to clear cache if needed async clearCache() { await this.cache.clear(); } // Add method to remove specific cache entry async clearCacheForContract(contractAddress, functionName) { await this.cache.delete(`${contractAddress}-${functionName}`); } // Method to set log level for this bridge instance setLogLevel(level) { this.logger.setLogLevel(level); } } function formatValue(value, type) { if (value === null || value === void 0) { return "0"; } if (value._isBigNumber) { return value.toString(); } if (type.startsWith("uint") || type.startsWith("int")) { return String(value); } else if (type === "bool") { return value ? "true" : "false"; } else if (type === "string") { return value; } else if (type === "address") { return String(value).toLowerCase(); } else if (type.endsWith("[]")) { return Array.isArray(value) ? value.map((v) => String(v)) : []; } else { return String(value); } } export { EVMBridge }; //# sourceMappingURL=standards-sdk.es4.js.map