Skip to content

Commit

Permalink
feat: add mirror node contract call and estimate queries
Browse files Browse the repository at this point in the history
Signed-off-by: Ivaylo Nikolov <[email protected]>
  • Loading branch information
ivaylonikolov7 committed Dec 16, 2024
1 parent 089e714 commit d7dbae9
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/query/MirrorNodeContractCallQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import MirrorNodeContractQuery from "./MirrorNodeContractQuery.js";

/**
* @typedef {import("../channel/Channel.js").default} Channel
* @typedef {import("../client/Client.js").default<*, *>} Client
*/
export default class MirrorNodeContractCallQuery extends MirrorNodeContractQuery {
/**
* @returns {Promise<string>}
*/
async execute() {
if (this.callData == null) {
throw new Error("Call data is required.");
}

const API_ENDPOINT = "contracts/call";
const JSON_PAYLOAD = {
data: Buffer.from(this.callData).toString("hex"),
to: this.contractEvmAddress,
estimate: false,
};

console.log(JSON_PAYLOAD);
/**
* @type { { data: { result: string } } }
*/
const mirrorNodeRequest = await this.performMirrorNodeRequest(
API_ENDPOINT,
JSON.stringify(JSON_PAYLOAD),
);
//console.log(mirrorNodeRequest);
/**
* @type {object}
*/
return mirrorNodeRequest.data.result;
}
}
36 changes: 36 additions & 0 deletions src/query/MirrorNodeContractEstimateQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Long from "long";
import MirrorNodeContractQuery from "./MirrorNodeContractQuery.js";

/**
* @typedef {import("../channel/Channel.js").default} Channel
* @typedef {import("../client/Client.js").default<*, *>} Client
*/
export default class MirrorNodeContractCallQuery extends MirrorNodeContractQuery {
/**
* @returns {Promise<Long>}
*/
async execute() {
if (this.callData == null) {
throw new Error("Call data is required.");
}

const JSON_PAYLOAD = {
data: Buffer.from(this.callData).toString("hex"),
from: this.senderEvmAddress,
to: this.contractEvmAddress,
estimate: true,
value: this.value,
};

/**
* @type {{data: {result: string}}}
*/
const mirrorNodeRequest = await this.performMirrorNodeRequest(
"contracts/call",
JSON.stringify(JSON_PAYLOAD),
);

console.log(Number(mirrorNodeRequest.data.result));
return Long.fromNumber(Number(mirrorNodeRequest.data.result));
}
}
187 changes: 187 additions & 0 deletions src/query/MirrorNodeContractQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import axios from "axios";
import { ContractFunctionParameters } from "../exports.js";

/**
* @typedef {import("../contract/ContractId").default} ContractId
* @typedef {import("../account/AccountId").default} AccountId
* @typedef {import("../client/Client.js").default<*, *>} Client
* @typedef {import("axios").AxiosResponse} AxiosResponse
*
*/
export default class MirrorNodeContractQuery {
constructor() {
this._contractId = null;
this._contractEvmAddress = null;
this._sender = null;
this._senderEvmAddress = null;
this._functionName = null;
this._functionParameters = null;
this._value = null;
this._gasLimit = null;
this._gasPrice = null;
this._blockNumber = null;
}

/**
*
* @param {ContractId} contractId
* @returns
*/
setContractId(contractId) {
this._contractId = contractId;
return this;
}

/**
* @param {AccountId} sender
* @returns
*/
setSender(sender) {
this._sender = sender;
return this;
}

/**
*
* @param {string} name
* @param {ContractFunctionParameters} functionParameters
* @returns
*/
setFunction(name, functionParameters) {
this._functionParameters =
functionParameters != null
? functionParameters._build(name)
: new ContractFunctionParameters()._build(name);

return this;
}

/**
* @param {Long} value
* @returns
*/
setValue(value) {
this._value = value;
return this;
}

/**
* @param {Long} gasLimit
* @returns
*/
setGasLimit(gasLimit) {
this._gasLimit = gasLimit;
return this;
}

/**
* @param {Long} gasPrice
* @returns
*/
setGasPrice(gasPrice) {
this._gasPrice = gasPrice;
return this;
}

/**
* @param {Long} blockNumber
* @returns
*/
setBlockNumber(blockNumber) {
this._blockNumber = blockNumber;
return this;
}

/**
* @returns {ContractId?}
*/
get contractId() {
return this._contractId;
}

/**
* @returns {string}
*/
get contractEvmAddress() {
const solidityAddress = this._contractId?.toSolidityAddress();
if (solidityAddress == null) {
throw new Error("Contract ID is not set");
}
return solidityAddress;
}

/**
* @returns {AccountId?}
*/
get sender() {
return this._sender;
}

/**
* @returns {string?}
*/
get senderEvmAddress() {
const solidityAddress = this._sender?.toSolidityAddress();
if (solidityAddress == null) {
throw new Error("Sender is not set");
}
return solidityAddress;
}

/**
* @returns {Uint8Array | null | undefined}
*/
get callData() {
return this._functionParameters;
}

/**
* @returns {Long?}
*/
get value() {
return this._value;
}

/**
* @returns {Long?}
*/
get gasLimit() {
return this._gasLimit;
}

/**
* @returns {Long?}
*/
get gasPrice() {
return this._gasPrice;
}

/**
* @returns {Long?}
*/
get blockNumber() {
return this._blockNumber;
}

/**
*
* @param {string} apiEndpoint
* @param {string} jsonPayload
* @returns {Promise<AxiosResponse>}
*/
async performMirrorNodeRequest(apiEndpoint, jsonPayload) {
if (this.contractId == null) {
throw new Error("Contract ID is not set");
}

const MIRROR_NETWORK_ADDRESS =
"https://testnet.mirrornode.hedera.com/api/v1/" + apiEndpoint;

let result = await axios.post(MIRROR_NETWORK_ADDRESS, jsonPayload, {
headers: {
"Content-Type": "application/json",
},
});
return result;
}
}

0 comments on commit d7dbae9

Please sign in to comment.