Skip to content

Commit 0c6ac25

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 cc8cae5 commit 0c6ac25

16 files changed

Lines changed: 377 additions & 85 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 com.hedera.hashgraph.sdk.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+
- `com.hedera.hashgraph.sdk.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: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ default Account createAccount(long initialBalanceInHbar) throws HieroException {
9494
*/
9595
void updateAccountMemo(@NonNull Account account, @NonNull String memo) throws HieroException;
9696

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+
97111
/**
98112
* Updates both key and memo of the given account.
99113
*
@@ -142,7 +156,7 @@ default void addHook(@NonNull Account account, @NonNull HookDetails hookDetails)
142156
throws HieroException {
143157
Objects.requireNonNull(account, "account must not be null");
144158
Objects.requireNonNull(hookDetails, "hookDetails must not be null");
145-
updateHooks(account, List.of(hookDetails), List.of());
159+
updateAccountHooks(account, List.of(hookDetails), List.of());
146160
}
147161

148162
/** Deletes a hook from an account. */
@@ -151,7 +165,7 @@ default void deleteHook(@NonNull Account account, long hookId) throws HieroExcep
151165
if (hookId < 0) {
152166
throw new IllegalArgumentException("hookId must be non-negative");
153167
}
154-
updateHooks(account, List.of(), List.of(hookId));
168+
updateAccountHooks(account, List.of(), List.of(hookId));
155169
}
156170

157171
/** Updates account hooks by creating and/or deleting hooks. */
@@ -160,6 +174,6 @@ default void updateHooks(
160174
@NonNull List<HookDetails> hooksToCreate,
161175
@NonNull List<Long> hookIdsToDelete)
162176
throws HieroException {
163-
throw new UnsupportedOperationException("Account hook management is not implemented yet.");
177+
updateAccountHooks(account, hooksToCreate, hookIdsToDelete);
164178
}
165179
}
Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,33 @@
11
package org.hiero.base.data;
22

3-
import com.hedera.hashgraph.sdk.ContractId;
4-
import com.hedera.hashgraph.sdk.EvmHookStorageUpdate;
3+
import com.hedera.hashgraph.sdk.EvmHook;
4+
import com.hedera.hashgraph.sdk.HookCreationDetails;
55
import com.hedera.hashgraph.sdk.HookExtensionPoint;
66
import com.hedera.hashgraph.sdk.Key;
7-
import java.util.List;
87
import java.util.Objects;
98
import org.jspecify.annotations.NonNull;
109
import org.jspecify.annotations.Nullable;
1110

12-
/**
13-
* High-level representation of a hook to attach to an account.
14-
*
15-
* @param extensionPoint the extension point where the hook should be attached
16-
* @param hookId unique identifier of the hook on the owning entity
17-
* @param evmHookContractId contract implementing the hook logic
18-
* @param initialStorageUpdates initial EVM storage updates to apply on hook creation
19-
* @param adminKey optional key used to authorize management operations for this hook
20-
*/
11+
/** Data model describing a hook to be created on an account update transaction. */
2112
public record HookDetails(
2213
@NonNull HookExtensionPoint extensionPoint,
2314
long hookId,
24-
@NonNull ContractId evmHookContractId,
25-
@NonNull List<EvmHookStorageUpdate> initialStorageUpdates,
15+
@NonNull EvmHook hook,
2616
@Nullable Key adminKey) {
2717

2818
public HookDetails {
29-
Objects.requireNonNull(extensionPoint, "extensionPoint must not be null");
30-
Objects.requireNonNull(evmHookContractId, "evmHookContractId must not be null");
31-
Objects.requireNonNull(initialStorageUpdates, "initialStorageUpdates must not be null");
32-
initialStorageUpdates.forEach(
33-
update -> Objects.requireNonNull(update, "initialStorageUpdates must not contain null"));
34-
initialStorageUpdates = List.copyOf(initialStorageUpdates);
19+
Objects.requireNonNull(extensionPoint, "extensionPoint is required");
20+
Objects.requireNonNull(hook, "hook is required");
3521
if (hookId < 0) {
3622
throw new IllegalArgumentException("hookId must be non-negative");
3723
}
3824
}
25+
26+
@NonNull
27+
public HookCreationDetails toHederaSdkType() {
28+
if (adminKey != null) {
29+
return new HookCreationDetails(extensionPoint, hookId, hook, adminKey);
30+
}
31+
return new HookCreationDetails(extensionPoint, hookId, hook);
32+
}
3933
}

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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ default AccountHookUpdateResult executeAccountHookUpdateTransaction(
202202
@NonNull AccountUpdateResult executeAccountUpdateTransaction(
203203
@NonNull AccountUpdateRequest request) throws HieroException;
204204

205+
/**
206+
* Executes an account hook update transaction.
207+
*
208+
* @param request the request containing the details of the account hook update transaction
209+
* @return the result of the account hook update transaction
210+
* @throws HieroException if the transaction could not be executed
211+
*/
212+
@NonNull AccountHookUpdateResult executeAccountHookUpdateTransaction(
213+
@NonNull AccountHookUpdateRequest request) throws HieroException;
214+
205215
/**
206216
* Executes a token create transaction.
207217
*

0 commit comments

Comments
 (0)