Skip to content

Commit 5ece92b

Browse files
committed
feat(hooks): add account hook create/delete support across base, Spring, MicroProfile, and docs
Signed-off-by: Aman <amkr6207@gmail.com>
1 parent 5e1a805 commit 5ece92b

17 files changed

Lines changed: 455 additions & 6 deletions

File tree

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,30 @@ public class HieroAccountService {
7777
All APIs of the client are synchronous and return the result of the operation.
7878
For asynchronous operations, you can easily wrap calls by use the [`@Async` annotation of spring](https://spring.io/guides/gs/async-method).
7979

80+
### Hook lifecycle management
81+
82+
`AccountClient` exposes hook lifecycle management via `updateAccountHooks(...)`.
83+
This operation delegates to Hedera SDK account update hook fields (`addHookToCreate`, `addHookToDelete`).
84+
85+
```java
86+
import com.hedera.hashgraph.sdk.ContractId;
87+
import com.hedera.hashgraph.sdk.EvmHook;
88+
import java.util.List;
89+
import org.hiero.base.AccountClient;
90+
import org.hiero.base.data.Account;
91+
import org.hiero.base.data.HookDetails;
92+
import org.hiero.base.data.HookExtensionPoint;
93+
94+
HookDetails hookToCreate =
95+
new HookDetails(
96+
HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
97+
1001L,
98+
new EvmHook(ContractId.fromString("0.0.5001")),
99+
null);
100+
101+
accountClient.updateAccountHooks(account, List.of(hookToCreate), List.of(77L));
102+
```
103+
80104
### Hiero Spring Sample
81105

82106
A sample application that uses the Hiero Spring module can be found in the `hiero-enterprise-spring-sample` module.
@@ -131,6 +155,7 @@ The following services are available in spring and microprofile:
131155

132156
- `org.hiero.base.HieroContext`: component that provides the information about the Hiero network and the operator account
133157
- `org.hiero.base.AccountClient`: to interact with accounts
158+
- `org.hiero.base.HookClient`: to interact with hook storage updates
134159
- `org.hiero.base.FileClient`: to interact with files
135160
- `org.hiero.base.FungibleTokenClient`: to interact with fungible tokens
136161
- `org.hiero.base.NftClient`: to interact with NFTs

docs/managed-services.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# Base / Managed Services
22

3-
<!-- TODO: Add documentation for hiero-enterprise-base: HieroContext, AccountClient, FileClient, FungibleTokenClient, NftClient, SmartContractClient, ContractVerificationClient, mirror node repositories, ProtocolLayerClient, MirrorNodeClient. -->
3+
`hiero-enterprise-base` provides the core managed clients used by Spring and MicroProfile modules.
44

5-
Placeholder: technical documentation for the base module and managed services will be added here.
5+
## Hook lifecycle support
6+
7+
Hook lifecycle operations are exposed through `AccountClient.updateAccountHooks(...)`.
8+
This API supports both:
9+
10+
- creating hooks (`hooksToCreate`)
11+
- deleting hooks (`hooksToDelete`)
12+
13+
Core types:
14+
15+
- `org.hiero.base.data.HookDetails`
16+
- `org.hiero.base.data.HookExtensionPoint`
17+
- `org.hiero.base.protocol.data.AccountHookUpdateRequest`
18+
- `org.hiero.base.protocol.data.AccountHookUpdateResult`
19+
20+
Example:
21+
22+
```java
23+
HookDetails hookToCreate =
24+
new HookDetails(
25+
HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
26+
1001L,
27+
new EvmHook(ContractId.fromString("0.0.5001")),
28+
null);
29+
30+
accountClient.updateAccountHooks(account, List.of(hookToCreate), List.of(77L));
31+
```

docs/microprofile.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# MicroProfile Integration
22

3-
<!-- TODO: Add MicroProfile/Quarkus setup, configuration, available clients and usage. -->
3+
MicroProfile integration exposes `AccountClient` via CDI.
44

5-
Placeholder: technical documentation for the MicroProfile integration (hiero-enterprise-microprofile) will be added here.
5+
## Hook lifecycle usage
6+
7+
Use `AccountClient.updateAccountHooks(...)` to create and/or delete hooks in one account update transaction.
8+
9+
```java
10+
@Inject AccountClient accountClient;
11+
12+
HookDetails hookToCreate =
13+
new HookDetails(
14+
HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
15+
1001L,
16+
new EvmHook(ContractId.fromString("0.0.5001")),
17+
null);
18+
19+
accountClient.updateAccountHooks(account, List.of(hookToCreate), List.of(77L));
20+
```

docs/spring-boot.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Spring Boot Integration
22

3-
<!-- TODO: Add Spring Boot setup, @EnableHiero, configuration properties, available clients and usage. -->
3+
Spring integration exposes `AccountClient` as a managed bean.
44

5-
Placeholder: technical documentation for the Spring Boot integration (hiero-enterprise-spring) will be added here.
5+
## Hook lifecycle usage
6+
7+
Use `AccountClient.updateAccountHooks(...)` to create and/or delete hooks in one account update transaction.
8+
9+
```java
10+
@Autowired AccountClient accountClient;
11+
12+
HookDetails hookToCreate =
13+
new HookDetails(
14+
HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK,
15+
1001L,
16+
new EvmHook(ContractId.fromString("0.0.5001")),
17+
null);
18+
19+
accountClient.updateAccountHooks(account, List.of(hookToCreate), List.of(77L));
20+
```

hiero-enterprise-base/src/main/java/org/hiero/base/AccountClient.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import com.hedera.hashgraph.sdk.AccountId;
44
import com.hedera.hashgraph.sdk.Hbar;
55
import com.hedera.hashgraph.sdk.PrivateKey;
6+
import java.util.List;
67
import java.util.Objects;
78
import org.hiero.base.data.Account;
9+
import org.hiero.base.data.HookDetails;
810
import org.jspecify.annotations.NonNull;
911

1012
/**
@@ -92,6 +94,20 @@ default Account createAccount(long initialBalanceInHbar) throws HieroException {
9294
*/
9395
void updateAccountMemo(@NonNull Account account, @NonNull String memo) throws HieroException;
9496

97+
/**
98+
* Updates account hooks by creating and/or deleting hooks in one update transaction.
99+
*
100+
* @param account the account to update
101+
* @param hooksToCreate hook definitions to create
102+
* @param hooksToDelete hook ids to delete
103+
* @throws HieroException if the account could not be updated
104+
*/
105+
void updateAccountHooks(
106+
@NonNull Account account,
107+
@NonNull List<HookDetails> hooksToCreate,
108+
@NonNull List<Long> hooksToDelete)
109+
throws HieroException;
110+
95111
/**
96112
* Updates both key and memo of the given account.
97113
*
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.hiero.base.data;
2+
3+
import com.hedera.hashgraph.sdk.EvmHook;
4+
import com.hedera.hashgraph.sdk.HookCreationDetails;
5+
import com.hedera.hashgraph.sdk.Key;
6+
import java.util.Objects;
7+
import org.jspecify.annotations.NonNull;
8+
import org.jspecify.annotations.Nullable;
9+
10+
/** Data model describing a hook to be created on an account update transaction. */
11+
public record HookDetails(
12+
@NonNull HookExtensionPoint extensionPoint,
13+
long hookId,
14+
@NonNull EvmHook hook,
15+
@Nullable Key adminKey) {
16+
17+
public HookDetails {
18+
Objects.requireNonNull(extensionPoint, "extensionPoint is required");
19+
Objects.requireNonNull(hook, "hook is required");
20+
if (hookId < 0) {
21+
throw new IllegalArgumentException("hookId must be non-negative");
22+
}
23+
}
24+
25+
@NonNull
26+
public HookCreationDetails toHederaSdkType() {
27+
if (adminKey != null) {
28+
return new HookCreationDetails(extensionPoint.toHederaSdkType(), hookId, hook, adminKey);
29+
}
30+
return new HookCreationDetails(extensionPoint.toHederaSdkType(), hookId, hook);
31+
}
32+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.hiero.base.data;
2+
3+
/** Hook extension points supported by account hook creation. */
4+
public enum HookExtensionPoint {
5+
ACCOUNT_ALLOWANCE_HOOK;
6+
7+
public com.hedera.hashgraph.sdk.HookExtensionPoint toHederaSdkType() {
8+
return com.hedera.hashgraph.sdk.HookExtensionPoint.ACCOUNT_ALLOWANCE_HOOK;
9+
}
10+
}

hiero-enterprise-base/src/main/java/org/hiero/base/implementation/AccountClientImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33
import com.hedera.hashgraph.sdk.AccountId;
44
import com.hedera.hashgraph.sdk.Hbar;
55
import com.hedera.hashgraph.sdk.PrivateKey;
6+
import java.util.List;
67
import java.util.Objects;
78
import org.hiero.base.AccountClient;
89
import org.hiero.base.HieroException;
910
import org.hiero.base.data.Account;
11+
import org.hiero.base.data.HookDetails;
1012
import org.hiero.base.protocol.ProtocolLayerClient;
1113
import org.hiero.base.protocol.data.AccountBalanceRequest;
1214
import org.hiero.base.protocol.data.AccountBalanceResponse;
1315
import org.hiero.base.protocol.data.AccountCreateRequest;
1416
import org.hiero.base.protocol.data.AccountCreateResult;
1517
import org.hiero.base.protocol.data.AccountDeleteRequest;
18+
import org.hiero.base.protocol.data.AccountHookUpdateRequest;
1619
import org.hiero.base.protocol.data.AccountUpdateRequest;
1720
import org.jspecify.annotations.NonNull;
1821

@@ -76,6 +79,20 @@ public void updateAccountMemo(@NonNull Account account, @NonNull String memo)
7679
client.executeAccountUpdateTransaction(request);
7780
}
7881

82+
@Override
83+
public void updateAccountHooks(
84+
@NonNull final Account account,
85+
@NonNull final List<HookDetails> hooksToCreate,
86+
@NonNull final List<Long> hooksToDelete)
87+
throws HieroException {
88+
Objects.requireNonNull(account, "account must not be null");
89+
Objects.requireNonNull(hooksToCreate, "hooksToCreate must not be null");
90+
Objects.requireNonNull(hooksToDelete, "hooksToDelete must not be null");
91+
final AccountHookUpdateRequest request =
92+
AccountHookUpdateRequest.of(account, hooksToCreate, hooksToDelete);
93+
client.executeAccountHookUpdateTransaction(request);
94+
}
95+
7996
@Override
8097
public @NonNull Account updateAccount(
8198
@NonNull Account account, @NonNull PrivateKey updatedPrivateKey, @NonNull String memo)

hiero-enterprise-base/src/main/java/org/hiero/base/implementation/ProtocolLayerClientImpl.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
import org.hiero.base.protocol.data.AccountCreateResult;
5959
import org.hiero.base.protocol.data.AccountDeleteRequest;
6060
import org.hiero.base.protocol.data.AccountDeleteResult;
61+
import org.hiero.base.protocol.data.AccountHookUpdateRequest;
62+
import org.hiero.base.protocol.data.AccountHookUpdateResult;
6163
import org.hiero.base.protocol.data.AccountUpdateRequest;
6264
import org.hiero.base.protocol.data.AccountUpdateResult;
6365
import org.hiero.base.protocol.data.ContractCallRequest;
@@ -407,6 +409,30 @@ public AccountUpdateResult executeAccountUpdateTransaction(
407409
return new AccountUpdateResult(receipt.transactionId, receipt.status);
408410
}
409411

412+
@Override
413+
@NonNull
414+
public AccountHookUpdateResult executeAccountHookUpdateTransaction(
415+
@NonNull final AccountHookUpdateRequest request) throws HieroException {
416+
Objects.requireNonNull(request, "request must not be null");
417+
final AccountUpdateTransaction transaction =
418+
new AccountUpdateTransaction()
419+
.setMaxTransactionFee(request.maxTransactionFee())
420+
.setTransactionValidDuration(request.transactionValidDuration())
421+
.setAccountId(request.toUpdate().accountId());
422+
423+
for (final var hookToCreate : request.hooksToCreate()) {
424+
transaction.addHookToCreate(hookToCreate.toHederaSdkType());
425+
}
426+
for (final Long hookIdToDelete : request.hooksToDelete()) {
427+
transaction.addHookToDelete(hookIdToDelete);
428+
}
429+
430+
sign(transaction, request.toUpdate().privateKey());
431+
final TransactionReceipt receipt =
432+
executeTransactionAndWaitOnReceipt(transaction, TransactionType.ACCOUNT_UPDATE);
433+
return new AccountHookUpdateResult(receipt.transactionId, receipt.status);
434+
}
435+
410436
public TopicCreateResult executeTopicCreateTransaction(@NonNull final TopicCreateRequest request)
411437
throws HieroException {
412438
Objects.requireNonNull(request, "request must not be null");

hiero-enterprise-base/src/main/java/org/hiero/base/protocol/ProtocolLayerClient.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import org.hiero.base.protocol.data.AccountCreateResult;
99
import org.hiero.base.protocol.data.AccountDeleteRequest;
1010
import org.hiero.base.protocol.data.AccountDeleteResult;
11+
import org.hiero.base.protocol.data.AccountHookUpdateRequest;
12+
import org.hiero.base.protocol.data.AccountHookUpdateResult;
1113
import org.hiero.base.protocol.data.AccountUpdateRequest;
1214
import org.hiero.base.protocol.data.AccountUpdateResult;
1315
import org.hiero.base.protocol.data.ContractCallRequest;
@@ -187,6 +189,16 @@ public interface ProtocolLayerClient {
187189
@NonNull AccountUpdateResult executeAccountUpdateTransaction(
188190
@NonNull AccountUpdateRequest request) throws HieroException;
189191

192+
/**
193+
* Executes an account hook update transaction.
194+
*
195+
* @param request the request containing the details of the account hook update transaction
196+
* @return the result of the account hook update transaction
197+
* @throws HieroException if the transaction could not be executed
198+
*/
199+
@NonNull AccountHookUpdateResult executeAccountHookUpdateTransaction(
200+
@NonNull AccountHookUpdateRequest request) throws HieroException;
201+
190202
/**
191203
* Executes a token create transaction.
192204
*

0 commit comments

Comments
 (0)