> ## 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.

# Multi-Signature Transactions

> Complete guide to creating and signing multi-signature transactions on Hive

Multi-signature transactions allow multiple keys to sign the same transaction. This is useful for multi-sig accounts, escrow services, and collaborative operations.

## Multi-Signature Basics

Hive accounts can have multiple keys with different weights for each authority level (owner, active, posting). A transaction requires enough signature weight to meet the threshold.

### How Multi-Sig Works

1. **Authority Structure**: Each account has owner, active, and posting authorities with configurable thresholds
2. **Key Weights**: Each public key in an authority has a weight (default: 1)
3. **Threshold**: Minimum total weight required for authorization
4. **Signatures**: Transaction must collect enough signatures to meet or exceed threshold

<Note>
  For a standard account, the threshold is 1 and the single key has weight 1. Multi-sig accounts have thresholds greater than 1 or multiple keys.
</Note>

## Signing with Multiple Keys at Once

The simplest approach is to sign with all required keys in a single call:

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

// Create transaction
const tx = new Transaction()
await tx.addOperation('transfer', {
  from: 'multisig-account',
  to: 'alice',
  amount: '10.000 HIVE',
  memo: 'Multi-sig payment'
})

// Load multiple keys
const key1 = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')
const key2 = PrivateKey.from('5K...')
const key3 = PrivateKey.from('5H...')

// Sign with all keys at once
tx.sign([key1, key2, key3])

// Broadcast
const result = await tx.broadcast(true)
console.log('Transaction ID:', result.tx_id)
```

<Tip>
  Pass an array of PrivateKey objects to `.sign()` to add multiple signatures at once.
</Tip>

## Sequential Signing (Collecting Signatures)

For distributed multi-sig workflows, signatures can be collected sequentially:

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

    const tx = new Transaction()
    await tx.addOperation('transfer', {
      from: 'multisig-account',
      to: 'bob',
      amount: '5.000 HIVE',
      memo: 'Collaborative payment'
    })
    ```
  </Step>

  <Step title="First signer signs">
    ```typescript theme={null}
    import { PrivateKey } from 'hive-tx'

    const key1 = PrivateKey.from('5J...')
    tx.sign(key1)

    // Transaction now has 1 signature
    console.log('Signatures:', tx.transaction?.signatures.length) // 1
    ```
  </Step>

  <Step title="Serialize and send to next signer">
    ```typescript theme={null}
    // Get the transaction object
    const txData = tx.transaction

    // Send to next signer (e.g., via API, file, etc.)
    const serialized = JSON.stringify(txData)
    ```
  </Step>

  <Step title="Next signer adds their signature">
    ```typescript theme={null}
    // Receive transaction data
    const txData = JSON.parse(serialized)

    // Recreate transaction from data
    const tx2 = new Transaction({ transaction: txData })

    // Add second signature
    const key2 = PrivateKey.from('5K...')
    tx2.sign(key2)

    console.log('Signatures:', tx2.transaction?.signatures.length) // 2
    ```
  </Step>

  <Step title="Broadcast when enough signatures collected">
    ```typescript theme={null}
    // After all required signatures are added
    const result = await tx2.broadcast(true)
    console.log('Multi-sig transaction confirmed:', result.tx_id)
    ```
  </Step>
</Steps>

## Using addSignature Method

You can also add pre-computed signatures directly:

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

const tx = new Transaction()
await tx.addOperation('vote', {
  voter: 'multisig-account',
  author: 'alice',
  permlink: 'post',
  weight: 10000
})

// Sign externally and get signature string
const key = PrivateKey.from('5J...')
const { digest } = tx.digest()
const signature = key.sign(digest)

// Add signature directly (must be 130 character hex string)
tx.addSignature(signature.toString())

