- Please see the transaction and query fees table for the base transaction fee
- Please use the Hedera fee estimator to estimate your transaction fee cost
addApprovedHbarTransfer()addApprovedTokenTransfer()addApprovedNftTransfer()addApprovedTokenTransferWithDecimals()
Note: The allowance spender must pay the fee for the transaction.
TransferTransaction can reference a hook on the sending or receiving account. The hook’s EVM bytecode runs and must return true for the transfer to proceed. This enables custom validation logic like one-time passcodes, compliance rules, or conditional transfer approvals.
To invoke a hook, use the WithHook variants of the transfer methods:
addHbarTransferWithHook()— HBAR transfers with aFungibleHookCalladdTokenTransferWithHook()— Fungible token transfers with aFungibleHookCalladdNftTransferWithHook()— NFT transfers with optional sender and receiverNftHookCall
addHbarTransfer(), addTokenTransfer(), or addNftTransfer() methods.
Hook Invocation LimitsChild records generated by hook calls are capped at 50 per transaction (
consensus.handle.maxFollowingRecords=50). Hook executions are not supported in batch or scheduled transactions.- The accounts the tokens are being debited from are required to sign the transaction
- If an authorized spender account is spending on behalf of the account that owns the tokens then the spending account is required to sign
- The transaction fee-paying account is required to sign the transaction
Methods
| Method | Type | Description |
|---|---|---|
addHbarTransfer(<accountId>, <evmAddress>, <value>) | AccountId, string, HBAR | The account involved in the transfer and the number of HBAR. The sender and recipient values must net zero. |
addTokenTransfer(<tokenId>, <accountId>, <evmAddress>, <value>) | TokenId, AccountId, string, long | The ID of the token, the account ID involved in the transfer, and the number of tokens to transfer. The sender and recipient values must net zero. |
addNftTransfer(<nftId>, <sender>, <receiver>) | NftId, AccountId, AccountId | The NFT ID (token + serial number), the sending account, and receiving account. |
addTokenTransferWithDecimals(<tokenId>, <accountId>, <value>, <int>) | TokenId, AccountId, long, decimals | The ID of the token, the account ID involved in the transfer, the number of tokens to transfer, the decimals of the token. The sender and recipient values must net zero. |
addApprovedHbarTransfer(<ownerAccountId>, <amount>) | AccountId, Hbar | The owner account ID the spender is authorized to transfer from and the amount. Applicable to allowance transfers only. |
addApprovedTokenTransfer(<tokenId>, <accountId>, <value>) | TokenId, AccountId, long | The owner account ID and token the spender is authorized to transfer from. The debiting account is the owner account. Applicable to allowance transfers only. |
addApprovedTokenTransferWithDecimals(<tokenId>, <accountId>, <value>, <decimals>) | TokenId, AccountId, long, int | The owner account ID and token ID (with decimals) the spender is authorized to transfer from. The debit account is the account ID of the sender. Applicable to allowance transfers only. |
addApprovedNftTransfer(<nftId>, <sender>, <receiver>) | NftId, AccountId, AccountId | The NFT ID the spender is authorized to transfer. The sender is the owner account and receiver is the receiving account. Applicable to allowance transfers only. |
addHbarTransferWithHook(<accountId>, <amount>, <hookCall>) | AccountId, Hbar, FungibleHookCall | Adds an HBAR transfer with an attached account allowance hook call. The FungibleHookType on the hook call determines sender/receiver role and pre/pre-post mode. See Hiero Hooks. |
addTokenTransferWithHook(<tokenId>, <accountId>, <amount>, <hookCall>) | TokenId, AccountId, long, FungibleHookCall | Adds a fungible token transfer with an attached account allowance hook call. See Hiero Hooks. |
addNftTransferWithHook(<nftId>, <sender>, <receiver>, <senderHookCall>, <receiverHookCall>) | NftId, AccountId, AccountId, NftHookCall, NftHookCall | Adds an NFT transfer with optional sender and/or receiver hook calls. Pass null for either hook call if not needed. See Hiero Hooks. |
Transfer with account allowance hooks
The following examples demonstrate how to invoke Hiero Hooks during a transfer. EachWithHook method attaches a hook call to a specific transfer entry. The hook’s EVM bytecode executes and must return true for the transfer to succeed.
Hook call types
Hooks use typed call objects that extend a baseHookCall:
| Class | Used For | Hook Type Enum |
|---|---|---|
FungibleHookCall | HBAR and fungible token transfers | FungibleHookType: PRE_HOOK_SENDER, PRE_POST_HOOK_SENDER, PRE_HOOK_RECEIVER, PRE_POST_HOOK_RECEIVER |
NftHookCall | NFT transfers | NftHookType: PRE_HOOK, PRE_POST_HOOK |
hookId (the 64-bit ID of the hook on the owning account) and an EvmHookCall containing data (extra bytes passed to the hook) and gasLimit (maximum gas the payer will pay for this hook).
Example: HBAR transfer with a pre-hook
Example: NFT transfer with sender and receiver hooks
Example: Fungible token transfer with pre/post hook
Hook execution order
When aTransferTransaction invokes multiple hooks, the network executes them in a strict order:
- Pre-hooks: All
PRE_HOOK_SENDER/PRE_HOOK_RECEIVERhooks execute in the order their transfers appear (HBAR first, then each token transfer list). For NFT transfers with both sender and receiver hooks, the sender hook executes first. - Pre/Post hooks (pre-transfer call): All
PRE_POST_HOOKvariants execute theirallowPre(...)function, in the same transfer order. - Main transfer logic executes.
- Pre/Post hooks (post-transfer call): The same hooks execute their
allowPost(...)function, in the same order as step 2.
Get transaction values
| Method | Type | Description |
|---|---|---|
getHbarTransfers() | Map<AccountId, Hbar> | Returns a list of the hbar transfers in this transaction |
getTokenTransfers() | Map<TokenId, Map<AccountId, long>> | Returns the list of token transfers in the transaction |