npm package: @hydrawallet-sdk/bridge
Description: Hydra wallet
Latest version: 1.0.3
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# @hydrawallet-sdk/bridge

A comprehensive bridge library for connecting and interacting with Hydra Node in the Cardano ecosystem. This package provides essential tools for managing Hydra Heads, executing transactions, and monitoring Hydra network state with real-time event handling.

## 🚀 Key Features

- **Multiple Connection Types**: Support for WebSocket and Socket.IO connections
- **Hydra Head Lifecycle**: Complete management of Hydra Head states (Init, Open, Close, Abort, Fanout)
- **Transaction Processing**: Send, track, and validate transactions within Hydra Heads
- **Real-time Events**: Comprehensive event system for monitoring Hydra network state
- **UTxO Management**: Query and manage UTxOs in snapshots with address filtering
- **Protocol Parameters**: Automatic fetching and management of Cardano protocol parameters
- **Commit/Decommit**: Support for moving funds in and out of Hydra Heads
- **Authentication**: Built-in support for JWT-based authentication

## 📦 Installation

```bash
npm install @hydrawallet-sdk/bridge
# or
pnpm add @hydrawallet-sdk/bridge
# or
yarn add @hydrawallet-sdk/bridge
```

## 🏗️ Architecture

### Core Components

#### 1. **HydraBridge**
Main class for interacting with Hydra Node:
- Connection and state management
- Command execution (Init, Close, Abort, Fanout, Contest, Recover)
- Transaction submission and tracking
- Event handling and state monitoring
- UTxO querying and management

#### 2. **Connectors**
Multiple connector types for different use cases:
- **WebsocketConnector**: Direct WebSocket connection to Hydra Node
- **HexcoreConnector**: Connection via Hexcore API with Socket.IO and authentication

#### 3. **Event System**
Comprehensive event handling:
- **Connection Events**: onConnected, onDisconnected, onConnectError
- **Hydra Events**: Real-time updates from Hydra Node
- **Message Types**: 20+ different message types for complete state tracking

#### 4. **Types & Interfaces**
- **HydraPayload**: 20+ message type definitions
- **HydraCommand**: All available commands (Init, Close, Abort, etc.)
- **HydraHeadStatus**: Head state enumeration (Idle, Initializing, Open, etc.)
- **Transaction**: Complete transaction structure with CBOR support
- **Protocol Parameters**: Cardano protocol parameter types

## 🚀 Basic Usage

### Initialize HydraBridge

```typescript
import { HydraBridge, HexcoreConnector } from '@hydrawallet-sdk/bridge'

// Using WebSocket connector (direct connection)
const bridge = new HydraBridge({
  url: 'ws://localhost:4001',
  verbose: true
})

// Using HexcoreConnector with authentication
const hexcoreConnector = new HexcoreConnector({
  socketIoUrl: 'wss://rps-api.hexcore.io.vn/hydra',
  socketIoOptions: {
    auth: {
      token: 'your_jwt_token_here'
    }
  }
})

const bridge = new HydraBridge({
  connector: hexcoreConnector,
  verbose: true
})
```

### Connect and Listen to Events

```typescript
// Connect to Hydra Node
bridge.connect()

// Listen to events
bridge.events.on('onConnected', async () => {
  console.log('Connected to Hydra Node')

  // Get protocol parameters after connection
  const protocolParams = await bridge.getProtocolParameters()
  console.log('Protocol Parameters:', protocolParams)
})

bridge.events.on('onMessage', (payload) => {
  console.log('Received message:', payload)

  switch (payload.tag) {
    case 'HeadIsOpen':
      console.log('Hydra Head is open')
      break
    case 'TxValid':
      console.log('Transaction valid:', payload.transactionId)
      break
    case 'SnapshotConfirmed':
      console.log('Snapshot confirmed')
      break
  }
})

bridge.events.on('onDisconnected', () => {
  console.log('Disconnected')
})

// Clean up on unmount/destroy
bridge.events.on('onConnectError', (error) => {
  console.error('Connection error:', error)
})
```

### Hydra Head Management

```typescript
// Initialize Hydra Head
bridge.commands.init()

// Close Hydra Head
bridge.commands.close()

// Abort Hydra Head
bridge.commands.abort()

// Fanout (withdraw from Head)
bridge.commands.fanout()

// Contest
bridge.commands.contest()

// Recover
bridge.commands.recover('tx_hash_here')
```

