Skip to main content
Transactions are the core building blocks for interacting with the Hive blockchain. This guide shows you how to create transactions with different types of operations.

Basic Transaction Flow

1

Import the Transaction class

import { Transaction, PrivateKey } from 'hive-tx'
2

Create a new transaction

const tx = new Transaction()
You can optionally set a custom expiration time (in milliseconds):
const tx = new Transaction({ expiration: 120_000 }) // 2 minutes
Default expiration is 60 seconds (60,000 ms). Maximum is 24 hours (86,400,000 ms).
3

Add operations to the transaction

Use addOperation() to add operations. This method automatically creates the transaction structure on first call:
await tx.addOperation('transfer', {
  from: 'alice',
  to: 'bob',
  amount: '1.000 HIVE',
  memo: 'Payment for services'
})
4

Sign and broadcast

const privateKey = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')
tx.sign(privateKey)
const result = await tx.broadcast()
console.log('Transaction ID:', result.tx_id)

Transfer Operation

Send HIVE or HBD tokens between accounts:
import { Transaction, PrivateKey } from 'hive-tx'

const tx = new Transaction()

await tx.addOperation('transfer', {
  from: 'alice',
  to: 'bob',
  amount: '1.000 HIVE',
  memo: 'Thanks for the help!'
})

const key = PrivateKey.fromLogin('alice', 'password', 'active')
tx.sign(key)
await tx.broadcast()
For transfers, you need the account’s active key.

Vote Operation

Upvote or downvote content:
const tx = new Transaction()

// Upvote at 100%
await tx.addOperation('vote', {
  voter: 'alice',
  author: 'bob',
  permlink: 'my-awesome-post',
  weight: 10000 // 100% = 10000, 50% = 5000
})

// Downvote at 50%
await tx.addOperation('vote', {
  voter: 'alice',
  author: 'spammer',
  permlink: 'spam-post',
  weight: -5000 // negative for downvote
})

const key = PrivateKey.fromLogin('alice', 'password', 'posting')
tx.sign(key)
await tx.broadcast()
Vote weight ranges from -10000 (100% downvote) to 10000 (100% upvote). Use posting key for voting.

Comment Operation

Create posts and comments:
const tx = new Transaction()

// Create a new post
await tx.addOperation('comment', {
  parent_author: '',
  parent_permlink: 'hive', // category/tag
  author: 'alice',
  permlink: 'my-first-post',
  title: 'My First Post',
  body: 'Hello Hive! This is my first post.',
  json_metadata: JSON.stringify({
    tags: ['hive', 'introduction'],
    app: 'my-app/1.0'
  })
})

const key = PrivateKey.fromLogin('alice', 'password', 'posting')
tx.sign(key)
await tx.broadcast()
Create a comment (reply):
const tx = new Transaction()

await tx.addOperation('comment', {
  parent_author: 'bob',
  parent_permlink: 'bobs-post',
  author: 'alice',
  permlink: 're-bobs-post-20240101',
  title: '',
  body: 'Great post! Thanks for sharing.',
  json_metadata: JSON.stringify({ app: 'my-app/1.0' })
})

const key = PrivateKey.fromLogin('alice', 'password', 'posting')
tx.sign(key)
await tx.broadcast()

Custom JSON Operation

Execute custom operations for apps and games:
const tx = new Transaction()

await tx.addOperation('custom_json', {
  required_auths: [], // Use for active authority
  required_posting_auths: ['alice'], // Use for posting authority
  id: 'follow', // operation ID
  json: JSON.stringify([
    'follow',
    {
      follower: 'alice',
      following: 'bob',
      what: ['blog'] // can be ['blog'], ['ignore'], or []
    }
  ])
})

const key = PrivateKey.fromLogin('alice', 'password', 'posting')
tx.sign(key)
await tx.broadcast()

Delegate Vesting Shares

Delegate HIVE Power to another account:
const tx = new Transaction()

await tx.addOperation('delegate_vesting_shares', {
  delegator: 'alice',
  delegatee: 'bob',
  vesting_shares: '1000.000000 VESTS' // Use VESTS, not HP
})

const key = PrivateKey.fromLogin('alice', 'password', 'active')
tx.sign(key)
await tx.broadcast()
Delegation amounts must be in VESTS, not HIVE Power. Use conversion APIs to calculate VESTS from HP.

Multiple Operations in One Transaction

You can add multiple operations to a single transaction:
const tx = new Transaction()

// Upvote a post
await tx.addOperation('vote', {
  voter: 'alice',
  author: 'bob',
  permlink: 'great-post',
  weight: 10000
})

// Leave a comment
await tx.addOperation('comment', {
  parent_author: 'bob',
  parent_permlink: 'great-post',
  author: 'alice',
  permlink: 're-great-post',
  title: '',
  body: 'Excellent work!',
  json_metadata: '{}'
})

const key = PrivateKey.fromLogin('alice', 'password', 'posting')
tx.sign(key)
await tx.broadcast()

Transaction Expiration

Control when your transaction expires:
// Expire in 30 seconds
const tx1 = new Transaction({ expiration: 30_000 })

// Expire in 5 minutes
const tx2 = new Transaction({ expiration: 300_000 })

// Expire in 1 hour
const tx3 = new Transaction({ expiration: 3_600_000 })
Transactions that haven’t been included in a block when they expire will be dropped from the mempool.

Error Handling

Always wrap transaction creation and broadcasting in try-catch blocks:
import { Transaction, PrivateKey, RPCError } from 'hive-tx'

try {
  const tx = new Transaction()
  
  await tx.addOperation('transfer', {
    from: 'alice',
    to: 'bob',
    amount: '1.000 HIVE',
    memo: 'Payment'
  })
  
  const key = PrivateKey.from('5J...')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Success! TX ID:', result.tx_id)
  
} catch (error) {
  if (error instanceof RPCError) {
    console.error('RPC Error:', error.message)
    console.error('Error code:', error.code)
    console.error('Error data:', error.data)
  } else {
    console.error('Error:', error.message)
  }
}

Common Errors

Missing Required Authority: Ensure you’re using the correct key type (posting, active, or owner) for your operation.
Insufficient Funds: Check account balance before transferring or delegating.
Invalid Operation Data: Verify all required fields are present and formatted correctly.

Next Steps

Build docs developers (and LLMs) love