Skip to main content

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() and getAfter() to access data from other on-chain collections.
    • ⚠️ CRITICAL LIMITATION: On-chain hooks cannot use get() or getAfter() to access data from off-chain ("onchain": false) collections.
  • 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.