> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mahdiyari/hive-tx/llms.txt
> Use this file to discover all available pages before exploring further.

# Transactions

> Learn how to create, sign, and broadcast transactions on the Hive blockchain

Transactions are the fundamental unit of interaction with the Hive blockchain. The `Transaction` class provides a complete lifecycle for creating, signing, and broadcasting operations.

## Transaction Lifecycle

Every transaction follows this sequence:

1. **Create** - Initialize a transaction with default or custom expiration
2. **Add Operations** - Append one or more operations to execute
3. **Sign** - Sign with one or more private keys
4. **Broadcast** - Submit to the Hive network

<Steps>
  <Step title="Create Transaction">
    ```typescript theme={null}
    import { Transaction } from 'hive-tx'

    // Default 60 second expiration
    const tx = new Transaction()

    // Custom expiration (3 minutes)
    const txCustom = new Transaction({ expiration: 180_000 })
    ```
  </Step>

  <Step title="Add Operations">
    ```typescript theme={null}
    // Add a vote operation
    await tx.addOperation('vote', {
    voter: 'alice',
    author: 'bob',
    permlink: 'awesome-post',
    weight: 10000  // 100% upvote
    })

    // Add more operations to the same transaction
    await tx.addOperation('transfer', {
    from: 'alice',
    to: 'bob',
    amount: '1.000 HIVE',
    memo: 'Thanks for the post!'
    })
    ```
  </Step>

  <Step title="Sign Transaction">
    ```typescript theme={null}
    import { PrivateKey } from 'hive-tx'

    const key = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')
    tx.sign(key)
    ```
  </Step>

  <Step title="Broadcast">
    ```typescript theme={null}
    // Broadcast and return immediately
    const result = await tx.broadcast()
    console.log(result.tx_id) // Transaction ID

    // Broadcast and wait for confirmation
    const confirmedResult = await tx.broadcast(true)
    console.log(confirmedResult.status) // 'within_irreversible_block'
    ```
  </Step>
</Steps>

## Transaction Structure

Under the hood, a Hive transaction contains these fields:

<ResponseField name="expiration" type="string" required>
  ISO 8601 timestamp when the transaction expires (max 24 hours from creation)
</ResponseField>

<ResponseField name="ref_block_num" type="number" required>
  Lower 16 bits of reference block number (prevents replay attacks)
</ResponseField>

<ResponseField name="ref_block_prefix" type="number" required>
  Reference block prefix derived from head block ID
</ResponseField>

<ResponseField name="operations" type="Operation[]" required>
  Array of operations to execute, each formatted as `[operationName, operationBody]`
</ResponseField>

<ResponseField name="extensions" type="Extension[]" default="[]">
  Optional protocol extensions (rarely used)
</ResponseField>

<ResponseField name="signatures" type="string[]" required>
  Array of hex-encoded signatures (added when you call `sign()`)
</ResponseField>

<Info>
  The `ref_block_num` and `ref_block_prefix` are automatically set from the current head block when you call `addOperation()`. This ties your transaction to recent blockchain state and prevents replay attacks.
</Info>

## Creating Transactions

You can create a transaction in two ways:

### With Default Expiration

By default, transactions expire 60 seconds after creation:

```typescript theme={null}
const tx = new Transaction()
// Expiration: 60_000ms (60 seconds)
```

### With Custom Expiration

Set a custom expiration in milliseconds (max 86400000ms = 24 hours):

```typescript theme={null}
// 5 minute expiration
const tx = new Transaction({ expiration: 300_000 })

// 1 hour expiration
const tx = new Transaction({ expiration: 3_600_000 })
```

<Warning>
  Transactions expire after the specified time. If broadcast fails or is delayed, the transaction becomes invalid after expiration.
</Warning>

## Transaction Digest and ID

The transaction digest is a SHA256 hash used for signing. The transaction ID is derived from this digest.

### Getting the Digest

```typescript src/Transaction.ts:153 theme={null}
const { digest, txId } = tx.digest()

console.log(txId)    // First 40 hex characters of SHA256(transaction)
console.log(digest)  // SHA256(chainId + transaction) as Uint8Array
```

The digest combines:

* **Chain ID** - Hive mainnet identifier (`beeab0de...`)
* **Serialized Transaction** - Binary representation of the transaction

This ensures signatures are valid only for the specific transaction on the specific chain.

## Multi-Signature Transactions

Sign with multiple keys by passing an array or calling `sign()` multiple times:

### Sign All at Once