### Complete Transaction Example with Wallet Integration

```typescript
import { AppWallet, deserializeTx } from '@hydrawallet-sdk/core'
import { TxBuilder } from '@hydrawallet-sdk/transaction'

// Initialize HydraBridge with HexcoreConnector
const hexcoreConnector = new HexcoreConnector({
  socketIoUrl: 'wss://rps-api.hexcore.io.vn/hydra',
  socketIoOptions: {
    auth: {
      token: 'your_jwt_token_here'
    }
  }
})

const bridge = new HydraBridge({
  connector: hexcoreConnector,
  verbose: true
})

// Create wallet
const wallet = new AppWallet({
  networkId: 0, // 0 = testnet, 1 = mainnet
  key: {
    type: 'mnemonic',
    words: 'your mnemonic words here'.split(' ')
  }
})

// Get account
const account = wallet.getAccount(0, 0)

// Connect and handle events
bridge.connect()

bridge.events.on('onConnected', async () => {
  console.log('Connected to Hydra Node')

  // Query UTxOs for specific address
  const addressUtxos = await bridge.queryAddressUTxO(account.baseAddressBech32)
  console.log('Address UTxOs:', addressUtxos)

  // Get all addresses in head
  const addresses = bridge.addressesInHead()
  console.log('Addresses in Head:', addresses)

  // Get protocol parameters
  const protocolParams = await bridge.getProtocolParameters()

  // Create transaction builder for Hydra
  const txBuilder = new TxBuilder({
    isHydra: true,
    params: protocolParams
  })

  // Build transaction
  const tx = await txBuilder
    .setInputs(addressUtxos)
    .addLovelaceOutput(account.baseAddressBech32, '1000000') // 1 ADA
    .setChangeAddress(account.baseAddressBech32)
    .complete()

  // Get transaction ID
  const txId = deserializeTx(tx.to_hex()).transaction_hash().to_hex()

  // Sign transaction
  const signedTx = await wallet.signTx(tx.to_hex(), false, 0, 0)

  // Submit to Hydra Head using submitTxSync
  try {
    const result = await bridge.submitTxSync({
      type: 'Witnessed Tx ConwayEra',
      description: 'Ledger Cddl Format',
      cborHex: signedTx,
      txId
    }, { timeout: 30000 })

    console.log('Transaction successful:', result)
  } catch (error) {
    console.error('Transaction failed:', error)
  }
})

bridge.events.on('onMessage', (payload) => {
  console.log('Received message:', payload)
})

// Cleanup on unmount
bridge.events.on('onDisconnected', () => {
  console.log('Disconnected from Hydra Node')
})
```

### Commit and Decommit

```typescript
// Commit UTxO to Hydra Head
const commitData = {
  cborHex: '84a400818258...',
  description: 'Commit transaction'
}

try {
  const commitResult = await bridge.commit(commitData)
  console.log('Commit successful:', commitResult)
} catch (error) {
  console.error('Commit failed:', error)
}

// Decommit UTxO from Hydra Head
try {
  const decommitResult = await bridge.commands.decommit({
    cborHex: '84a400818258...',
    txHash: 'transaction_hash',
    timeout: 30000
  })
  console.log('Decommit successful:', decommitResult)
} catch (error) {
  console.error('Decommit failed:', error)
}
```

## 📊 Data Queries

### Protocol Parameters

```typescript
// Get protocol parameters
const protocolParams = await bridge.getProtocolParameters()
console.log('Protocol Parameters:', protocolParams)
```

### UTxO Management

```typescript
// Query snapshot UTxO
const utxoObject = await bridge.querySnapshotUtxo()
console.log('Snapshot UTxO:', utxoObject)

// Get UTxO array
const utxoArray = bridge.snapshotUtxoArray()
console.log('UTxO Array:', utxoArray)

// Query UTxO by address
const address = 'addr1...'
const addressUtxos = await bridge.queryAddressUTxO(address)
console.log('Address UTxOs:', addressUtxos)

// Get addresses in Head
const addresses = bridge.addressesInHead()
console.log('Addresses in Head:', addresses)
```

### Head State

