Skip to main content

What are operations

Operations are the fundamental building blocks of Hive blockchain transactions. Each operation represents a specific action you want to perform on the blockchain, such as transferring funds, voting on content, or updating account settings.
Think of operations as instructions that modify the blockchain state. When bundled into a transaction and broadcast, they execute atomically.

Protocol buffers

WAX uses Protocol Buffers (protobuf) as the canonical format for representing operations and blockchain types. These definitions come directly from the Hive blockchain source code.

Why Protocol Buffers?

Type Safety

Strong typing ensures your operations are correctly structured before they reach the blockchain

Efficiency

Compact binary serialization reduces bandwidth and storage requirements

Cross-Language

Single source of truth works across TypeScript, Python, and C++

Validation

Built-in validation ensures operations meet protocol requirements

Source location

All protocol definitions originate from the Hive blockchain repository:
hive/libraries/protocol/proto/
├── transaction.proto
├── operation.proto
├── vote.proto
├── transfer.proto
├── comment.proto
└── ... (100+ operation types)

Operation structure

Every operation follows a consistent structure with required and optional fields:
// Vote operation definition
export interface vote {
  voter: string;      // Account name
  author: string;     // Post author
  permlink: string;   // Post identifier
  weight: number;     // -10000 to 10000
}

// Transfer operation definition
export interface transfer {
  from: string;              // Sender account
  to: string;                // Recipient account
  amount: asset | undefined; // Amount to transfer
  memo: string;              // Optional memo
}

Common operations

Here are the most frequently used operations:

Vote operation

Upvote or downvote content on the blockchain.
tx.pushOperation({
  vote_operation: {
    voter: "alice",
    author: "bob",
    permlink: "example-post",
    weight: 10000  // 100% upvote
  }
});

// Downvote
tx.pushOperation({
  vote_operation: {
    voter: "alice",
    author: "spam-account",
    permlink: "spam-post",
    weight: -10000  // 100% downvote
  }
});
Fields:
  • voter: Account casting the vote
  • author: Author of the content
  • permlink: Unique identifier for the content
  • weight: Vote strength from -10000 (100% downvote) to 10000 (100% upvote)

Transfer operation

Transfer HIVE or HBD between accounts.
// Transfer HIVE
tx.pushOperation({
  transfer_operation: {
    from: "alice",
    to: "bob",
    amount: chain.hive(10.5),  // 10.5 HIVE
    memo: "Payment for services"
  }
});

// Transfer HBD
tx.pushOperation({
  transfer_operation: {
    from: "alice",
    to: "bob",
    amount: chain.hbd(25),  // 25 HBD
    memo: "Invoice #12345"
  }
});
Fields:
  • from: Sender account name
  • to: Recipient account name
  • amount: Asset amount (HIVE or HBD)
  • memo: Optional message (max 2048 characters, can be encrypted)
When a memo starts with #, WAX automatically encrypts it using the accounts’ memo keys.

Comment operation

Create posts and comments.
// Create a post
tx.pushOperation({
  comment_operation: {
    parent_author: "",
    parent_permlink: "blog",
    author: "alice",
    permlink: "my-first-post",
    title: "Hello Hive!",
    body: "This is my first post on Hive.",
    json_metadata: JSON.stringify({
      tags: ["introduction", "hive"],
      app: "myapp/1.0.0"
    })
  }
});

// Create a comment
tx.pushOperation({
  comment_operation: {
    parent_author: "bob",
    parent_permlink: "example-post",
    author: "alice",
    permlink: "re-example-post-20260304",
    title: "",
    body: "Great post!",
    json_metadata: ""
  }
});

Custom JSON operation

Execute custom application logic.
tx.pushOperation({
  custom_json_operation: {
    id: "follow",
    json: JSON.stringify([
      "follow",
      {
        follower: "alice",
        following: "bob",
        what: ["blog"]
      }
    ]),
    required_auths: [],
    required_posting_auths: ["alice"]
  }
});

Operation naming conventions

Operation names differ between the protocol definition and the runtime usage. Be aware of the _operation suffix.

TypeScript

In TypeScript, operations use the _operation suffix when pushed to transactions:
import { vote } from "@hiveio/wax";

// Import uses the base name
import type { vote } from "@hiveio/wax";

// Push uses the _operation suffix
tx.pushOperation({
  vote_operation: {
    voter: "alice",
    author: "bob",
    permlink: "post",
    weight: 10000
  }
});