```typescript theme={null}
const key1 = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41Ek...')
const key2 = PrivateKey.from('5HqNQNxcfq7Y84fLk8RVpC...')

tx.sign([key1, key2])
```

### Sign Incrementally

```typescript theme={null}
// Sign with first key
tx.sign(activeKey)

// Later, sign with second key
tx.sign(postingKey)

// Both signatures are added to transaction.signatures[]
```

<Tip>
  Use incremental signing when keys are held by different parties or when you need to sign at different times.
</Tip>

## Broadcasting Transactions

The `broadcast()` method submits your signed transaction to the Hive network.

### Quick Broadcast

Return immediately after submission (status may be unknown):

```typescript src/Transaction.ts:106 theme={null}
const result = await tx.broadcast()
// { tx_id: '...', status: 'unknown' }
```

### Confirmed Broadcast

Wait for the transaction to be included in an irreversible block:

```typescript theme={null}
const result = await tx.broadcast(true)
// { tx_id: '...', status: 'within_irreversible_block' }
```

Possible status values:

* `unknown` - Broadcast succeeded but status not checked
* `within_mempool` - Waiting in transaction pool
* `within_reversible_block` - In a block but not yet irreversible
* `within_irreversible_block` - Permanently confirmed
* `expired_reversible` - Expired before becoming irreversible
* `expired_irreversible` - Expired after being irreversible
* `too_old` - Transaction is too old to check

<Warning>
  Broadcasting with `checkStatus=false` does not guarantee the transaction will be included in a block. It may expire in the mempool.
</Warning>

## Checking Transaction Status

Manually check a transaction's status using `checkStatus()`:

```typescript src/Transaction.ts:193 theme={null}
await tx.broadcast()

// Check status later
const status = await tx.checkStatus()
console.log(status.status) // Current transaction status
```

## Adding External Signatures

If you sign transactions with external tools (hardware wallets, etc.), add signatures manually:

```typescript src/Transaction.ts:178 theme={null}
const signature = '1f4c3d2e...' // 130-character hex string
tx.addSignature(signature)
```

<Info>
  Signatures must be exactly 130 hex characters (65 bytes). This includes the recovery byte and the 64-byte ECDSA signature.
</Info>

## Error Handling

Common errors and solutions:

### No Operations

```typescript theme={null}
try {
  await tx.broadcast()
} catch (e) {
  // Error: Attempted to broadcast an empty transaction
  // Solution: Call addOperation() first
}
```

### No Signatures

```typescript theme={null}
try {
  await tx.broadcast()
} catch (e) {
  // Error: Attempted to broadcast a transaction with no signatures
  // Solution: Call sign(key) before broadcasting
}
```

### Duplicate Transaction

The SDK automatically handles duplicate transaction errors when retrying broadcasts.

## Complete Example

Here's a complete transaction workflow:

```typescript theme={null}
import { Transaction, PrivateKey } from 'hive-tx'

async function publishPost() {
  // Create transaction with 5 minute expiration
  const tx = new Transaction({ expiration: 300_000 })
  
  // Add comment operation
  await tx.addOperation('comment', {
    parent_author: '',
    parent_permlink: 'hive',
    author: 'alice',
    permlink: 'my-first-post',
    title: 'Hello Hive!',
    body: 'This is my first post on Hive.',
    json_metadata: JSON.stringify({ tags: ['hive', 'introduction'] })
  })
  
  // Add comment options for beneficiaries
  await tx.addOperation('comment_options', {
    author: 'alice',
    permlink: 'my-first-post',
    max_accepted_payout: '1000000.000 HBD',
    percent_hbd: 10000,
    allow_votes: true,
    allow_curation_rewards: true,
    extensions: [[
      { account: 'bob', weight: 2500 } // 25% beneficiary
    ]]
  })
  
  // Sign with posting key
  const postingKey = PrivateKey.fromLogin('alice', 'password', 'posting')
  tx.sign(postingKey)
  
  // Broadcast and wait for confirmation
  const result = await tx.broadcast(true)
  console.log(`Post published! TX ID: ${result.tx_id}`)
  console.log(`Status: ${result.status}`)
}

publishPost()
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Operations" icon="layer-group" href="/concepts/operations">
    Learn about all available Hive operations
  </Card>

  <Card title="Keys & Signatures" icon="key" href="/concepts/keys-and-signatures">
    Understand cryptographic operations
  </Card>

  <Card title="Transaction API" icon="code" href="/api/transaction">
    Full API reference for Transaction class
  </Card>

  <Card title="Voting Guide" icon="thumbs-up" href="/examples/voting">
    Build a voting application
  </Card>
</CardGroup>
