Homework 1: Building a Custom RPC Handler

← Back to Building and Integrating Custom RPC Handlers


Overview

In this comprehensive workshop, you will implement a complete RPC handler from scratch. This exercise will consolidate everything you've learned by having you build a production-quality GetAccountBalance command for Rippled.

Estimated Time: 4-6 hours

Difficulty Level: Intermediate to Advanced


Learning Objectives

By completing this workshop, you will:

  • Understand how handlers are registered in the central handler table

  • Implement proper input validation and error handling

  • Access ledger data through the JsonContext API

  • Calculate XRP reserves and available balances

  • Build well-structured JSON responses

  • Write comprehensive unit tests for your handler

  • Follow Rippled coding conventions and best practices


Prerequisites

Before starting this workshop, ensure you have:


The Challenge

You will implement a new RPC command called get_account_balance that provides detailed balance information for an XRP Ledger account, including:

  • Current XRP balance

  • Base reserve requirement

  • Owner reserve requirement (based on owned objects)

  • Available balance (balance minus reserves)

  • Owner count (number of owned ledger objects)

  • Optional: Trust line balances (if requested)


Part 1: Understanding the RPC System

Before writing code, answer these architectural questions to demonstrate your understanding:

Questions

  1. Handler Discovery

    • How does Rippled locate and invoke the correct handler when a request arrives?

    • What data structure stores the mapping between command names and handler functions?

    • Where in the codebase is this mapping defined?

  2. Request Lifecycle

    • Trace the complete journey of an RPC request from reception to response

    • What stages does a request pass through?

    • At what point is permission checking performed?

  3. Role-Based Access Control

    • What are the five role levels in Rippled's RBAC system?

    • How is a client's role determined?

    • Can you explain the difference between GUEST, USER, and ADMIN roles?

Write your answers in answers.md


Part 2: Handler Implementation

Task 2.1: Create the Handler File

Create a new file:

File: src/xrpld/rpc/handlers/GetAccountBalance.cpp\

Follow the standard file header format used in other handlers.

Task 2.2: Implement the Handler Function

Your handler must:

  1. Validate the account parameter

    • Check if the field exists

    • Validate the account address format

    • Return appropriate errors for invalid input

  2. Handle optional ledger_index parameter

    • Support "current", "validated", "closed"

    • Support specific ledger numbers

    • Default to current ledger if not specified

  3. Query the ledger for account data

    • Use RPC::lookupLedger() to get the ledger

    • Read the account object using keylet::account()

    • Handle account not found scenario

  4. Calculate balance information

    • Get current XRP balance

    • Calculate base reserve (from fees)

    • Calculate owner reserve (based on owner count)

    • Compute available balance (balance - total reserve)

  5. Build the response

    • Include all required fields

    • Use proper JSON structure

    • Mark response as validated when appropriate

Task 2.3: Register the Handler

Add your handler to the central handler table:

File: src/xrpld/rpc/handlers/Handlers.cpp

Choose appropriate values for:

  • Minimum required role

  • Execution conditions

  • API version support

Task 2.4: Expected Request Format

Task 2.5: Expected Response Format


Part 3: Error Handling

Your handler must properly handle these error scenarios:

Required Error Cases

  1. Missing account field

    • Error: rpcINVALID_PARAMS

    • Message: "Missing 'account' field"

  2. Invalid account format

    • Error: rpcACT_MALFORMED

    • Message: "Invalid account address"

  3. Account not found

    • Error: rpcACT_NOT_FOUND

    • Message: "Account not found"

  4. Ledger not available

    • Error: rpcLGR_NOT_FOUND

    • Message: "Ledger not found"

  5. Invalid ledger index

    • Error: rpcINVALID_PARAMS

    • Message: "Invalid ledger_index"

Task 3.1: Implement Error Handling

Ensure each error case returns the proper error code and a descriptive message.


Part 4: Input Validation

Implement comprehensive validation for:

Task 4.1: Account Parameter

Task 4.2: Ledger Parameter

Task 4.3: Edge Cases

Handle these special scenarios:

  • Empty account string

  • Account with no owner count field (shouldn't happen, but be defensive)

  • Ledger with missing fee information

  • Balance exceeding maximum XRP supply


Part 5: Testing

Create comprehensive unit tests for your handler.

Task 5.1: Create Test File

File: src/test/rpc/GetAccountBalance_test.cpp

Task 5.2: Implement Test Cases

Test 5.2.1: Valid Request

Test 5.2.2: Invalid Account Address

Test 5.2.3: Account Not Found

Test 5.2.4: Ledger Selection

Test 5.2.5: Permission Levels

Test 5.2.6: Missing Parameters

Test 5.2.7: Reserve Calculations

Task 5.3: Optional Advanced Tests

  • Concurrent access: Test handler with multiple simultaneous requests

  • Performance: Measure handler execution time

  • Ledger transitions: Test behavior during ledger close

  • Large owner counts: Test with accounts owning many objects


Part 6: Optional Enhancements

After completing the core implementation, consider these enhancements:

Enhancement 6.1: Trust Line Balances

Add optional include_lines parameter:

Response includes trust lines:

Enhancement 6.2: Currency Filtering

Add currency filter for trust lines:

Enhancement 6.3: Pagination

For accounts with many trust lines, add pagination:


Reference Implementation Files

Study these existing handlers as reference:

  1. AccountInfo.cpp

    • Location: src/xrpld/rpc/handlers/AccountInfo.cpp

    • Similar structure to your handler

    • Shows account querying and response building

  2. AccountLines.cpp

    • Location: src/xrpld/rpc/handlers/AccountLines.cpp

    • Trust line iteration and filtering

    • Pagination implementation

  3. LedgerData.cpp

    • Location: src/xrpld/rpc/handlers/LedgerData.cpp

    • Ledger object iteration

    • Large result set handling

  4. RPCHelpers.h

    • Location: src/xrpld/rpc/detail/RPCHelpers.h

    • Utility functions for common tasks

    • Account parsing, ledger lookup, etc.


Submission Checklist

Before considering your implementation complete:


Evaluation Criteria

Your implementation will be evaluated on:

Criterion
Weight
Details

Correctness

40%

Handler produces correct results

Error Handling

20%

All error cases properly handled

Code Quality

20%

Follows best practices and conventions

Testing

15%

Comprehensive test coverage

Documentation

5%

Clear comments and documentation


Getting Help

If you encounter difficulties:

  1. Review the module topics

    • Re-read relevant sections

    • Study code examples carefully

  2. Examine existing handlers

    • AccountInfo.cpp is the best reference

    • Look for similar patterns

  3. Check Rippled documentation

  4. Ask for help


Solution Resources

After attempting the workshop independently:


What You'll Build

By the end of this workshop, you'll have:

  • A fully functional RPC handler integrated into Rippled

  • Comprehensive error handling and input validation

  • Production-quality unit tests

  • Understanding of the complete RPC development lifecycle

  • Skills to build any custom handler you need

Good luck! Enjoy building your first RPC handler!

Last updated