```typescript
// Check connection status
console.log('Connected:', bridge.connected())

// Get Head information (async method - currently returns placeholder)
const headInfo = await bridge.headInfo()
console.log('Head Info:', headInfo)
console.log('Head Status:', headInfo.headStatus)
console.log('Head ID:', headInfo.headId)
console.log('VKey:', headInfo.vkey)

// Note: headInfo() method is currently not fully implemented
// It returns a placeholder object with default values

// Available Head Statuses (HydraHeadStatus enum):
// - Idle: Head not initialized
// - Initializing: Head is being set up
// - Open: Head is active and ready for transactions
// - Closed: Head is closed but not finalized
// - FanoutPossible: Ready for fanout
// - Final: Head is completely finalized
```

## 🔧 Advanced Configuration

### Custom Connector

```typescript
import { HydraConnector, HydraBridgeFetcher, HydraBridgeSubmitter } from '@hydrawallet-sdk/bridge'

class CustomConnector implements HydraConnector {
  // Implement interface methods
  connect() { /* custom logic */ }
  disconnect() { /* custom logic */ }
  connected() { /* custom logic */ }
  sendCommand(data) { /* custom logic */ }
  // ... other methods
}

const bridge = new HydraBridge({
  connector: new CustomConnector(),
  verbose: true
})
```

### Custom Fetcher and Submitter

```typescript
import { HexcoreConnector } from '@hydrawallet-sdk/bridge'

const customFetcher = {
  queryRawProtocolParameters: async () => {
    // Custom implementation
    return await fetch('/api/protocol-parameters').then(r => r.json())
  },
  querySnapshotUtxo: async () => {
    // Custom implementation
    return await fetch('/api/snapshot/utxo').then(r => r.json())
  }
}

const customSubmitter = {
  commit: async (data) => {
    // Custom implementation
    return await fetch('/api/commit', {
      method: 'POST',
      body: JSON.stringify(data)
    }).then(r => r.json())
  },
  submitCardanoTx: async (data) => {
    // Custom implementation
    return await fetch('/api/submit-tx', {
      method: 'POST',
      body: JSON.stringify(data)
    }).then(r => r.json())
  }
}

const connector = new HexcoreConnector({
  socketIoUrl: 'wss://your-hydra-api.com/hydra',
  fetcher: customFetcher,
  submitter: customSubmitter,
  socketIoOptions: {
    auth: {
      token: 'your_auth_token'
    }
  }
})
```

## 🔄 Lifecycle Management

### Proper Connection Management (Vue.js Example from Playground)

```typescript
// Vue.js Composition API example
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { HydraBridge, HexcoreConnector } from '@hydrawallet-sdk/bridge'

export default {
  setup() {
    const hydraBridge = ref<HydraBridge | null>(null)

    onMounted(async () => {
      // Clean up existing connection
      if (hydraBridge.value) {
        hydraBridge.value.disconnect()
        hydraBridge.value = null
      }

      // Create HexcoreConnector with authentication
      const hexcoreConnector = new HexcoreConnector({
        socketIoUrl: 'wss://rps-api.hexcore.io.vn/hydra',
        socketIoOptions: {
          auth: {
            token: 'your_jwt_token_here'
          }
        }
      })

      // Create HydraBridge instance
      hydraBridge.value = new HydraBridge({
        connector: hexcoreConnector
      })

      // Connect to Hydra Node
      hydraBridge.value.connect()

      // Set up event listeners
      hydraBridge.value.events.on('onMessage', (payload) => {
        console.log('Received message:', payload)
      })

      hydraBridge.value.events.on('onConnected', async () => {
        console.log('Connected to Hydra Node')

        // Auto-query snapshot UTxO on connection
        const snapshot = await hydraBridge.value!.querySnapshotUtxo()
        console.log('Snapshot UTxO:', snapshot)
      })
    })

    onBeforeUnmount(() => {
      // Always clean up on component unmount
      if (hydraBridge.value) {
        hydraBridge.value.disconnect()
        hydraBridge.value = null
      }
    })

    return { hydraBridge }
  }
}
```

### React.js Hook Example