console.log('Signature added:', tx.transaction?.signatures.length)
```

<Note>
  The `addSignature()` method expects a 130-character hex signature string. Use this when working with external signing tools or hardware wallets.
</Note>

## Complete Multi-Sig Example

Here's a complete example of a 2-of-3 multi-signature workflow:

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

// Scenario: 3 parties control a multi-sig account
// Threshold: 2 signatures required

class MultiSigCoordinator {
  private tx?: Transaction
  
  // Party 1: Initialize transaction
  async initializeTransfer(from: string, to: string, amount: string) {
    this.tx = new Transaction({ expiration: 300_000 }) // 5 min expiry
    
    await this.tx.addOperation('transfer', {
      from,
      to,
      amount,
      memo: 'Multi-sig transfer'
    })
    
    return this.exportTransaction()
  }
  
  // Export for sharing with other signers
  exportTransaction(): string {
    if (!this.tx?.transaction) {
      throw new Error('No transaction to export')
    }
    return JSON.stringify(this.tx.transaction)
  }
  
  // Import transaction from another party
  importTransaction(txData: string) {
    const parsed = JSON.parse(txData)
    this.tx = new Transaction({ transaction: parsed })
  }
  
  // Sign with party's key
  sign(privateKey: PrivateKey) {
    if (!this.tx) {
      throw new Error('No transaction loaded')
    }
    this.tx.sign(privateKey)
    
    const sigCount = this.tx.transaction?.signatures.length || 0
    console.log(`Signed. Total signatures: ${sigCount}`)
  }
  
  // Check if enough signatures
  hasEnoughSignatures(required: number): boolean {
    const count = this.tx?.transaction?.signatures.length || 0
    return count >= required
  }
  
  // Broadcast when ready
  async broadcast() {
    if (!this.tx) {
      throw new Error('No transaction to broadcast')
    }
    
    return await this.tx.broadcast(true)
  }
}

// Usage:

// Party 1: Create and sign
const coordinator1 = new MultiSigCoordinator()
const txData1 = await coordinator1.initializeTransfer(
  'multisig-account',
  'alice',
  '100.000 HIVE'
)

const party1Key = PrivateKey.from('5J...')
coordinator1.sign(party1Key)

// Send transaction to Party 2
const serialized = coordinator1.exportTransaction()

// Party 2: Import and sign
const coordinator2 = new MultiSigCoordinator()
coordinator2.importTransaction(serialized)

const party2Key = PrivateKey.from('5K...')
coordinator2.sign(party2Key)

// Check if enough signatures (2 required)
if (coordinator2.hasEnoughSignatures(2)) {
  console.log('Threshold reached! Broadcasting...')
  const result = await coordinator2.broadcast()
  console.log('Success:', result.tx_id)
} else {
  // Need Party 3's signature
  const serialized2 = coordinator2.exportTransaction()
  // Send to Party 3...
}
```

## Multi-Sig Account Setup

To create a multi-sig account authority structure:

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

// Get public keys for the three parties
const pubkey1 = PublicKey.fromString('STM...')
const pubkey2 = PublicKey.fromString('STM...')
const pubkey3 = PublicKey.fromString('STM...')

// Update account with 2-of-3 multi-sig active authority
const tx = new Transaction()
await tx.addOperation('account_update', {
  account: 'myaccount',
  active: {
    weight_threshold: 2,  // Require 2 signatures
    account_auths: [],
    key_auths: [
      [pubkey1, 1],  // Key 1 has weight 1
      [pubkey2, 1],  // Key 2 has weight 1
      [pubkey3, 1]   // Key 3 has weight 1
    ]
  },
  memo_key: 'STM...',  // unchanged
  json_metadata: ''
})

// Sign with current owner key
const ownerKey = PrivateKey.from('5H...')
tx.sign(ownerKey)
await tx.broadcast(true)

console.log('Account updated to 2-of-3 multi-sig')
```

<Warning>
  Always test multi-sig configurations on testnet first! Incorrect setup can lock you out of your account.
</Warning>

## Weighted Multi-Sig

You can assign different weights to different keys:

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

// Setup: CEO key has weight 3, CFO has weight 2, others have weight 1
// Threshold: 3 required

const tx = new Transaction()
await tx.addOperation('account_update', {
  account: 'company-account',
  active: {
    weight_threshold: 3,
    account_auths: [],
    key_auths: [
      ['STM_CEO_PUBKEY', 3],      // CEO can sign alone (3 >= 3)
      ['STM_CFO_PUBKEY', 2],      // CFO + any other (2+1 >= 3)
      ['STM_MANAGER1_PUBKEY', 1], // Needs 3 managers or CFO+manager
      ['STM_MANAGER2_PUBKEY', 1],
      ['STM_MANAGER3_PUBKEY', 1]
    ]
  },
  memo_key: 'STM...',
  json_metadata: ''
})
```

