Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:
uses: hiero-ledger/hiero-solo-action@b76850c1ac44466900f8e7412b309c3aa0f539c1 # v0.12
with:
installMirrorNode: true
hieroVersion: v0.65.0
hieroVersion: v0.69.0-alpha.2
mirrorNodeVersion: v0.138.0
grpcProxyPort: 8080

Expand Down Expand Up @@ -211,7 +211,7 @@ jobs:
uses: hiero-ledger/hiero-solo-action@b76850c1ac44466900f8e7412b309c3aa0f539c1 # v0.12
with:
installMirrorNode: true
hieroVersion: v0.65.0
hieroVersion: v0.69.0-alpha.2
mirrorNodeVersion: v0.138.0
grpcProxyPort: 8080

Expand Down
177 changes: 177 additions & 0 deletions examples/account-hooks-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { decode } from "../src/encoding/hex.js";
import fs from "fs";
import {
AccountCreateTransaction,
AccountUpdateTransaction,
ContractCreateTransaction,
PrivateKey,
Hbar,
Client,
AccountId,
HookCreationDetails,
LambdaEvmHook,
HookExtensionPoint,
Long,
} from "@hiero-ledger/sdk";

import dotenv from "dotenv";

dotenv.config();

async function main() {
if (
process.env.OPERATOR_ID == null ||
process.env.OPERATOR_KEY == null ||
process.env.HEDERA_NETWORK == null
) {
throw new Error(
"Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.",
);
}

const operatorId = AccountId.fromString(process.env.OPERATOR_ID);
const operatorKey = PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY);
const network = process.env.HEDERA_NETWORK;
const client = Client.forName(network).setOperator(operatorId, operatorKey);

