Basic operations
Vote on a post
import { createHiveChain } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
// Initialize chain and wallet
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("my-salt");
const { wallet } = await session.createWallet("my-wallet", "password");
// Import posting key
const postingKey = await wallet.importKey("5JWcdkhS...");
// Create transaction
const tx = await chain.createTransaction();
// Add vote operation
tx.pushOperation({
vote: {
voter: "alice",
author: "bob",
permlink: "my-awesome-post",
weight: 10000 // 100%
}
});
// Sign and broadcast
const signature = await wallet.signDigest(tx.sigDigest, postingKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log(`Vote transaction ${tx.id} broadcasted!`);
Transfer HIVE
import { createHiveChain } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
// Import active key (required for transfers)
const activeKey = await wallet.importKey("5JWcdkhS...");
// Create transaction
const tx = await chain.createTransaction();
// Add transfer operation
tx.pushOperation({
transfer: {
from_account: "alice",
to_account: "bob",
amount: chain.hiveCoins(10),
memo: "Thanks for the help!"
}
});
// Sign with active key
const signature = await wallet.signDigest(tx.sigDigest, activeKey);
tx.addSignature(signature);
// Broadcast
await chain.broadcast(tx);
console.log("Transfer successful!");
Query account information
import { createHiveChain, EManabarType } from "@hiveio/wax";
const chain = await createHiveChain();
// Get account data
const accountData = await chain.api.database_api.find_accounts({
accounts: ["alice"],
delayed_votes_active: true
});
const account = accountData.accounts[0];
// Get dynamic global properties for current time
const props = await chain.api.database_api.get_dynamic_global_properties({});
const now = new Date(props.time).getTime() / 1000;
// Display account information
console.log(`Account: ${account.name}`);
console.log(`Balance: ${account.balance}`);
console.log(`HBD: ${account.hbd_balance}`);
console.log(`VESTS: ${account.vesting_shares}`);
// Calculate voting manabar
const upvoteManabar = chain.calculateAccountMana(account, now, EManabarType.UPVOTE);
console.log(`Upvote mana: ${upvoteManabar.percent.toFixed(2)}%`);
const downvoteManabar = chain.calculateAccountMana(account, now, EManabarType.DOWNVOTE);
console.log(`Downvote mana: ${downvoteManabar.percent.toFixed(2)}%`);
// Get RC information
const rcData = await chain.api.rc_api.find_rc_accounts({
accounts: ["alice"]
});
if (rcData.rc_accounts.length > 0) {
const rc = rcData.rc_accounts[0];
const rcManabar = chain.calculateCurrentManabarValue(
now,
rc.max_rc,
rc.rc_manabar.current_mana,
rc.rc_manabar.last_update_time
);
console.log(`RC mana: ${rcManabar.percent.toFixed(2)}%`);
}
Blog operations
Create a blog post
import { createHiveChain, BlogPostOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const postingKey = await wallet.importKey("5JWcdkhS...");
// Create transaction
const tx = await chain.createTransaction();
// Add blog post operation
tx.pushOperation(new BlogPostOperation({
author: "alice",
permlink: "my-first-post-2024",
title: "My First Post on Hive",
body: "# Welcome\\n\\nThis is my first post on Hive blockchain!\\n\\nI'm excited to join this community.",
category: "hive-174695", // Community ID or main tag
tags: ["introduceyourself", "firstpost", "blog"],
description: "My introduction to the Hive community",
format: "markdown",
beneficiaries: [
{ account: "bob", weight: 500 } // 5% to bob
]
}));
// Sign and broadcast
const signature = await wallet.signDigest(tx.sigDigest, postingKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log(`Post created: ${tx.id}`);
Reply to a comment
import { createHiveChain, ReplyOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const postingKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Reply to a post or comment
tx.pushOperation(new ReplyOperation({
parentAuthor: "bob",
parentPermlink: "some-interesting-post",
author: "alice",
permlink: "re-some-interesting-post-20240101",
body: "Great post! Thanks for sharing this valuable information.",
title: "" // Usually empty for comments
}));
const signature = await wallet.signDigest(tx.sigDigest, postingKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Reply posted!");
Account management
Update account authority
import { createHiveChain, AccountAuthorityUpdateOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
// Import owner key (required for authority changes)
const ownerKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Update posting authority
tx.pushOperation(
new AccountAuthorityUpdateOperation({
accountName: "alice"
})
.addKeyPostingAuth("STM8ZSw7KjYWJoVvffQLCxj3iLkMHUB7ToyqEYvYj2kH8XdDH3MSL", 1)
.addAccountPostingAuth("bob", 1)
.updatePostingAuthorityThreshold(1)
);
const signature = await wallet.signDigest(tx.sigDigest, ownerKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Authority updated!");
Delegate resource credits
import { createHiveChain, ResourceCreditsOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const activeKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Delegate RC to another account
tx.pushOperation(
new ResourceCreditsOperation("alice")
.delegate("bob", chain.vestsCoins(1000))
);
const signature = await wallet.signDigest(tx.sigDigest, activeKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("RC delegated!");
Advanced operations
Create recurrent transfer
import { createHiveChain, DefineRecurrentTransferOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const activeKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Create recurring transfer
tx.pushOperation(new DefineRecurrentTransferOperation({
from: "alice",
to: "bob",
amount: chain.hiveCoins(10),
memo: "Monthly subscription payment",
recurrence: 24, // Every 24 hours
executions: 30, // 30 transfers total
pairId: 1 // Unique identifier
}));
const signature = await wallet.signDigest(tx.sigDigest, activeKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Recurrent transfer created!");
Update witness properties
import { createHiveChain, WitnessSetPropertiesOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const activeKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Update witness properties
tx.pushOperation(
new WitnessSetPropertiesOperation("alice")
.update("account_creation_fee", chain.hiveCoins(3))
.update("hbd_interest_rate", 1000) // 10%
.update("url", "https://mywitness.example.com")
);
const signature = await wallet.signDigest(tx.sigDigest, activeKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Witness properties updated!");
Community operations
Subscribe to community
import { createHiveChain, CommunityOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const postingKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Subscribe to community
tx.pushOperation(
new CommunityOperation("alice")
.subscribe("hive-174695")
);
const signature = await wallet.signDigest(tx.sigDigest, postingKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Subscribed to community!");
Follow/unfollow accounts
import { createHiveChain, FollowOperation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const chain = await createHiveChain();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
const postingKey = await wallet.importKey("5JWcdkhS...");
const tx = await chain.createTransaction();
// Follow an account
tx.pushOperation(
new FollowOperation("alice")
.follow("bob", ["blog"])
);
const signature = await wallet.signDigest(tx.sigDigest, postingKey);
tx.addSignature(signature);
await chain.broadcast(tx);
console.log("Now following bob!");
Custom operations
Create custom game operation
import { createHiveChain, OperationBase, IOperationSink, operation } from "@hiveio/wax";
// Define custom operation class
class SplinterlandsGame extends OperationBase {
private readonly operations: operation[] = [];
constructor(public readonly player: string) {
super();
}
public finalize(_sink: IOperationSink): Iterable<operation> {
return this.operations;
}
public enterTournament(tournamentId: string): this {
this.operations.push({
custom_json_operation: {
id: "sm_enter_tournament",
json: JSON.stringify({
tournament_id: tournamentId,
app: "splinterlands/0.7.139"
}),
required_auths: [],
required_posting_auths: [this.player]
}
});
return this;
}
public stakeTokens(amount: number): this {
this.operations.push({
custom_json_operation: {
id: "sm_stake_tokens",
json: JSON.stringify({
qty: amount.toFixed(3),
token: "SPS",
app: "splinterlands/0.7.139"
}),
required_auths: [],
required_posting_auths: [this.player]
}
});
return this;
}
}
// Use the custom operation
const chain = await createHiveChain();
const tx = await chain.createTransaction();
const game = new SplinterlandsGame("alice");
game.enterTournament("tournament-123").stakeTokens(10);
tx.pushOperation(game);
console.log(`Transaction has ${tx.transaction.operations.length} operations`);
Block exploration
Fetch and parse blocks
import { createHiveChain } from "@hiveio/wax";
const chain = await createHiveChain();
// Get current head block
const props = await chain.api.database_api.get_dynamic_global_properties({});
const headBlockNum = props.head_block_number;
console.log(`Current head block: ${headBlockNum}`);
// Fetch block
const blockData = await chain.api.block_api.get_block({
block_num: headBlockNum
});
const block = blockData.block;
console.log(`\nBlock ${block.block_id}`);
console.log(`Witness: ${block.witness}`);
console.log(`Time: ${block.timestamp}`);
console.log(`Transactions: ${block.transactions.length}`);
// Parse transactions
for (const [idx, tx] of block.transactions.entries()) {
console.log(`\nTransaction #${idx + 1}:`);
console.log(` Operations: ${tx.operations.length}`);
for (const op of tx.operations) {
const opType = Object.keys(op)[0];
console.log(` - ${opType}`);
}
}
// Fetch block range
const rangeData = await chain.api.block_api.get_block_range({
starting_block_num: headBlockNum - 10,
count: 10
});
console.log(`\nFetched ${rangeData.blocks.length} blocks`);
Encryption
Encrypt memo in transfer
import { createWaxFoundation } from "@hiveio/wax";
import createBeekeeper from "@hiveio/wax-signers-beekeeper";
const wax = await createWaxFoundation();
const beekeeper = await createBeekeeper();
const session = beekeeper.createSession("salt");
const { wallet } = await session.createWallet("wallet", "password");
// Import keys
const aliceKey = await wallet.importKey("5JWcdkhS...");
const bobMemoKey = "STM7Abc..."; // Bob's memo public key
// Get head block ID from network
const headBlockId = "0129d3f75e53c4c8e35b52548f5f2e45b3e0c8b3";
// Create transaction with encryption
const tx = wax.createTransactionWithTaPoS(headBlockId);
tx
.startEncrypt(aliceKey, bobMemoKey)
.pushOperation({
transfer: {
from_account: "alice",
to_account: "bob",
amount: wax.hiveCoins(10),
memo: "This is a secret message" // Will be encrypted
}
})
.stopEncrypt();
console.log("Transaction with encrypted memo ready");
Key generation
Generate account keys
import { createWaxFoundation } from "@hiveio/wax";
const wax = await createWaxFoundation();
// Generate brain key
const brainKeyData = wax.suggestBrainKey();
console.log("Brain key:", brainKeyData.brainKey);
console.log("Private key:", brainKeyData.wifPrivateKey);
console.log("Public key:", brainKeyData.associatedPublicKey);
// Generate keys from password
const accountName = "alice";
const password = "MySecurePassword123";
const ownerKey = wax.getPrivateKeyFromPassword(accountName, "owner", password);
const activeKey = wax.getPrivateKeyFromPassword(accountName, "active", password);
const postingKey = wax.getPrivateKeyFromPassword(accountName, "posting", password);
const memoKey = wax.getPrivateKeyFromPassword(accountName, "memo", password);
console.log("\nGenerated keys for:", accountName);
console.log("Owner:", ownerKey.associatedPublicKey);
console.log("Active:", activeKey.associatedPublicKey);
console.log("Posting:", postingKey.associatedPublicKey);
console.log("Memo:", memoKey.associatedPublicKey);
Asset conversions
Convert between asset types
import { createHiveChain } from "@hiveio/wax";
const chain = await createHiveChain();
// Get conversion factors from chain
const props = await chain.api.database_api.get_dynamic_global_properties({});
const totalVestingFundHive = props.total_vesting_fund_hive;
const totalVestingShares = props.total_vesting_shares;
// Convert VESTS to HP
const vests = chain.vestsCoins(1000000);
const hp = chain.vestsToHp(vests, totalVestingFundHive, totalVestingShares);
const hpData = chain.getAsset(hp);
console.log(`1,000,000 VESTS = ${hpData.amount} ${hpData.symbol}`);
// Convert HP to VESTS
const hiveAmount = chain.hiveCoins(1000);
const vestsAmount = chain.hpToVests(hiveAmount, totalVestingFundHive, totalVestingShares);
const vestsData = chain.getAsset(vestsAmount);
console.log(`1,000 HP = ${vestsData.amount} ${vestsData.symbol}`);
// Get price feed
const feed = await chain.api.database_api.get_feed_history({});
const base = feed.current_median_history.base;
const quote = feed.current_median_history.quote;
// Convert HBD to HIVE
const hbd = chain.hbdCoins(100);
const hive = chain.hbdToHive(hbd, base, quote);
const hiveData = chain.getAsset(hive);
console.log(`100 HBD = ${hiveData.amount} ${hiveData.symbol}`);
React application example
Complete React component:App.tsx
import { useState, useEffect } from "react";
import { createHiveChain, type IHiveChainInterface } from "@hiveio/wax";
import type { ApiAccount } from "@hiveio/wax";
function App() {
const [chain, setChain] = useState<IHiveChainInterface | null>(null);
const [account, setAccount] = useState<ApiAccount | null>(null);
const [username, setUsername] = useState("alice");
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Initialize WAX
useEffect(() => {
createHiveChain()
.then((instance) => {
setChain(instance);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, []);
// Fetch account
const fetchAccount = async () => {
if (!chain) return;
setLoading(true);
setError(null);
try {
const result = await chain.api.database_api.find_accounts({
accounts: [username]
});
if (result.accounts.length === 0) {
setError("Account not found");
setAccount(null);
} else {
setAccount(result.accounts[0]);
}
} catch (err) {
setError((err as Error).message);
} finally {
setLoading(false);
}
};
if (loading && !chain) {
return <div>Loading WAX...</div>;
}
return (
<div style={{ padding: "20px" }}>
<h1>Hive Account Viewer</h1>
<div>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter username"
/>
<button onClick={fetchAccount}>Search</button>
</div>
{loading && <p>Loading...</p>}
{error && <p style={{ color: "red" }}>Error: {error}</p>}
{account && (
<div style={{ marginTop: "20px" }}>
<h2>{account.name}</h2>
<p><strong>Balance:</strong> {account.balance}</p>
<p><strong>HBD:</strong> {account.hbd_balance}</p>
<p><strong>VESTS:</strong> {account.vesting_shares}</p>
<p><strong>Created:</strong> {account.created}</p>
</div>
)}
</div>
);
}
export default App;
Next steps
Explore the SDK documentation:- Learn about offline operations
- Discover online operations
- Read about transaction building
- Study API calls
- Integrate with frameworks