Lesson 5: Development Environment Setup | Hooks & Smart Contracts | XRP Academy - XRP Academy
3 free lessons remaining this month

Free preview access resets monthly

Upgrade for Unlimited
Skip to main content
beginner60 min

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

  1. Navigate to hooks.xrpl.org
  2. 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

  1. Generate a new account in Hooks Builder
  2. Fund it using the faucet
  3. Record your address and secret somewhere safe
  4. 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

  1. Click "Examples" in left panel
  2. Load the "accept.c" example
  3. Review the code structure
  4. 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)

  1. Install Docker if not present
  2. Create a hooks-dev directory
  3. Write a simple Hook
  4. Compile using Docker
  5. 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)

  1. Install VS Code if not present
  2. Install C/C++ extension
  3. Create hooks project folder
  4. Add configuration files
  5. 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

  1. 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;
}
  1. Compile (click Compile button)
  2. Select your funded account
  3. Deploy (click Deploy button)
  4. 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

  1. From Hooks Builder, send payment TO your Hook account
  2. Or fund a second account and send from there
  3. Verify transaction succeeds
  4. 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

  1. Add trace() calls at key points
  2. Recompile and redeploy
  3. Trigger with transaction
  4. Review output
  5. 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 files

Create 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 5

What 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

1

Hooks Builder is the fastest way to start.

Browser-based development with integrated compilation, deployment, and debugging.

2

Local development offers more power.

Version control, automation, and better IDE support, but requires setup.

3

trace() is your primary debugging tool.

Add logging liberally during development; you can remove it for production.

4

The SetHook transaction attaches Hooks to accounts.

Understand this transaction type—you'll use it constantly.

5

Test everything on testnet first.

No exceptions. Verify your Hook works correctly before any production use. ---