Hooks: Integrating Composable Onchain Actions
Hooks define automated onchain actions that execute after a write operation (create
, update
, delete
) successfully passes its defined rules. Hooks are only applicable to documents configured with "onchain": true
.
Syntax
Hooks are defined within the hooks
object, specifically under the onchain
key for create, update, or delete operations.
"someCollection/$docId": {
"onchain": true,
// ... other properties like fields, rules ...
"hooks": {
"onchain": {
"create": "<action_string>",
"update": "<action_string>",
"delete": "<action_string>"
}
}
}
Example Hook:
"hooks": {
"onchain": {
"create": "@TokenPlugin.transfer(@user.address, get(/chatrooms/$roomId).feeReceiverAddress, @TokenPlugin.USDC, get(/chatrooms/$roomId).feeAmount)"
}
}
This hook transfers a specified amount of USDC tokens from the user's wallet (@user.address
) to a fee receiver address (retrieved using get()
) when a new document matching the path is successfully created.
Key Concepts
- Execution Order: Hooks run after all associated rules for the operation have been evaluated and passed.
- On-Chain Only: Hooks operate exclusively on collections marked
"onchain": true
. Off-chain hooks are not currently supported. - Transactional Plugins: Hooks are the primary place to use transactional plugin functions (like token transfers) that modify blockchain state.
- Atomicity: If any part of a hook action (or rule) fails, the entire operation (including the initial write and any preceding hook actions) is reverted atomically.
- Data Access: Hooks can use
get()
andgetAfter()
to access data from other on-chain collections.- ⚠️ CRITICAL LIMITATION: On-chain hooks cannot use
get()
orgetAfter()
to access data from off-chain ("onchain": false
) collections.
- ⚠️ CRITICAL LIMITATION: On-chain hooks cannot use
- Constants: Hooks can reference predefined constants using
@constants.CONSTANT_NAME
.
Multiple Actions
You can chain multiple plugin calls within a single hook action string using logical operators &&
(AND) and ||
(OR).
"hooks": {
"onchain": {
"create": "@TokenPlugin.burn(@user.address, @TokenPlugin.SOME_TOKEN, 100) && @AccountPlugin.logEvent('User burned tokens')"
}
}
Conditional logic can be achieved using combinations of &&
and ||
:
"hooks": {
"onchain": {
// If user is admin, do action A, otherwise do action B
"create": "(@user.address == @constants.ADMIN_ADDRESS && <action_A>) || (@user.address != @constants.ADMIN_ADDRESS && <action_B>)"
}
}
Note: Ternary operators (condition ? true_action : false_action
) are not supported.
Plugins: Extending Functionality
Plugins provide specialized functions accessible within both rules and hooks. Transactional functions (those modifying state) are primarily intended for use within hooks.
Future Plugins and Extensibility
Tarobase will introduce more built-in plugins. Additionally, the plugin system is planned to be open-sourced, allowing developers to create and integrate custom plugins tailored to specific application needs.