```typescript
import { useEffect, useState } from 'react'
import { HydraBridge, HexcoreConnector } from '@hydrawallet-sdk/bridge'

function useHydraBridge(token: string) {
  const [bridge, setBridge] = useState<HydraBridge | null>(null)
  const [connected, setConnected] = useState(false)

  useEffect(() => {
    const connector = new HexcoreConnector({
      socketIoUrl: 'wss://rps-api.hexcore.io.vn/hydra',
      socketIoOptions: {
        auth: { token }
      }
    })

    const newBridge = new HydraBridge({ connector })

    // Set up event listeners
    newBridge.events.on('onConnected', () => {
      setConnected(true)
    })

    newBridge.events.on('onDisconnected', () => {
      setConnected(false)
    })

    newBridge.connect()
    setBridge(newBridge)

    // Cleanup function
    return () => {
      newBridge.disconnect()
      setBridge(null)
      setConnected(false)
    }
  }, [token])

  return { bridge, connected }
}
```

## 📝 Event Types

### Connection Events
- `onConnected`: When connection is successful
- `onDisconnected`: When disconnected
- `onConnectError`: When connection error occurs

### Hydra Events
- `onMessage`: Receive message from Hydra Node with typed payload

### Complete Message Types (HydraHeadTag)

#### Core Head Events
- `Greetings`: Initial greeting with head info and snapshot
- `HeadIsInitializing`: Head initialization started
- `HeadIsOpen`: Head is open and ready for transactions
- `HeadIsClosed`: Head has been closed
- `HeadIsContested`: Head state is being contested
- `HeadIsAborted`: Head initialization was aborted
- `HeadIsFinalized`: Head is completely finalized
- `ReadyToFanout`: Head is ready for fanout process

#### Transaction Events
- `TxValid`: Transaction is valid and accepted
- `TxInvalid`: Transaction is invalid with validation error
- `SnapshotConfirmed`: New snapshot has been confirmed
- `InvalidInput`: Invalid input received
- `PostTxOnChainFailed`: On-chain transaction posting failed

#### Peer Events
- `PeerConnected`: New peer connected to head
- `PeerDisconnected`: Peer disconnected from head
- `PeerHandshakeFailure`: Peer handshake failed

#### Commit/Decommit Events
- `CommitRecorded`: Commit transaction recorded
- `CommitApproved`: Commit has been approved
- `CommitFinalized`: Commit process completed
- `CommitRecovered`: Commit recovered after failure
- `CommitIgnored`: Commit was ignored
- `DecommitInvalid`: Decommit transaction is invalid
- `DecommitRequested`: Decommit has been requested
- `DecommitApproved`: Decommit has been approved
- `DecommitFinalized`: Decommit process completed

#### System Events
- `CommandFailed`: Command execution failed
- `IgnoredHeadInitializing`: Head initialization ignored
- `GetUTxOResponse`: Response to UTxO query (deprecated)

## 📚 API Reference

### HydraBridge Class

#### Constructor
```typescript
new HydraBridge(options: InitHydraBridgeOptions)
```

#### Methods
- `connect()`: Establish connection to Hydra Node
- `disconnect()`: Close connection
- `connected()`: Check connection status (returns boolean)
- `headInfo()`: Get current head information (async, currently returns placeholder)
- `getProtocolParameters()`: Fetch Cardano protocol parameters
- `querySnapshotUtxo()`: Get current snapshot UTxOs (auto-called on connection)
- `queryAddressUTxO(address: string)`: Get UTxOs for specific address
- `snapshotUtxoArray()`: Convert snapshot UTxO object to array format
- `addressesInHead()`: Get all unique addresses in current head
- `commit(data: CommitBody)`: Commit UTxOs to head
- `submitCardanoTransaction(data: SubmitTxBody)`: Submit transaction to Cardano network
- `submitTxSync(tx: Transaction, options?)`: Submit transaction and wait for confirmation
- `sendCommand(data)`: Send raw command to Hydra Node

#### Properties
- `events`: Event emitter for listening to Hydra events
- `commands`: Object containing all Hydra commands

#### Commands
- `commands.init()`: Initialize new Hydra Head
- `commands.close()`: Close current Hydra Head
- `commands.abort()`: Abort Hydra Head initialization
- `commands.fanout()`: Execute fanout process
- `commands.contest()`: Contest current head state
- `commands.recover(txId: string)`: Recover from failed state
- `commands.newTx(cborHex: string, description?: string, cb?: function)`: Submit new transaction
- `commands.decommit(payload: {cborHex, txId, timeout?})`: Decommit UTxOs from head
- `commands.initSync(retry?: number, interval?: number)`: Initialize with retry logic

### Types

