Skip to main content
WAX allows you to extend the base API with custom endpoints, override existing methods, or add entirely new API namespaces. This is useful for working with custom Hive nodes or adding application-specific functionality.

Understanding API structure

Hive uses a JSON-RPC API organized into namespaces:
  • database_api - Read blockchain data
  • block_api - Get block information
  • network_broadcast_api - Broadcast transactions
  • account_by_key_api - Look up accounts by public key
  • Custom APIs - Your own endpoints
WAX generates TypeScript types and Python classes for all standard Hive API methods automatically.

Extending existing APIs

Add new methods to existing API namespaces.
import { createHiveChain } from '@hiveio/wax';
import { DatabaseApi as BaseDatabaseApi } from '@hiveio/wax';

// Extend the DatabaseApi class
class DatabaseApi extends BaseDatabaseApi {
  // Add a method that doesn't exist in base
  @BaseDatabaseApi.endpointJsonrpc
  async get_config(): Promise<any> {
    // Method body is generated automatically
    // Return type can be any or a specific interface
  }

  // Override an existing method to change behavior
  @BaseDatabaseApi.endpointJsonrpc
  async find_accounts(args: { accounts: string[] }): Promise<any> {
    // Custom implementation or call to parent
    const result = await super.find_accounts(args);
    // Add custom processing
    return result;
  }
}

// Create API collection with extended class
class MyApiCollection {
  database_api = DatabaseApi;
}

// Use the extended API
const wax = await createHiveChain();
const extendedWax = wax.extend(MyApiCollection);

// Now you can use the custom method
const config = await extendedWax.api.database_api.get_config();
console.log('Node config:', config);
The @endpoint_jsonrpc decorator automatically handles JSON-RPC communication. You only need to define the method signature.

Creating new API namespaces

Define entirely new API namespaces for custom endpoints.
import { createHiveChain } from '@hiveio/wax';
import { AbstractApi } from '@hiveio/wax';

// Define a new API namespace
class BlockApi extends AbstractApi {
  @AbstractApi.endpointJsonrpc
  async get_block_header(args: { block_num: number }): Promise<any> {
    // Implementation generated automatically
  }

  @AbstractApi.endpointJsonrpc
  async get_block_range(args: {
    starting_block_num: number;
    count: number;
  }): Promise<any> {}
}

// Create API collection with new namespace
class MyApiCollection {
  block_api = BlockApi;
}

// Use the new API namespace
const wax = await createHiveChain();
const extendedWax = wax.extend(MyApiCollection);

const blockHeader = await extendedWax.api.block_api.get_block_header({
  block_num: 123456
});

console.log('Block header:', blockHeader);
The class name must match the API namespace exactly. For example, BlockApi maps to the block_api JSON-RPC namespace.

Combining multiple extensions

You can extend multiple API namespaces in a single collection.
import { createHiveChain } from '@hiveio/wax';
import {
  DatabaseApi as BaseDatabaseApi,
  AbstractApi
} from '@hiveio/wax';

// Extend existing API
class DatabaseApi extends BaseDatabaseApi {
  @BaseDatabaseApi.endpointJsonrpc
  async get_config(): Promise<any> {}
}

// Add new API
class BlockApi extends AbstractApi {
  @AbstractApi.endpointJsonrpc
  async get_block_header(args: { block_num: number }): Promise<any> {}
}

// Add another new API
class ReputationApi extends AbstractApi {
  @AbstractApi.endpointJsonrpc
  async get_account_reputations(args: {
    account_lower_bound: string;
    limit: number;
  }): Promise<any> {}
}

// Combine all extensions
class MyFullApiCollection {
  database_api = DatabaseApi;  // Extended
  block_api = BlockApi;        // New
  reputation_api = ReputationApi; // New
}

// Use all APIs
const wax = await createHiveChain();
const extended = wax.extend(MyFullApiCollection);

// Use extended database_api
const config = await extended.api.database_api.get_config();

// Use new block_api
const header = await extended.api.block_api.get_block_header({
  block_num: 123
});

// Use new reputation_api
const reps = await extended.api.reputation_api.get_account_reputations({
  account_lower_bound: "alice",
  limit: 10
});

Working with REST APIs

You can also extend WAX to work with REST APIs instead of JSON-RPC.
import { createHiveChain } from '@hiveio/wax';

// Define REST API methods
class CustomRestApi {
  constructor(private baseUrl: string) {}

  async getCustomData(id: string): Promise<any> {
    const response = await fetch(`${this.baseUrl}/data/${id}`);
    return response.json();
  }

