@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
JavaScript
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