From 489de75f9e60aa31b471243a0e268f9747b342af Mon Sep 17 00:00:00 2001 From: Ivaylo Nikolov Date: Tue, 17 Dec 2024 01:38:01 +0200 Subject: [PATCH] test: add integration and unit tests Signed-off-by: Ivaylo Nikolov --- .../MirrorNodeContractCallQuery.js | 43 +++++++ .../MirrorNodeContractEstimateQuery.js | 43 +++++++ .../client/BaseIntegrationTestEnv.js | 20 ++-- .../client/TestnetIntegrationTestEnv.js | 4 +- test/unit/MirrorNodeContractCallQuery.js | 28 +++++ test/unit/MirrorNodeContractEstimateQuery.js | 31 +++++ test/unit/MirrorNodeContractQuery.js | 111 ++++++++++++++++++ 7 files changed, 267 insertions(+), 13 deletions(-) create mode 100644 test/integration/MirrorNodeContractCallQuery.js create mode 100644 test/integration/MirrorNodeContractEstimateQuery.js create mode 100644 test/unit/MirrorNodeContractCallQuery.js create mode 100644 test/unit/MirrorNodeContractEstimateQuery.js create mode 100644 test/unit/MirrorNodeContractQuery.js diff --git a/test/integration/MirrorNodeContractCallQuery.js b/test/integration/MirrorNodeContractCallQuery.js new file mode 100644 index 000000000..733cb5498 --- /dev/null +++ b/test/integration/MirrorNodeContractCallQuery.js @@ -0,0 +1,43 @@ +import { setTimeout } from "timers/promises"; +import { + MirrorNodeContractCallQuery, + ContractCreateTransaction, + FileCreateTransaction, + ContractFunctionParameters, +} from "../../src/exports.js"; +import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; + +describe("MirrorNodeContractCallQuery", function () { + let env; + + beforeEach(async function () { + env = await IntegrationTestEnv.new(); + }); + + it("should get contract message", async function () { + const BYTECODE = + "60806040526040518060400160405280600581526020017f68656c6c6f0000000000000000000000000000000000000000000000000000008152505f90816100479190610293565b50348015610053575f80fd5b50610362565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806100d457607f821691505b6020821081036100e7576100e6610090565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026101497fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261010e565b610153868361010e565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61019761019261018d8461016b565b610174565b61016b565b9050919050565b5f819050919050565b6101b08361017d565b6101c46101bc8261019e565b84845461011a565b825550505050565b5f90565b6101d86101cc565b6101e38184846101a7565b505050565b5b81811015610206576101fb5f826101d0565b6001810190506101e9565b5050565b601f82111561024b5761021c816100ed565b610225846100ff565b81016020851015610234578190505b610248610240856100ff565b8301826101e8565b50505b505050565b5f82821c905092915050565b5f61026b5f1984600802610250565b1980831691505092915050565b5f610283838361025c565b9150826002028217905092915050565b61029c82610059565b67ffffffffffffffff8111156102b5576102b4610063565b5b6102bf82546100bd565b6102ca82828561020a565b5f60209050601f8311600181146102fb575f84156102e9578287015190505b6102f38582610278565b86555061035a565b601f198416610309866100ed565b5f5b828110156103305784890151825560018201915060208501945060208101905061030b565b8683101561034d5784890151610349601f89168261025c565b8355505b6001600288020188555050505b505050505050565b6102178061036f5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063ce6d41de1461002d575b5f80fd5b61003561004b565b6040516100429190610164565b60405180910390f35b60605f8054610059906101b1565b80601f0160208091040260200160405190810160405280929190818152602001828054610085906101b1565b80156100d05780601f106100a7576101008083540402835291602001916100d0565b820191905f5260205f20905b8154815290600101906020018083116100b357829003601f168201915b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101115780820151818401526020810190506100f6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610136826100da565b61014081856100e4565b93506101508185602086016100f4565b6101598161011c565b840191505092915050565b5f6020820190508181035f83015261017c818461012c565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806101c857607f821691505b6020821081036101db576101da610184565b5b5091905056fea26469706673582212202a86c27939bfab6d4a2c61ebbf096d8424e17e22dfdd42320f6e2654863581e964736f6c634300081a0033"; + const { fileId } = await ( + await new FileCreateTransaction() + .setContents(BYTECODE) + .execute(env.client) + ).getReceipt(env.client); + + const { contractId } = await ( + await new ContractCreateTransaction() + .setBytecodeFileId(fileId) + .setGas(200000) + .execute(env.client) + ).getReceipt(env.client); + + // wait 5 seconds for MN to update + await setTimeout(10000); + + const result = await new MirrorNodeContractCallQuery() + .setContractId(contractId) + .setBlockNumber("latest") + .setFunction("getMessage", new ContractFunctionParameters()) + .execute(); + expect(result).to.not.be.null; + }); +}); diff --git a/test/integration/MirrorNodeContractEstimateQuery.js b/test/integration/MirrorNodeContractEstimateQuery.js new file mode 100644 index 000000000..733cb5498 --- /dev/null +++ b/test/integration/MirrorNodeContractEstimateQuery.js @@ -0,0 +1,43 @@ +import { setTimeout } from "timers/promises"; +import { + MirrorNodeContractCallQuery, + ContractCreateTransaction, + FileCreateTransaction, + ContractFunctionParameters, +} from "../../src/exports.js"; +import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; + +describe("MirrorNodeContractCallQuery", function () { + let env; + + beforeEach(async function () { + env = await IntegrationTestEnv.new(); + }); + + it("should get contract message", async function () { + const BYTECODE = + "60806040526040518060400160405280600581526020017f68656c6c6f0000000000000000000000000000000000000000000000000000008152505f90816100479190610293565b50348015610053575f80fd5b50610362565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806100d457607f821691505b6020821081036100e7576100e6610090565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026101497fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261010e565b610153868361010e565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61019761019261018d8461016b565b610174565b61016b565b9050919050565b5f819050919050565b6101b08361017d565b6101c46101bc8261019e565b84845461011a565b825550505050565b5f90565b6101d86101cc565b6101e38184846101a7565b505050565b5b81811015610206576101fb5f826101d0565b6001810190506101e9565b5050565b601f82111561024b5761021c816100ed565b610225846100ff565b81016020851015610234578190505b610248610240856100ff565b8301826101e8565b50505b505050565b5f82821c905092915050565b5f61026b5f1984600802610250565b1980831691505092915050565b5f610283838361025c565b9150826002028217905092915050565b61029c82610059565b67ffffffffffffffff8111156102b5576102b4610063565b5b6102bf82546100bd565b6102ca82828561020a565b5f60209050601f8311600181146102fb575f84156102e9578287015190505b6102f38582610278565b86555061035a565b601f198416610309866100ed565b5f5b828110156103305784890151825560018201915060208501945060208101905061030b565b8683101561034d5784890151610349601f89168261025c565b8355505b6001600288020188555050505b505050505050565b6102178061036f5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063ce6d41de1461002d575b5f80fd5b61003561004b565b6040516100429190610164565b60405180910390f35b60605f8054610059906101b1565b80601f0160208091040260200160405190810160405280929190818152602001828054610085906101b1565b80156100d05780601f106100a7576101008083540402835291602001916100d0565b820191905f5260205f20905b8154815290600101906020018083116100b357829003601f168201915b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101115780820151818401526020810190506100f6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610136826100da565b61014081856100e4565b93506101508185602086016100f4565b6101598161011c565b840191505092915050565b5f6020820190508181035f83015261017c818461012c565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806101c857607f821691505b6020821081036101db576101da610184565b5b5091905056fea26469706673582212202a86c27939bfab6d4a2c61ebbf096d8424e17e22dfdd42320f6e2654863581e964736f6c634300081a0033"; + const { fileId } = await ( + await new FileCreateTransaction() + .setContents(BYTECODE) + .execute(env.client) + ).getReceipt(env.client); + + const { contractId } = await ( + await new ContractCreateTransaction() + .setBytecodeFileId(fileId) + .setGas(200000) + .execute(env.client) + ).getReceipt(env.client); + + // wait 5 seconds for MN to update + await setTimeout(10000); + + const result = await new MirrorNodeContractCallQuery() + .setContractId(contractId) + .setBlockNumber("latest") + .setFunction("getMessage", new ContractFunctionParameters()) + .execute(); + expect(result).to.not.be.null; + }); +}); diff --git a/test/integration/client/BaseIntegrationTestEnv.js b/test/integration/client/BaseIntegrationTestEnv.js index 723d8d6c3..f8a212d27 100644 --- a/test/integration/client/BaseIntegrationTestEnv.js +++ b/test/integration/client/BaseIntegrationTestEnv.js @@ -4,9 +4,9 @@ import { TokenDeleteTransaction, Hbar, AccountId, - Wallet + Wallet, } from "../../../src/exports.js"; -import LocalProvider from '../../../src/LocalProvider.js' +import LocalProvider from "../../../src/LocalProvider.js"; /** * @typedef {import("../../../src/exports.js").TokenId} TokenId @@ -79,11 +79,11 @@ export default class BaseIntegrationTestEnv { }); } else if (options.env.CONFIG_FILE != null) { client = await options.client.fromConfigFile( - options.env.CONFIG_FILE + options.env.CONFIG_FILE, ); } else { throw new Error( - "Failed to construct client for IntegrationTestEnv" + "Failed to construct client for IntegrationTestEnv", ); } @@ -92,7 +92,9 @@ export default class BaseIntegrationTestEnv { options.env.OPERATOR_KEY != null ) { const operatorId = AccountId.fromString(options.env.OPERATOR_ID); - const operatorKey = PrivateKey.fromStringED25519(options.env.OPERATOR_KEY); + const operatorKey = PrivateKey.fromStringECDSA( + options.env.OPERATOR_KEY, + ); client.setOperator(operatorId, operatorKey); } @@ -127,7 +129,7 @@ export default class BaseIntegrationTestEnv { const response = await new AccountCreateTransaction() .setKey(newOperatorKey) .setInitialBalance( - new Hbar(options.balance != null ? options.balance : 100) + new Hbar(options.balance != null ? options.balance : 100), ) .execute(client); @@ -135,11 +137,7 @@ export default class BaseIntegrationTestEnv { client.setOperator(newOperatorId, newOperatorKey); - wallet = new Wallet( - newOperatorId, - newOperatorKey, - new LocalProvider() - ) + wallet = new Wallet(newOperatorId, newOperatorKey, new LocalProvider()); return new BaseIntegrationTestEnv({ client: client, diff --git a/test/integration/client/TestnetIntegrationTestEnv.js b/test/integration/client/TestnetIntegrationTestEnv.js index 61508b96a..10d24e8d6 100644 --- a/test/integration/client/TestnetIntegrationTestEnv.js +++ b/test/integration/client/TestnetIntegrationTestEnv.js @@ -18,9 +18,9 @@ export default class TestnetIntegrationTestEnv extends BaseIntegrationTestEnv { return BaseIntegrationTestEnv.new({ client: Client, env: { - OPERATOR_ID: "0.0.8920", + OPERATOR_ID: "0.0.4481103", OPERATOR_KEY: - "07f9f9c355d32c5c93a50024b596ed3ccc39954ba1963c68ac21cb7802fd5f83", + "3d11515c6794311c87dfdeaac90d4c223c22f3634db8f24690b557ea0ca97c11", HEDERA_NETWORK: "testnet", }, nodeAccountIds: options.nodeAccountIds, diff --git a/test/unit/MirrorNodeContractCallQuery.js b/test/unit/MirrorNodeContractCallQuery.js new file mode 100644 index 000000000..4ab122490 --- /dev/null +++ b/test/unit/MirrorNodeContractCallQuery.js @@ -0,0 +1,28 @@ +import { AccountId, MirrorNodeContractCallQuery } from "../../src/exports.js"; + +describe("MirrorNodeContractCallQuery", function () { + const SENDER = new AccountId(1); + const CONTRACT_ID = new AccountId(1); + const VALUE = 100; + const GAS_LIMIT = 100; + const GAS_PRICE = 100; + const BLOCK_NUMBER = 100; + + it("should throw an error without calldata", async function () { + const query = new MirrorNodeContractCallQuery() + .setBlockNumber(BLOCK_NUMBER) + .setSender(SENDER) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE) + .setContractId(CONTRACT_ID); + + let err = false; + try { + await query.execute(); + } catch (e) { + err = e.message.includes("Call data is required."); + } + expect(err).to.equal(true); + }); +}); diff --git a/test/unit/MirrorNodeContractEstimateQuery.js b/test/unit/MirrorNodeContractEstimateQuery.js new file mode 100644 index 000000000..fc129d88e --- /dev/null +++ b/test/unit/MirrorNodeContractEstimateQuery.js @@ -0,0 +1,31 @@ +import { + AccountId, + MirrorNodeContractEstimateQuery, +} from "../../src/exports.js"; + +describe("MirrorNodeContractCallQuery", function () { + const SENDER = new AccountId(1); + const CONTRACT_ID = new AccountId(1); + const VALUE = 100; + const GAS_LIMIT = 100; + const GAS_PRICE = 100; + const BLOCK_NUMBER = 100; + + it("should throw an error without calldata", async function () { + const query = new MirrorNodeContractEstimateQuery() + .setBlockNumber(BLOCK_NUMBER) + .setSender(SENDER) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE) + .setContractId(CONTRACT_ID); + + let err = false; + try { + await query.execute(); + } catch (e) { + err = e.message.includes("Call data is required."); + } + expect(err).to.equal(true); + }); +}); diff --git a/test/unit/MirrorNodeContractQuery.js b/test/unit/MirrorNodeContractQuery.js new file mode 100644 index 000000000..9a23de18f --- /dev/null +++ b/test/unit/MirrorNodeContractQuery.js @@ -0,0 +1,111 @@ +import { AccountId } from "../../src/exports.js"; +import MirrorNodeContractQuery from "../../src/query/MirrorNodeContractQuery.js"; + +describe("MirrorNodeContractQuery", function () { + const SENDER = new AccountId(1); + const SENDER_EVM_ADDRESS = "0000000000000000000000000000000000000001"; + const CONTRACT_EVM_ADDRESS = "0000000000000000000000000000000000000001"; + const CONTRACT_ID = new AccountId(1); + const FUNCTION_NAME = "getMessage"; + const FUNCTION_SELECTOR = new Uint8Array([206, 109, 65, 222]); // getMessage() + const VALUE = 100; + const GAS_LIMIT = 100; + const GAS_PRICE = 100; + const BLOCK_NUMBER = 100; + + it("should set query parameters", function () { + const query = new MirrorNodeContractQuery() + .setBlockNumber(BLOCK_NUMBER) + .setSender(SENDER) + .setFunction(FUNCTION_NAME) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE) + .setContractId(CONTRACT_ID); + + expect(query.sender).to.be.instanceOf(AccountId); + expect(query.senderEvmAddress).to.be.equal(SENDER_EVM_ADDRESS); + expect(query.contractEvmAddress).to.be.equal(CONTRACT_EVM_ADDRESS); + expect(query.callData).to.be.deep.equal(FUNCTION_SELECTOR); + expect(query.value).to.be.equal(VALUE); + expect(query.gasLimit).to.be.equal(GAS_LIMIT); + expect(query.gasPrice).to.be.equal(GAS_PRICE); + expect(query.blockNumber).to.be.equal(BLOCK_NUMBER); + expect(query.contractId).to.be.equal(CONTRACT_ID); + }); + + it("should throw an error when no contract id sent", async function () { + const query = new MirrorNodeContractQuery() + .setBlockNumber(BLOCK_NUMBER) + .setSender(SENDER) + .setFunction(FUNCTION_NAME) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE); + + let err = false; + try { + query.contractEvmAddress; + } catch (e) { + err = e.message.includes("Contract ID is not set"); + } + expect(err).to.be.true; + /* + err = false; + try { + await query.execute(); + } catch (e) { + console.log(e); + err = e.message.includes("Contract ID is not set"); + } + expect(err).to.be.true; + */ + }); + + it("should throw an error when no sender sent", async function () { + const query = new MirrorNodeContractQuery() + .setBlockNumber(BLOCK_NUMBER) + .setFunction(FUNCTION_NAME) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE) + .setContractId(CONTRACT_ID); + expect(query.sender).to.be.null; + + let err = false; + try { + query.senderEvmAddress; + } catch (e) { + err = e.message.includes("Sender is not set"); + } + expect(err).to.be.true; + + /* + err = false; + try { + await query.execute(); + } catch (e) { + err = e.message.includes("Sender is not set"); + } + expect(err).to.be.true; + */ + }); + + it("should not be able to perform MN request without contract id", async function () { + const query = new MirrorNodeContractQuery() + .setBlockNumber(BLOCK_NUMBER) + .setSender(SENDER) + .setFunction(FUNCTION_NAME) + .setValue(VALUE) + .setGasLimit(GAS_LIMIT) + .setGasPrice(GAS_PRICE); + + let err = false; + try { + await query.performMirrorNodeRequest("", ""); + } catch (e) { + err = e.message.includes("Contract ID is not set"); + } + expect(err).to.be.true; + }); +});