#### InitHydraBridgeOptions
```typescript
type InitHydraBridgeOptions = {
  verbose?: boolean
} & (
  | { url: string } // WebSocket URL for direct connection
  | { connector: HydraConnector } // Custom connector (HexcoreConnector, etc.)
)
```

#### WebSocket Connector Options
```typescript
interface WebsocketConnectorOptions {
  websocketUrl: string
  fetcher?: HydraBridgeFetcher
  submitter?: HydraBridgeSubmitter
  // Optional connection settings
  noHistory?: boolean // Don't receive full node history
  noSnapshotUtxo?: boolean // Don't receive snapshot UTxO
  address?: string // Filter transactions by address
}
```

#### HexcoreConnector Options
```typescript
interface HexcoreConnectorOptions {
  socketIoUrl: string
  namespace?: string // Default: 'hydra'
  fetcher?: HydraBridgeFetcher
  submitter?: HydraBridgeSubmitter
  socketIoOptions?: {
    auth?: {
      token: string // JWT token for authentication
    }
    // Other Socket.IO client options
  }
}
```

#### Transaction
```typescript
interface Transaction {
  txId: string
  cborHex: string
  description: string
  type: 'Witnessed Tx ConwayEra'
}
```

#### CommitBody
```typescript
interface CommitBody {
  cborHex: string
  description: string
}
```

## 🔧 Best Practices

### Connection Management
1. **Always clean up connections** when components unmount
2. **Use verbose mode** during development for debugging
3. **Handle connection errors** gracefully with retry logic
4. **Auto-reconnect** on connection loss for production apps

### Event Handling
1. **Listen to onConnected** before performing operations
2. **Handle onMessage** for real-time updates
3. **Use typed payloads** for better TypeScript support
4. **Implement error boundaries** for event handling

### Transaction Management
1. **Always wait for confirmation** using `submitTxSync`
2. **Set appropriate timeouts** for transaction submission
3. **Handle transaction failures** with proper error messages
4. **Use proper CBOR encoding** for transaction data

## 🐛 Troubleshooting

### Common Issues

#### Connection Problems
```typescript
// Check connection status
if (!bridge.connected()) {
  console.log('Not connected to Hydra Node')
  bridge.connect()
}

// Handle connection errors
bridge.events.on('onConnectError', (error) => {
  console.error('Connection failed:', error)
  // Implement retry logic
})
```

#### Authentication Issues
```typescript
// Ensure JWT token is valid and not expired
const connector = new HexcoreConnector({
  socketIoUrl: 'wss://your-api.com/hydra',
  socketIoOptions: {
    auth: {
      token: 'valid_jwt_token_here'
    }
  }
})
```

#### Transaction Failures
```typescript
try {
  const result = await bridge.submitTxSync(transaction, { timeout: 60000 })
} catch (error) {
  if (error.tag === 'TxInvalid') {
    console.error('Transaction invalid:', error.reason)
  } else if (error.tag === 'Timeout') {
    console.error('Transaction timeout')
  }
}
```

## 🧪 Testing

```bash
# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Update snapshots
pnpm test:u
```

## 🔗 Dependencies

### Core Dependencies
- `@hydrawallet-sdk/core`: Core wallet functionality and UTxO management
- `@hydrawallet-sdk/cardano-wasm`: Cardano WASM bindings for serialization

### Network & Communication
- `socket.io-client`: Socket.IO client for real-time communication
- `axios`: HTTP client for API requests

### Utilities
- `mitt`: Lightweight event emitter for type-safe events
- `lodash-es`: Utility functions (uniq, etc.)
- `@scure/base`: Base encoding/decoding utilities
- `bip39`: BIP39 mnemonic phrase handling

### Development Dependencies
- `tsup`: TypeScript bundler
- `vite`: Development and testing framework

## 📄 License

MIT License - see [LICENSE](../../LICENSE) file for details.

## 🤝 Contributing

1. Fork the repository
2. Create feature branch: `git checkout -b feature/amazing-feature`
3. Commit changes: `git commit -m 'Add amazing feature'`
4. Push to branch: `git push origin feature/amazing-feature`
5. Create Pull Request

## 🔗 Links

- [Hydra Documentation](https://hydra.family/head-protocol/)
- [Cardano Developer Portal](https://developers.cardano.org/)
- [Hydra Node API](https://hydra.family/head-protocol/api-reference/)

---

**@hydrawallet-sdk/bridge** - Connect and interact with Hydra Node easily and efficiently.