  async postCustomData(data: any): Promise<any> {
    const response = await fetch(`${this.baseUrl}/data`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    return response.json();
  }
}

// Use with WAX
const wax = await createHiveChain();
const customApi = new CustomRestApi('https://api.example.com');

// Use alongside WAX APIs
const accounts = await wax.api.database_api.find_accounts({
  accounts: ['alice']
});
const customData = await customApi.getCustomData('123');

Type-safe API definitions

Define interfaces for type safety.
import { AbstractApi } from '@hiveio/wax';

// Define request/response types
interface GetBlockHeaderRequest {
  block_num: number;
}

interface BlockHeader {
  previous: string;
  timestamp: string;
  witness: string;
  transaction_merkle_root: string;
  extensions: any[];
}

interface GetBlockHeaderResponse {
  header: BlockHeader;
}

// Use types in API definition
class BlockApi extends AbstractApi {
  @AbstractApi.endpointJsonrpc
  async get_block_header(
    args: GetBlockHeaderRequest
  ): Promise<GetBlockHeaderResponse> {}
}

// TypeScript will now enforce types
const result = await api.block_api.get_block_header({
  block_num: 123
});
// result.header is typed as BlockHeader
console.log(result.header.witness);

Complete example

Here’s a complete example showing API extension in practice:
import { createHiveChain } from '@hiveio/wax';
import {
  DatabaseApi as BaseDatabaseApi,
  AbstractApi
} from '@hiveio/wax';

// Extend DatabaseApi with custom method
class DatabaseApi extends BaseDatabaseApi {
  @BaseDatabaseApi.endpointJsonrpc
  async get_config(): Promise<any> {}
}

// Add new BlockApi
class BlockApi extends AbstractApi {
  @AbstractApi.endpointJsonrpc
  async get_block_header(args: { block_num: number }): Promise<any> {}
}

// Create API collection
class MyApiCollection {
  database_api = DatabaseApi;
  block_api = BlockApi;
}

// Main application
async function main() {
  // Create base chain
  const chain = await createHiveChain();
  
  // Extend with custom APIs
  const wax = chain.extend(MyApiCollection);

  // Use standard API
  const accounts = await wax.api.database_api.find_accounts({
    accounts: ['alice', 'bob']
  });
  console.log('Accounts:', accounts.accounts.length);

  // Use extended database_api method
  const config = await wax.api.database_api.get_config();
  console.log('Node config:', config);

  // Use new block_api
  const header = await wax.api.block_api.get_block_header({
    block_num: 12345
  });
  console.log('Block header:', header);

  // Still can use chain methods
  const tx = await wax.createTransaction();
  tx.pushOperation({
    vote_operation: {
      voter: 'alice',
      author: 'bob',
      permlink: 'test-post',
      weight: 10000
    }
  });
}

main().catch(console.error);

Best practices

Define TypeScript interfaces or Python TypedDicts for request and response types.
interface MyRequest {
  param1: string;
  param2: number;
}

interface MyResponse {
  result: string;
}

async myMethod(args: MyRequest): Promise<MyResponse> {}
Group related API extensions together and use meaningful names.
// Good organization
class EnhancedDatabaseApi extends DatabaseApi { ... }
class CustomAnalyticsApi extends AbstractApi { ... }
class CustomNotificationApi extends AbstractApi { ... }

class MyApiCollection {
  database_api = EnhancedDatabaseApi;
  analytics_api = CustomAnalyticsApi;
  notification_api = CustomNotificationApi;
}
API class names must match the exact JSON-RPC namespace with snake_case converted to PascalCase.
// Correct
class BlockApi { }        // Maps to block_api
class DatabaseApi { }     // Maps to database_api
class ReputationApi { }   // Maps to reputation_api

// Incorrect
class Block { }           // Won't map correctly
class DB_Api { }          // Wrong naming
Ensure your custom endpoints work correctly with different parameters.
// Test with various inputs
const tests = [
  { block_num: 1 },
  { block_num: 12345 },
  { block_num: 99999999 }
];

for (const test of tests) {
  try {
    const result = await api.block_api.get_block_header(test);
    console.log('✓ Test passed:', test);
  } catch (error) {
    console.error('✗ Test failed:', test, error);
  }
}

Next steps

Formatters

Learn how to format API responses for display

API reference

Explore available Hive API endpoints

Custom operations

Create custom complex operations

TypeScript SDK

Full guide to making API calls

Build docs developers (and LLMs) love