Lesson 5: Development Environment Setup
Learning Objectives
Navigate Hooks Builder and use it for rapid prototyping and testing
Set up local development tools including the compiler toolchain and VS Code
Create and fund testnet accounts on both Hooks testnet and Xahau testnet
Deploy a Hook via SetHook transaction
Debug Hook execution using trace logging and explorer tools
Hook development requires different tools than typical web or mobile development. You're writing C code that compiles to WebAssembly that runs on blockchain validators. The toolchain reflects this:
HOOKS DEVELOPMENT STACK
SOURCE CODE
├── C language (.c files)
├── Hooks API headers
└── Your business logic
↓ Compile
WEBASSEMBLY
├── .wasm binary
├── Portable bytecode
└── Runs on any WASM runtime
↓ Deploy
BLOCKCHAIN
├── SetHook transaction
├── Attached to account
└── Executes on transactions
```
We'll set up tools for each stage.
Hooks Builder is the fastest way to start:
HOOKS BUILDER ACCESS
URL: https://hooks.xrpl.org
Requirements:
├── Modern web browser (Chrome, Firefox, Safari)
├── Internet connection
├── No installation needed
└── Works on any OS
Features:
├── Code editor with syntax highlighting
├── Integrated C-to-WASM compiler
├── Account creation/management
├── Transaction submission
├── Debug output (trace)
├── Example library
└── Testnet deployment
Exercise: Open Hooks Builder
- Navigate to hooks.xrpl.org
- Explore the interface:
You need a testnet account to deploy Hooks:
CREATING TESTNET ACCOUNT
1. Click "Account" tab (right panel)
2. Click "Generate New Account"
3. Save the generated credentials:
4. Click "Fund Account" (uses testnet faucet)
5. Wait for funding confirmation
IMPORTANT:
├── These are TEST credentials
├── No real value
├── Save them for later use
├── Don't share secrets (even test ones, as habit)
Verify Funding:
├── Balance should show XRP
├── Account is now active
└── Ready for Hook deployment
Exercise: Create Your First Testnet Account
- Generate a new account in Hooks Builder
- Fund it using the faucet
- Record your address and secret somewhere safe
- Verify the balance displays
Hooks Builder includes working examples:
EXAMPLE LIBRARY NAVIGATION
Location: Left panel → Examples
Categories:
├── Basic: Simple Hooks for learning
├── Finance: Payment-related Hooks
├── Security: Filtering and protection
├── Utility: Helper functions
└── Advanced: Complex patterns
1. Click an example name
2. Code loads in editor
3. Review the code
4. Compile with "Compile" button
5. Deploy with "Deploy" button
6. Test with transactions
Recommended First Examples:
├── accept.c - Accepts all transactions
├── firewall.c - Basic filtering
├── savings.c - Auto-transfer percentage
└── starter.c - Minimal template
Exercise: Load and Review an Example
- Click "Examples" in left panel
- Load the "accept.c" example
- Review the code structure
- Identify the hook() and cbak() functions
Hooks Builder is great for learning, but local development offers advantages:
LOCAL VS BROWSER DEVELOPMENT
Hooks Builder:
├── Instant setup
├── Examples built-in
├── No installation
├── Limited debugging
├── Single-file focus
├── Good for: Learning, prototyping
Local Development:
├── Full IDE features
├── Version control
├── Multi-file projects
├── Better debugging
├── Automation possible
├── Good for: Serious development
For local development, you need:
LOCAL DEVELOPMENT TOOLS
1. C COMPILER (WASM target)
1. HOOKS TOOLS
1. TEXT EDITOR / IDE
1. NODE.JS (for scripts)
1. DOCKER (optional)
The simplest local setup uses Docker:
# Pull the hooks compiler image
docker pull xrplhooks/compiler
# Create a directory for your Hooks
mkdir ~/hooks-dev
cd ~/hooks-dev
# Create a simple Hook file
cat > accept.c << 'EOF'
#include "hookapi.h"
int64_t hook(uint32_t r) {
accept(SBUF("Accepted"), 0);
return 0;
}
int64_t cbak(uint32_t r) {
return 0;
}
EOF
# Compile using Docker
docker run --rm -v $(pwd):/src xrplhooks/compiler accept.c
# Output: accept.wasm in current directory
Exercise: Docker Compilation (If Docker Available)
- Install Docker if not present
- Create a hooks-dev directory
- Write a simple Hook
- Compile using Docker
- Verify .wasm file created
For full control, install tools manually:
# MacOS (with Homebrew)
# Install wasi-sdk
brew install llvm
export PATH="/usr/local/opt/llvm/bin:$PATH"
# Clone hooks toolkit
git clone https://github.com/XRPL-Labs/hooks-toolkit
cd hooks-toolkit
# Build tools
make all
# Linux (Ubuntu/Debian)
# Download wasi-sdk from GitHub releases
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz
tar xzf wasi-sdk-20.0-linux.tar.gz
export WASI_SDK_PATH=$(pwd)/wasi-sdk-20.0
# Clone and build hooks toolkit
git clone https://github.com/XRPL-Labs/hooks-toolkit
cd hooks-toolkit
make all
# Windows
# Use WSL2 with Ubuntu, follow Linux instructions
# Or use Docker approach
Set up VS Code for Hook development:
// .vscode/settings.json
{
"C_Cpp.default.includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/hooks-toolkit/include"
],
"C_Cpp.default.defines": [
"__HOOKS__"
],
"files.associations": {
"*.c": "c"
}
}
// .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile Hook",
"type": "shell",
"command": "docker run --rm -v ${workspaceFolder}:/src xrplhooks/compiler ${file}",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Exercise: VS Code Setup (Optional)
- Install VS Code if not present
- Install C/C++ extension
- Create hooks project folder
- Add configuration files
- Test compilation task
Hooks are deployed via SetHook transaction:
SETHOOK TRANSACTION
Transaction Type: SetHook
Required Fields:
├── Account: Your account address
├── Hooks: Array of Hook definitions
Hook Definition Fields:
├── HookHash: Hash of WASM binary (if referencing existing)
├── CreateCode: WASM binary in hex (if deploying new)
├── HookNamespace: 32-byte namespace
├── HookOn: Transaction type filter (which tx trigger Hook)
├── HookParameters: Install-time parameters (optional)
├── HookApiVersion: API version (0)
└── Flags: Hook flags
Example Transaction:
{
"TransactionType": "SetHook",
"Account": "rYourAccount...",
"Hooks": [
{
"Hook": {
"CreateCode": "0061736D010000...",
"HookNamespace": "00000000...",
"HookOn": "0000000000000000...",
"HookApiVersion": 0,
"Flags": 1
}
}
]
}
The easiest deployment method:
HOOKS BUILDER DEPLOYMENT
Step 1: COMPILE
├── Code in editor
├── Click "Compile"
├── Check for errors
├── Verify "Compilation successful"
Step 2: CONFIGURE
├── Select account (right panel)
├── Review Hook settings
├── HookOn filter (which transactions)
├── Default: All transaction types
Step 3: DEPLOY
├── Click "Deploy" button
├── Transaction submitted
├── Wait for validation
├── Success message appears
Step 4: VERIFY
├── Check account in explorer
├── Hook should show in account info
├── Ready for testing
Exercise: Deploy Accept Hook
- In Hooks Builder, load this code:
#include "hookapi.h"
int64_t hook(uint32_t reserved) {
// Log that we're executing
trace(SBUF("Hook executed!"), 0);
// Accept all transactions
accept(SBUF("Transaction accepted by Hook"), 0);
return 0;
}
int64_t cbak(uint32_t reserved) {
return 0;
}
- Compile (click Compile button)
- Select your funded account
- Deploy (click Deploy button)
- Wait for confirmation
After deployment, test that it works:
TESTING DEPLOYED HOOK
1. Use a second test account (or faucet)
2. Send small payment to your Hook account
3. Transaction should succeed
4. Check trace output for "Hook executed!"
1. Go to testnet explorer
2. Look up your account
3. Find the transaction
4. Expand Hook execution details
5. Verify accept message
Test Edge Cases:
├── Different transaction types
├── Different amounts
├── From different accounts
└── Observe Hook behavior
Exercise: Test Your Hook
- From Hooks Builder, send payment TO your Hook account
- Or fund a second account and send from there
- Verify transaction succeeds
- Check trace logs for Hook execution message
The primary debugging tool is trace():
// trace() function signature
int64_t trace(
uint32_t mread_ptr, uint32_t mread_len, // Message
int64_t num // Associated number
);
// Usage examples:
// Simple message
trace(SBUF("Starting hook"), 0);
// With number
int64_t amount = otxn_amount();
trace(SBUF("Payment amount:"), amount);
// In conditional
if (amount < 1000000) {
trace(SBUF("Small payment detected"), amount);
}
```
VIEWING TRACE OUTPUT
Location: Bottom panel → "Output" tab
Shows:
├── Compilation messages
├── Deployment status
├── Trace output from Hook execution
├── Error messages
└── Transaction results
Filtering:
├── Search/filter for specific messages
├── Clear between tests
├── Copy for documentation
└── Timestamps included
- Add trace() calls at key points
- Recompile and redeploy
- Trigger with transaction
- Review output
- Iterate
COMMON HOOK ERRORS
COMPILATION ERRORS:
"undefined reference to 'function'"
├── Cause: Using function not in Hooks API
├── Solution: Check xrpl-hooks.readme.io for valid functions
└── Common: Trying to use standard C library
"guard required"
├── Cause: Loop without guard
├── Solution: Add GUARD(n) before loop condition
└── Pattern: for(i=0; GUARD(10), i<10; ++i)
"memory allocation not allowed"
├── Cause: Using malloc, calloc, etc.
├── Solution: Use stack arrays only
└── Pattern: uint8_t buffer[256]; not uint8_t* buffer
DEPLOYMENT ERRORS:
"tecHOOK_REJECTED"
├── Cause: Hook code invalid
├── Check: Compilation actually succeeded
├── Check: WASM binary valid
└── Solution: Review compile output
"tesSUCCESS but Hook not showing"
├── Cause: Deployment succeeded but...
├── Check: Correct account selected
├── Check: Transaction actually submitted
└── Solution: Refresh account view
RUNTIME ERRORS:
"Hook rollback: guard violation"
├── Cause: Loop exceeded guard limit
├── Solution: Increase guard or fix loop
└── Check: Is loop terminating correctly?
"Hook rollback: instruction limit"
├── Cause: Too many instructions
├── Solution: Optimize code
└── Check: Reduce complexity
```
Use blockchain explorers for deeper debugging:
EXPLORER DEBUGGING
Hooks Testnet Explorer:
├── View account with Hook installed
├── See Hook execution in transaction metadata
├── Review HookExecutions block
├── Check return values and messages
Information Available:
├── HookHash (which Hook executed)
├── HookReturnCode (return value)
├── HookReturnString (accept/rollback message)
├── HookEmittedTxnCount (emissions)
├── HookInstructionCount (performance)
└── HookStateChangeCount (state modifications)
1. Submit transaction
2. Copy transaction hash
3. Look up in explorer
4. Expand Hook execution details
5. Identify issues from metadata
---
For serious Hook development:
hooks-project/
├── src/
│ ├── main.c # Primary Hook logic
│ ├── helpers.c # Helper functions (via macros)
│ └── config.h # Configuration constants
├── include/
│ ├── hookapi.h # Hooks API (copy from toolkit)
│ └── sfcodes.h # Serialized field codes
├── build/
│ └── *.wasm # Compiled output
├── test/
│ ├── deploy.js # Deployment script
│ ├── test.js # Test transactions
│ └── accounts.json # Test account credentials
├── docs/
│ └── README.md # Documentation
├── Makefile # Build commands
└── .gitignore # Ignore sensitive filesCreate a Makefile for consistent builds:
# Makefile for Hook development
CC = clang
WASM_FLAGS = --target=wasm32 -nostdlib -O3
# Source files
SRC = src/main.c
OUT = build/hook.wasm
# Hooks toolkit location
TOOLKIT = ../hooks-toolkit
INCLUDE = -I$(TOOLKIT)/include -Iinclude
.PHONY: all clean deploy test
all: $(OUT)
$(OUT): $(SRC)
@mkdir -p build
$(CC) $(WASM_FLAGS) $(INCLUDE) -o $@ $<
$(TOOLKIT)/hook-cleaner $@
$(TOOLKIT)/guard-checker $@
clean:
rm -rf build/*.wasm
deploy: $(OUT)
node test/deploy.js
test: deploy
node test/test.js
Automate deployment with JavaScript:
// test/deploy.js
const xrpl = require('xrpl');
const fs = require('fs');
async function deployHook() {
// Connect to testnet
const client = new xrpl.Client('wss://hooks-testnet-v3.xrpl-labs.com');
await client.connect();
// Load credentials
const accounts = JSON.parse(fs.readFileSync('test/accounts.json'));
const wallet = xrpl.Wallet.fromSecret(accounts.deployer.secret);
// Load compiled Hook
const wasmBinary = fs.readFileSync('build/hook.wasm');
const hookCode = wasmBinary.toString('hex').toUpperCase();
// Build SetHook transaction
const tx = {
TransactionType: 'SetHook',
Account: wallet.address,
Hooks: [{
Hook: {
CreateCode: hookCode,
HookNamespace: '0'.repeat(64),
HookApiVersion: 0,
HookOn: '0'.repeat(58) + 'FFFFFF',
Flags: 1
}
}]
};
// Submit
const result = await client.submitAndWait(tx, { wallet });
console.log('Deployment result:', result.result.meta.TransactionResult);
await client.disconnect();
}
deployHook().catch(console.error);
Before moving to the next lesson, verify your setup:
ENVIRONMENT VERIFICATION CHECKLIST
HOOKS BUILDER:
□ Can access hooks.xrpl.org
□ Created testnet account
□ Account funded with test XRP
□ Successfully compiled example Hook
□ Successfully deployed Hook
□ Tested Hook with transaction
□ Can view trace output
LOCAL DEVELOPMENT (Optional but Recommended):
□ Docker installed OR wasi-sdk configured
□ Can compile .c to .wasm locally
□ VS Code or editor configured
□ Can run deployment script
ACCOUNTS:
□ Have at least one funded testnet account
□ Credentials saved securely
□ Know how to fund additional accounts
□ Understand account vs secret distinction
DEBUGGING:
□ Know how to add trace() calls
□ Know where to view trace output
□ Can find transactions in explorer
□ Understand common error messages
READY FOR:
□ Writing custom Hook logic
□ Testing transaction filtering
□ Learning Hooks API
□ Building real applications
✅ Hooks Builder works for rapid development. Browser-based compilation and deployment is functional and convenient.
✅ The toolchain produces valid WASM. Compiled Hooks execute correctly on the testnet.
✅ Trace logging enables basic debugging. You can understand Hook execution with proper logging.
⚠️ Long-term tooling evolution. The ecosystem is young and tools may change significantly.
⚠️ Local development complexity. Setup varies by platform and can be challenging for beginners.
⚠️ Best practices still emerging. Project structures and workflows aren't standardized.
🔴 Committing secrets to version control. Never commit account secrets, even test ones (builds bad habits).
🔴 Testing on wrong network. Always verify you're on testnet, not accidentally spending real assets.
🔴 Skipping guard-checker. Always run guard-checker before deployment to catch missing guards.
The Hooks development environment is functional but less mature than Ethereum tooling. Hooks Builder provides an excellent starting point, and local development is achievable with some setup effort. The main challenge is documentation—you'll often need to experiment and refer to examples rather than finding explicit guidance. This course fills many of those gaps.
Assignment: Document your working development environment and demonstrate a deployed Hook.
Requirements:
Part 1: Environment Documentation (30%)
- Screenshot of Hooks Builder with your account
- Account address (NOT secret) and balance
- Any local tools installed (if applicable)
- Operating system and browser used
Part 2: Hook Deployment Evidence (40%)
Deploy this customized Hook:
#include "hookapi.h"
int64_t hook(uint32_t reserved) {
// YOUR NAME HERE - replace with your name
trace(SBUF("Hook by: [YOUR NAME]"), 0);
// Get the amount
int64_t drops = otxn_amount();
trace(SBUF("Amount in drops:"), drops);
// Accept all transactions
accept(SBUF("Hello from [YOUR NAME]'s Hook"), 0);
return 0;
}
int64_t cbak(uint32_t reserved) {
return 0;
}
- Screenshot of successful compilation
- Screenshot of successful deployment
- Transaction hash of deployment
- Screenshot showing Hook in account info
Part 3: Testing Evidence (30%)
Send a payment to your Hook account
Screenshot of trace output showing your name
Transaction hash of the test transaction
Brief description of what happened
Complete environment documentation (25%)
Successful Hook deployment (35%)
Successful testing with trace output (30%)
Clear screenshots and organization (10%)
Time investment: 1-2 hours
Value: Confirms you can build and deploy Hooks
Knowledge Check
Question 1 of 5What is the primary purpose of the guard-checker tool?
- Official: hooks.xrpl.org
- Examples within the builder
- GitHub: XRPL-Labs/hooks-toolkit
- Docker Hub: xrplhooks/compiler
- wasi-sdk: github.com/WebAssembly/wasi-sdk
- xrpl.js: js.xrpl.org
- xrpl-py: xrpl-py.readthedocs.io
For Next Lesson:
We'll dive into C programming essentials for Hooks. If you're not familiar with C, don't worry—we'll cover what you need to know. If you are familiar with C, you'll learn the Hooks-specific patterns.
End of Lesson 5
Total words: ~4,000
Estimated completion time: 60 minutes reading and setup
Key Takeaways
Hooks Builder is the fastest way to start.
Browser-based development with integrated compilation, deployment, and debugging.
Local development offers more power.
Version control, automation, and better IDE support, but requires setup.
trace() is your primary debugging tool.
Add logging liberally during development; you can remove it for production.
The SetHook transaction attaches Hooks to accounts.
Understand this transaction type—you'll use it constantly.
Test everything on testnet first.
No exceptions. Verify your Hook works correctly before any production use. ---