## Transaction Expiration in Multi-Sig

For multi-sig workflows, consider longer expiration:

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

// Give parties more time to sign
const tx = new Transaction({ 
  expiration: 3_600_000  // 1 hour instead of default 60 seconds
})

await tx.addOperation('transfer', {
  from: 'multisig-account',
  to: 'alice',
  amount: '50.000 HIVE',
  memo: 'Pending multi-sig approval'
})

// First party signs
const key1 = PrivateKey.from('5J...')
tx.sign(key1)

// Serialize and send to others
const txData = JSON.stringify(tx.transaction)

// They have up to 1 hour to add signatures and broadcast
```

<Tip>
  Maximum expiration is 24 hours (86,400,000 ms). Use longer expirations for multi-sig workflows that require coordination across time zones.
</Tip>

## Verifying Signatures

Check how many signatures a transaction has:

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

const tx = new Transaction({ transaction: txData })

const signatureCount = tx.transaction?.signatures.length || 0
console.log(`Transaction has ${signatureCount} signature(s)`)

if (signatureCount >= 2) {
  console.log('Enough signatures for 2-of-3 multi-sig')
  await tx.broadcast(true)
} else {
  console.log(`Need ${2 - signatureCount} more signature(s)`)
}
```

## Error Handling

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

try {
  const tx = new Transaction({ transaction: txData })
  
  const key = PrivateKey.from('5J...')
  tx.sign(key)
  
  const result = await tx.broadcast(true)
  console.log('Success:', result.tx_id)
  
} catch (error) {
  if (error instanceof RPCError) {
    if (error.message.includes('missing required')) {
      console.error('Not enough signatures for required authority')
      console.error('Add more signatures before broadcasting')
    } else if (error.message.includes('expired')) {
      console.error('Transaction expired - signatures took too long')
    } else {
      console.error('Blockchain error:', error.message)
    }
  } else {
    console.error('Error:', error.message)
  }
}
```

## Common Multi-Sig Patterns

### Escrow Service

```typescript theme={null}
// 3-party escrow: buyer, seller, arbitrator
// Threshold: 2 (any 2 can release funds)

const escrowAuthority = {
  weight_threshold: 2,
  account_auths: [],
  key_auths: [
    ['STM_BUYER_KEY', 1],
    ['STM_SELLER_KEY', 1],
    ['STM_ARBITRATOR_KEY', 1]
  ]
}
```

### Corporate Account

```typescript theme={null}
// Board approval: 3 of 5 directors required

const boardAuthority = {
  weight_threshold: 3,
  account_auths: [],
  key_auths: [
    ['STM_DIRECTOR1_KEY', 1],
    ['STM_DIRECTOR2_KEY', 1],
    ['STM_DIRECTOR3_KEY', 1],
    ['STM_DIRECTOR4_KEY', 1],
    ['STM_DIRECTOR5_KEY', 1]
  ]
}
```

### Recovery Account

```typescript theme={null}
// Cold storage + hot wallet
// Either cold storage alone OR 2 hot wallets

const recoveryAuthority = {
  weight_threshold: 2,
  account_auths: [],
  key_auths: [
    ['STM_COLD_STORAGE_KEY', 2],  // Can act alone
    ['STM_HOT_WALLET1_KEY', 1],
    ['STM_HOT_WALLET2_KEY', 1]
  ]
}
```

## Next Steps

* Learn about [Key Management](/guides/key-management) for securing multiple keys
* Explore [Signing and Broadcasting](/guides/signing-broadcasting) for advanced signing options
* Review [Creating Transactions](/guides/creating-transactions) for operation types