try {
console.log("Account Hooks Example Start!");

/*
* Step 1: Create the hook contract.
*/
console.log("Creating hook contract...");

// Create bytecode file for the hook contract
console.log("Creating bytecode for hook contract...");
const contractBytecodeHex = fs.readFileSync(
"./contracts/HieroHookContract.bytecode.txt",
"utf8",
);

// Create the hook contract
console.log("Creating hook contract...");
let { contractId } = await (
await (
await new ContractCreateTransaction()
.setAdminKey(operatorKey.publicKey)
.setGas(500_000)
.setBytecode(decode(contractBytecodeHex))
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log("Hook contract created with ID:", contractId.toString());

/*
* Step 2: Demonstrate creating an account with hooks.
*/
console.log("\n=== Creating Account with Hooks ===");
console.log("Creating account with lambda EVM hook...");

const accountKey = PrivateKey.generate();
const accountPublicKey = accountKey.publicKey;

// Create a lambda EVM hook
const lambdaHook = new LambdaEvmHook({ contractId });

// Create hook creation details
const adminKey = client.operatorPublicKey;
const hookWithId1002 = new HookCreationDetails({
extensionPoint: HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
hookId: Long.fromInt(1002),
hook: lambdaHook,
key: adminKey,
});

let { accountId } = await (
await (
await new AccountCreateTransaction()
.setKeyWithoutAlias(accountPublicKey)
.setInitialBalance(new Hbar(1))
.addHook(hookWithId1002)
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log(`account id = ${accountId.toString()}`);
console.log("Successfully created account with lambda hook!");

/*
* Step 3: Demonstrate adding hooks to an existing account.
*/
console.log("\n=== Adding Hooks to Existing Account ===");
console.log("Adding hooks to existing account...");

// Create basic lambda hooks with no storage updates
const basicHook = new LambdaEvmHook({ contractId });
const hookWithId1 = new HookCreationDetails({
extensionPoint: HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
hookId: Long.fromInt(1),
hook: basicHook,
key: adminKey,
});

const basicHook2 = new LambdaEvmHook({ contractId });
const hookWithId2 = new HookCreationDetails({
extensionPoint: HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
hookId: Long.fromInt(2),
hook: basicHook2,
key: adminKey,
});

try {
await (
await (
await new AccountUpdateTransaction()
.setAccountId(accountId)
.addHookToCreate(hookWithId1)
.addHookToCreate(hookWithId2)
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(accountKey)
).execute(client)
).getReceipt(client);

console.log("Successfully added hooks to account!");
} catch (error) {
console.error("Failed to execute hook transaction:", error);
}

/*
* Step 4: Demonstrate hook deletion.
*/
console.log("\n=== Deleting Hooks from Account ===");
console.log("Deleting hooks from account...");

try {
await (
await (
await new AccountUpdateTransaction()
.setAccountId(accountId)
.addHookToDelete(Long.fromNumber(1))
.addHookToDelete(Long.fromNumber(2))
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(accountKey)
).execute(client)
).getReceipt(client);

console.log("Successfully deleted hooks (IDs: 1, 2)");
} catch (error) {
console.error("Failed to execute hook deletion:", error);
}

console.log("Account Hooks Example Complete!");
} catch (error) {
console.error("Error occurred:", error);
}

client.close();
}

void main();
174 changes: 174 additions & 0 deletions examples/contract-hooks-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import fs from "fs";
import { decode } from "../src/encoding/hex.js";
import {
ContractCreateTransaction,
ContractUpdateTransaction,
PrivateKey,
Client,
AccountId,
HookCreationDetails,
LambdaEvmHook,
HookExtensionPoint,
Long,
Hbar,
} from "@hiero-ledger/sdk";

import dotenv from "dotenv";

dotenv.config();

async function main() {
if (
process.env.OPERATOR_ID == null ||
process.env.OPERATOR_KEY == null ||
process.env.HEDERA_NETWORK == null
) {
throw new Error(
"Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.",
);
}

const operatorId = AccountId.fromString(process.env.OPERATOR_ID);
const operatorKey = PrivateKey.fromStringECDSA(process.env.OPERATOR_KEY);
const network = process.env.HEDERA_NETWORK;
const client = Client.forName(network).setOperator(operatorId, operatorKey);

try {
console.log("Contract Hooks Example Start!");

/*
* Step 1: Create the hook contract.
*/
console.log("Creating hook contract...");

// Create bytecode file for the hook contract
console.log("Creating bytecode for hook contract...");
const hookContractBytecodeHex = fs.readFileSync(
"./contracts/HieroHookContract.bytecode.txt",
"utf8",
);

// Create the hook contract
console.log("Creating hook contract...");
let { contractId: hookContractId } = await (
await (
await new ContractCreateTransaction()
.setAdminKey(operatorKey.publicKey)
.setGas(500_000)
.setBytecode(decode(hookContractBytecodeHex))
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log(
"Hook contract created with ID:",
hookContractId.toString(),
);

/*
* Step 2: Demonstrate creating a contract with hooks.
*/
console.log("\n=== Creating Contract with Hooks ===");
console.log("Creating contract with lambda EVM hook...");

const simpleContractBytecodeHex = fs.readFileSync(
"./contracts/HelloWorld.bytecode.txt",
"utf8",
);

// Build a basic lambda EVM hook (no admin key, no storage updates)
const lambdaHook = new LambdaEvmHook({ contractId: hookContractId });
const hookWithId1 = new HookCreationDetails({
extensionPoint: HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
hookId: Long.fromInt(1),
hook: lambdaHook,
});

let { contractId: contractWithHooksId } = await (
await (
await new ContractCreateTransaction()
.setAdminKey(operatorKey.publicKey)
.setGas(400_000)
.setBytecode(decode(simpleContractBytecodeHex))
.addHook(hookWithId1)
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log(
"Created contract with ID:",
contractWithHooksId.toString(),
);
console.log("Successfully created contract with basic lambda hook!");

/*
* Step 3: Demonstrate adding hooks to an existing contract.
*/
console.log("\n=== Adding Hooks to Existing Contract ===");
console.log("Adding hooks to existing contract...");

const adminKey = client.operatorPublicKey;

// Hook 3: Basic lambda hook with no storage updates (using ID 3 to avoid conflict with existing hook 1)
const basicHook = new LambdaEvmHook({ contractId: hookContractId });
const hookWithId3 = new HookCreationDetails({
extensionPoint: HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
hookId: Long.fromInt(3),
hook: basicHook,
key: adminKey,
});

try {
await (
await (
await new ContractUpdateTransaction()
.setContractId(contractWithHooksId)
.addHookToCreate(hookWithId3)
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log("Successfully added hooks to contract!");
} catch (error) {
console.error("Failed to execute hook transaction:", error);
}

/*
* Step 4: Demonstrate hook deletion.
*/
console.log("\n=== Deleting Hooks from Contract ===");
console.log("Deleting hooks from contract...");

try {
await (
await (
await new ContractUpdateTransaction()
.setContractId(contractWithHooksId)
.addHookToDelete(Long.fromNumber(1)) // Delete hook created during contract creation
.addHookToDelete(Long.fromNumber(3)) // Delete hook added via contract update
.setMaxTransactionFee(new Hbar(10))
.freezeWith(client)
.sign(operatorKey)
).execute(client)
).getReceipt(client);

console.log("Successfully deleted hooks with IDs: 1 and 3");
} catch (error) {
console.error("Failed to execute hook deletion:", error);
}

console.log("Contract Hooks Example Complete!");
} catch (error) {
console.error("Error occurred:", error);
}

client.close();
}

void main();
1 change: 1 addition & 0 deletions examples/contracts/HelloWorld.bytecode.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
608060405234801561001057600080fd5b50610167806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80632f570a2314610030575b600080fd5b61004a600480360381019061004591906100b6565b610060565b604051610057919061010a565b60405180910390f35b60006001905092915050565b60008083601f84011261007e57600080fd5b8235905067ffffffffffffffff81111561009757600080fd5b6020830191508360018202830111156100af57600080fd5b9250929050565b600080602083850312156100c957600080fd5b600083013567ffffffffffffffff8111156100e357600080fd5b6100ef8582860161006c565b92509250509250929050565b61010481610125565b82525050565b600060208201905061011f60008301846100fb565b92915050565b6000811515905091905056fea264697066735822122097fc0c3ac3155b53596be3af3b4d2c05eb5e273c020ee447f01b72abc3416e1264736f6c63430008000033
14 changes: 14 additions & 0 deletions examples/contracts/HelloWorld.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.0;

/**
* @title Test
*/
contract HelloWorld {
constructor() {
}

function test(bytes calldata calldata_test) external returns(bool) {
return true;
}
}
1 change: 1 addition & 0 deletions examples/contracts/HieroHookContract.bytecode.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b506107d18061001c5f395ff3fe608060405260043610610033575f3560e01c8063124d8b301461003757806394112e2f14610067578063bd0dd0b614610097575b5f5ffd5b610051600480360381019061004c91906106f2565b6100c7565b60405161005e9190610782565b60405180910390f35b610081600480360381019061007c91906106f2565b6100d2565b60405161008e9190610782565b60405180910390f35b6100b160048036038101906100ac91906106f2565b6100dd565b6040516100be9190610782565b60405180910390f35b5f6001905092915050565b5f6001905092915050565b5f6001905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f60a08284031215610112576101116100f9565b5b81905092915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101658261011f565b810181811067ffffffffffffffff821117156101845761018361012f565b5b80604052505050565b5f6101966100e8565b90506101a2828261015c565b919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff8211156101c9576101c861012f565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610207826101de565b9050919050565b610217816101fd565b8114610221575f5ffd5b50565b5f813590506102328161020e565b92915050565b5f8160070b9050919050565b61024d81610238565b8114610257575f5ffd5b50565b5f8135905061026881610244565b92915050565b5f604082840312156102835761028261011b565b5b61028d604061018d565b90505f61029c84828501610224565b5f8301525060206102af8482850161025a565b60208301525092915050565b5f6102cd6102c8846101af565b61018d565b905080838252602082019050604084028301858111156102f0576102ef6101da565b5b835b818110156103195780610305888261026e565b8452602084019350506040810190506102f2565b5050509392505050565b5f82601f830112610337576103366101ab565b5b81356103478482602086016102bb565b91505092915050565b5f67ffffffffffffffff82111561036a5761036961012f565b5b602082029050602081019050919050565b5f67ffffffffffffffff8211156103955761039461012f565b5b602082029050602081019050919050565b5f606082840312156103bb576103ba61011b565b5b6103c5606061018d565b90505f6103d484828501610224565b5f8301525060206103e784828501610224565b60208301525060406103fb8482850161025a565b60408301525092915050565b5f6104196104148461037b565b61018d565b9050808382526020820190506060840283018581111561043c5761043b6101da565b5b835b81811015610465578061045188826103a6565b84526020840193505060608101905061043e565b5050509392505050565b5f82601f830112610483576104826101ab565b5b8135610493848260208601610407565b91505092915050565b5f606082840312156104b1576104b061011b565b5b6104bb606061018d565b90505f6104ca84828501610224565b5f83015250602082013567ffffffffffffffff8111156104ed576104ec6101a7565b5b6104f984828501610323565b602083015250604082013567ffffffffffffffff81111561051d5761051c6101a7565b5b6105298482850161046f565b60408301525092915050565b5f61054761054284610350565b61018d565b9050808382526020820190506020840283018581111561056a576105696101da565b5b835b818110156105b157803567ffffffffffffffff81111561058f5761058e6101ab565b5b80860161059c898261049c565b8552602085019450505060208101905061056c565b5050509392505050565b5f82601f8301126105cf576105ce6101ab565b5b81356105df848260208601610535565b91505092915050565b5f604082840312156105fd576105fc61011b565b5b610607604061018d565b90505f82013567ffffffffffffffff811115610626576106256101a7565b5b61063284828501610323565b5f83015250602082013567ffffffffffffffff811115610655576106546101a7565b5b610661848285016105bb565b60208301525092915050565b5f604082840312156106825761068161011b565b5b61068c604061018d565b90505f82013567ffffffffffffffff8111156106ab576106aa6101a7565b5b6106b7848285016105e8565b5f83015250602082013567ffffffffffffffff8111156106da576106d96101a7565b5b6106e6848285016105e8565b60208301525092915050565b5f5f60408385031215610708576107076100f1565b5b5f83013567ffffffffffffffff811115610725576107246100f5565b5b610731858286016100fd565b925050602083013567ffffffffffffffff811115610752576107516100f5565b5b61075e8582860161066d565b9150509250929050565b5f8115159050919050565b61077c81610768565b82525050565b5f6020820190506107955f830184610773565b9291505056fea26469706673582212207dfe7723f6d6869419b1cb0619758b439da0cf4ffd9520997c40a3946299d4dc64736f6c634300081e0033
Loading
Loading