Python

In Python, the proto classes use the base name, but the runtime expects the _operation suffix:
from wax.proto.operations import vote

# Import the class without suffix
vote_op = vote(
    voter="alice",
    author="bob",
    permlink="post",
    weight=10000
)

# Push operation (handled internally)
tx.push_operation(vote_op)

Complex operations

WAX provides high-level builders for operations that require multiple fields or complex logic:

Account update operation

import { AccountUpdateBuilder } from "@hiveio/wax";

const accountUpdate = new AccountUpdateBuilder("alice")
  .updatePosting({
    account_auths: {},
    key_auths: {
      "STM6vJmrwaX5TjgTS9dPH8KsArso5m91fVodJvv91j7G765wqcNM9": 1
    },
    weight_threshold: 1
  })
  .updateMemo("STM5VJ9YJH7r6pAQmvjN3pUbdwLqQ6CjQMhC7vLPapj4KPvChqKnH");

tx.pushOperation(accountUpdate);

Recurrent transfer operation

import { RecurrentTransferBuilder } from "@hiveio/wax";

const recurrent = new RecurrentTransferBuilder()
  .setFrom("alice")
  .setTo("bob")
  .setAmount(chain.hive(10))
  .setMemo("Monthly payment")
  .setRecurrence(24)  // Every 24 hours
  .setExecutions(30); // 30 times

tx.pushOperation(recurrent);

Creating custom operation builders

You can create your own operation builders for reusable operation patterns:
ts/wasm/lib/detailed/operation_base.ts
import { OperationBase, type IOperationSink, type operation } from "@hiveio/wax";

export class MyCustomOperation extends OperationBase {
  private operations: operation[] = [];
  
  constructor(
    public readonly account: string,
    public readonly target: string
  ) {
    super();
  }
  
  public finalize(sink: IOperationSink): Iterable<operation> {
    // Build your operations here
    this.operations.push({
      custom_json_operation: {
        id: "my-app",
        json: JSON.stringify({
          account: this.account,
          target: this.target
        }),
        required_auths: [],
        required_posting_auths: [this.account]
      }
    });
    
    return this.operations;
  }
}

// Usage
const op = new MyCustomOperation("alice", "bob");
tx.pushOperation(op);

Operation validation

Operations are validated at multiple levels:

Protocol-level validation

The C++ core validates:
  • Field types and formats
  • Account name validity
  • Asset precision and amounts
  • String length limits
  • Required field presence

Application-level validation

Your code should validate:
  • Business logic requirements
  • User permissions
  • Balance sufficiency
  • Rate limiting
try {
  tx.pushOperation({
    transfer_operation: {
      from: "alice",
      to: "bob",
      amount: chain.hive(10),
      memo: "Payment"
    }
  });
  
  tx.validate();
} catch (error) {
  if (error.message.includes("insufficient")) {
    console.error("Not enough balance");
  }
}

Asset types

Many operations work with asset types (HIVE, HBD, VESTS):
// Create assets
const hive = chain.hive(10.5);        // 10.500 HIVE
const hbd = chain.hbd(25);            // 25.000 HBD
const vests = chain.vests(1000000);   // 1000000.000000 VESTS

// From satoshis/smallest unit
const hive2 = chain.hiveFromSatoshis(10500);  // 10.500 HIVE

// Asset structure
interface asset {
  amount: string;  // "10500" (in satoshis)
  precision: number;  // 3 for HIVE/HBD, 6 for VESTS
  nai: string;  // "@@000000021" for HIVE
}

Operation categories

Operations are organized into several categories:
  • account_create
  • account_update
  • account_update2
  • account_witness_vote
  • account_witness_proxy
  • transfer
  • transfer_to_vesting
  • transfer_to_savings
  • transfer_from_savings
  • recurrent_transfer
  • comment
  • vote
  • delete_comment
  • comment_options
  • limit_order_create
  • limit_order_create2
  • limit_order_cancel
  • convert
  • collateralized_convert
  • witness_update
  • witness_set_properties
  • feed_publish
  • create_proposal
  • update_proposal_votes
  • remove_proposal

Next steps

Signing

Learn how to sign transactions with operations

Transactions

Understand transaction structure and lifecycle

API Reference

Browse all available operations

Examples

See operations in action

Build docs developers (and LLMs) love