# @hsuite/multisig

> 🚧 **Work in Progress** - This application is currently under active development. Features and APIs may change.

> 🔐 **Multi-Signature Wallet Platform** - Enterprise-grade security and transaction management for the Hedera ecosystem.

A comprehensive multi-signature wallet solution designed specifically for the Hedera network, providing secure transaction management, customizable approval workflows, and enterprise-grade controls with maximum security for digital assets. Built with NestJS, MongoDB, and seamless Hedera integration.

## 📑 Table of Contents

* [Overview](#overview)
* [Features](#features)
* [Technical Architecture](#technical-architecture)
* [API Endpoints](#api-endpoints)
* [Installation & Setup](#installation--setup)
* [Usage Examples](#usage-examples)
* [Database Schema](#database-schema)
* [Security Features](#security-features)
* [Queue System](#queue-system)
* [Development](#development)
* [Testing](#testing)
* [Contributing](#contributing)
* [License](#license)

## 🔍 Overview

The `@hsuite/multisig` application provides enterprise-grade multi-signature wallet functionality that supports:

* **Multi-Signature Wallets**: Create wallets requiring multiple signatures for transactions
* **Flexible Threshold Management**: Configure custom signature requirements (M-of-N)
* **Comprehensive Transaction Support**: HBAR transfers, token operations, staking, and account updates
* **Queue-based Processing**: Asynchronous transaction handling with Bull Queue
* **Real-time Updates**: WebSocket integration for live transaction status updates
* **Cross-Chain Support**: Extensible architecture for multiple blockchain networks

## ✨ Features

### 🏦 Multi-Signature Wallet Management

* **Create multi-signature wallets** with custom threshold requirements
* **Add/remove wallet owners** with proper validation and authorization
* **Update wallet configurations** including keys and thresholds
* **Track wallet history** with comprehensive audit trails

### 💰 Transaction Operations

* **HBAR Transfers**: Send and receive HBAR with multi-signature approval
* **Token Operations**:
  * Fungible token transfers (HTS tokens)
  * Non-fungible token (NFT) transfers
  * Token association/dissociation
* **Account Management**:
  * Account updates (keys, auto-renew, etc.)
  * Staking operations to consensus nodes
* **Transaction Batching**: Group multiple operations for efficiency

### 🔒 Security & Approval Workflows

* **Threshold Signatures**: Configurable M-of-N signature requirements
* **Transaction Validation**: Comprehensive checks before execution
* **Owner Management**: Secure addition/removal of wallet owners
* **Audit Logging**: Complete transaction and signature history
* **Queue Safety**: Time-limited transaction windows for security

### 🔄 Real-time Features

* **WebSocket Gateway**: Live updates for transaction status changes
* **Event-driven Architecture**: Pub/sub system for real-time notifications
* **Background Processing**: Asynchronous transaction handling
* **Status Monitoring**: Real-time wallet and transaction status tracking

## 🏗️ Technical Architecture

### Core Components

```typescript
/**
 * Main application components:
 * - MultisigService: Core wallet and transaction management
 * - MultisigConsumer: Background job processing with Bull Queue
 * - MultisigGateway: WebSocket real-time communication
 * - MultisigController: REST API endpoints
 * - Model Services: Database operations and business logic
 */
```

### Data Models

#### Multisig Wallet Entity

```typescript
interface MultisigWallet {
  wallet: string;                    // Hedera Account ID
  smartApp: string;                  // Smart application identifier
  name: string;                      // Wallet display name
  description: string;               // Wallet description
  settings: {
    owners: Array<{
      wallet: string;                // Owner's Hedera Account ID
      name: string;                  // Owner display name
    }>;
    threshold: number;               // Required signatures (M-of-N)
  };
  history: MultisigHistory[];        // Transaction history
}
```

#### Transaction History Entity

```typescript
interface MultisigHistory {
  type: 'create' | 'update' | 'withdraw' | 'associate' | 'dissociate';
  payload: any;                      // Transaction-specific data
  timestamp: string;                 // Transaction timestamp
  threshold: number;                 // Required threshold at time of transaction
  events: MultisigEvent[];           // Associated events and signatures
}
```

#### Transaction Event Entity

```typescript
interface MultisigEvent {
  status: 'pending' | 'success' | 'error';
  action: 'signature' | 'execute' | 'request';
  payload: any;                      // Event-specific data
  timestamp: string;                 // Event timestamp
  transaction?: Buffer;              // Serialized transaction data
  signature?: Buffer;                // Signature data
}
```

### Infrastructure Stack

* **Framework**: NestJS with TypeScript
* **Database**: MongoDB with Mongoose ODM
* **Queue System**: Bull Queue with Redis
* **WebSockets**: Socket.IO for real-time communication
* **Blockchain**: Hedera Hashgraph SDK integration
* **Validation**: class-validator and custom business rules
* **Background Jobs**: Automatic retry and error handling

## 🔌 API Endpoints

### Wallet Management

#### Get Wallet Information

```http
GET /multisig/wallet/{walletId}
Authorization: Bearer {token}
```

**Response:**

```json
{
  "wallet": "0.0.123456",
  "name": "Treasury Wallet",
  "description": "Main treasury multi-sig wallet",
  "settings": {
    "owners": [
      { "wallet": "0.0.111111", "name": "Alice" },
      { "wallet": "0.0.222222", "name": "Bob" },
      { "wallet": "0.0.333333", "name": "Charlie" }
    ],
    "threshold": 2
  },
  "assets": [...],
  "chain": "HEDERA"
}
```

### Wallet Creation

#### Create Wallet Request

```http
POST /multisig/wallet/create/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "name": "Development Team Wallet",
  "description": "Multi-sig wallet for development expenses",
  "balance": 100.0,
  "settings": {
    "owners": [
      { "wallet": "0.0.111111", "name": "Lead Developer" },
      { "wallet": "0.0.222222", "name": "Project Manager" },
      { "wallet": "0.0.333333", "name": "Technical Director" }
    ],
    "threshold": 2
  },
  "maxAutomaticTokenAssociations": 1000,
  "isReceiverSignatureRequired": false
}
```

#### Execute Wallet Creation

```http
POST /multisig/wallet/create/execute
Content-Type: application/json
Authorization: Bearer {token}

{
  "bytes": "0x...", // Signed transaction bytes
  "jobId": "12345"
}
```

### Transaction Operations

#### Create Withdrawal Request

```http
POST /multisig/wallet/withdraw/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "receiverId": "0.0.789012",
  "tokenId": "HBAR", // or token ID like "0.0.445566"
  "type": "FUNGIBLE_COMMON", // or "NON_FUNGIBLE_UNIQUE"
  "amountOrSerial": 100.0 // or NFT serial number
}
```

#### Create Update Request

```http
POST /multisig/wallet/update/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "action": "add", // or "remove"
  "owner": {
    "wallet": "0.0.444444",
    "name": "New Team Member"
  },
  "threshold": 3
}
```

#### Create Staking Request

```http
POST /multisig/wallet/stake/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "nodeId": 3 // Hedera consensus node ID, omit to unstake
}
```

### Signature Management

#### Sign Transaction

```http
POST /multisig/transaction/sign/{jobId}
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "senderId": "0.0.111111",
  "historyId": "6507f1f77bcf86cd79943901",
  "signature": "0x..." // Signature bytes
}
```

#### Get Transaction Status

```http
GET /multisig/transaction/status/{jobId}
Authorization: Bearer {token}
```

### Token Operations

#### Associate Token Request

```http
POST /multisig/wallet/associate/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "tokenId": "0.0.445566"
}
```

#### Dissociate Token Request

```http
POST /multisig/wallet/dissociate/request
Content-Type: application/json
Authorization: Bearer {token}

{
  "walletId": "0.0.123456",
  "tokenId": "0.0.445566"
}
```

## 🚀 Installation & Setup

### Prerequisites

* Node.js 18+ and npm/yarn
* MongoDB 5.0+
* Redis 6.0+
* Hedera testnet/mainnet account

### Environment Configuration

Create `.multisig.env` file:

```bash
# Database Configuration
DATABASE_URL=mongodb://localhost:27017/hsuite_multisig

# Redis Configuration (for Bull Queue)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=optional_password

# Hedera Network Configuration
HEDERA_NETWORK=testnet
HEDERA_ACCOUNT_ID=0.0.YOUR_ACCOUNT
HEDERA_PRIVATE_KEY=your_private_key_hex

# Application Configuration
PORT=3003
APP_NAME=@hsuite/multisig
LOG_LEVEL=info

# WebSocket Configuration
WS_PORT=3004
WS_NAMESPACE=multisig_events

# Queue Configuration
QUEUE_REDIS_URL=redis://localhost:6379
QUEUE_ATTEMPTS=3
QUEUE_BACKOFF_DELAY=2000

# Security Configuration
JWT_SECRET=your_jwt_secret
TRANSACTION_TIMEOUT=120000 # 2 minutes in milliseconds

# Chain Configuration
SUPPORTED_CHAINS=HEDERA,RIPPLE
DEFAULT_CHAIN=HEDERA
```

### Installation Steps

1. **Install dependencies**:

```bash
npm install
# or
yarn install
```

2. **Start required services**:

```bash
# Start MongoDB
mongod --dbpath /path/to/db

# Start Redis
redis-server
```

3. **Initialize database** (if required):

```bash
npm run migration:run multisig
```

4. **Start the application**:

```bash
# Development mode
npm run start:dev multisig

# Production mode  
npm run start:prod multisig

# Watch mode for development
npm run start:debug multisig
```

5. **Verify installation**:

```bash
# Health check
curl http://localhost:3003/health

# WebSocket test
curl -i -N -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
  -H "Sec-WebSocket-Version: 13" \
  http://localhost:3004/socket.io/
```

## 📚 Usage Examples

### Complete Multi-Signature Workflow

```typescript
import axios from 'axios';
import { PrivateKey, Client } from '@hashgraph/sdk';

const API_BASE = 'http://localhost:3003';
const client = Client.forTestnet();

// 1. Create a multi-signature wallet
const createMultisigWallet = async () => {
  // Request wallet creation
  const createResponse = await axios.post(`${API_BASE}/multisig/wallet/create/request`, {
    name: 'Team Treasury',
    description: 'Multi-signature wallet for team expenses',
    balance: 1000.0,
    settings: {
      owners: [
        { wallet: '0.0.111111', name: 'Alice (CEO)' },
        { wallet: '0.0.222222', name: 'Bob (CTO)' },
        { wallet: '0.0.333333', name: 'Charlie (CFO)' }
      ],
      threshold: 2
    },
    maxAutomaticTokenAssociations: 1000
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  // Sign the transaction
  const transactionBytes = Buffer.from(createResponse.data.bytes, 'base64');
  const privateKey = PrivateKey.fromString(process.env.PRIVATE_KEY);
  const signature = privateKey.sign(transactionBytes);

  // Execute the creation
  const executeResponse = await axios.post(`${API_BASE}/multisig/wallet/create/execute`, {
    bytes: Array.from(signature),
    jobId: createResponse.data.jobId
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  return executeResponse.data;
};

// 2. Create a withdrawal request
const createWithdrawal = async (walletId: string) => {
  const response = await axios.post(`${API_BASE}/multisig/wallet/withdraw/request`, {
    walletId,
    receiverId: '0.0.789012',
    tokenId: 'HBAR',
    type: 'FUNGIBLE_COMMON',
    amountOrSerial: 100.0
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  return response.data;
};

// 3. Sign a transaction (multiple owners need to do this)
const signTransaction = async (jobId: string, walletId: string, signerId: string) => {
  // Get transaction details first
  const statusResponse = await axios.get(`${API_BASE}/multisig/transaction/status/${jobId}`, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  // Sign the transaction bytes
  const transactionBytes = Buffer.from(statusResponse.data.bytes, 'base64');
  const privateKey = PrivateKey.fromString(process.env.SIGNER_PRIVATE_KEY);
  const signature = privateKey.sign(transactionBytes);

  // Submit signature
  const response = await axios.post(`${API_BASE}/multisig/transaction/sign/${jobId}`, {
    walletId,
    senderId: signerId,
    historyId: statusResponse.data.historyId,
    signature: Array.from(signature)
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  return response.data;
};

// 4. Monitor wallet status
const getWalletInfo = async (walletId: string) => {
  const response = await axios.get(`${API_BASE}/multisig/wallet/${walletId}`, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  console.log('Wallet Info:', {
    balance: response.data.assets,
    pendingTransactions: response.data.history.filter(h => h.status === 'pending'),
    owners: response.data.settings.owners,
    threshold: response.data.settings.threshold
  });

  return response.data;
};
```

### WebSocket Integration for Real-time Updates

```typescript
import { io, Socket } from 'socket.io-client';

class MultisigWebSocketClient {
  private socket: Socket;

  constructor(authToken: string) {
    this.socket = io('http://localhost:3004/multisig', {
      auth: {
        token: authToken
      },
      transports: ['websocket']
    });

    this.setupEventListeners();
  }

  private setupEventListeners() {
    // Connection events
    this.socket.on('connect', () => {
      console.log('Connected to multisig WebSocket');
    });

    this.socket.on('disconnect', () => {
      console.log('Disconnected from multisig WebSocket');
    });

    // Wallet events
    this.socket.on('wallet_created', (data) => {
      console.log('New wallet created:', data);
      // Update UI to show new wallet
    });

    this.socket.on('wallet_updated', (data) => {
      console.log('Wallet updated:', data);
      // Refresh wallet information
    });

    // Transaction events
    this.socket.on('transaction_pending', (data) => {
      console.log('Transaction pending signature:', data);
      // Show notification for pending transaction
    });

    this.socket.on('signature_added', (data) => {
      console.log('New signature added:', data);
      // Update signature count display
    });

    this.socket.on('transaction_executed', (data) => {
      console.log('Transaction executed:', data);
      // Update transaction history and balances
    });

    this.socket.on('transaction_failed', (data) => {
      console.error('Transaction failed:', data);
      // Show error notification
    });
  }

  // Subscribe to specific wallet events
  subscribeToWallet(walletId: string) {
    this.socket.emit('subscribe_wallet', { walletId });
  }

  // Unsubscribe from wallet events
  unsubscribeFromWallet(walletId: string) {
    this.socket.emit('unsubscribe_wallet', { walletId });
  }

  disconnect() {
    this.socket.disconnect();
  }
}

// Usage
const wsClient = new MultisigWebSocketClient(authToken);
wsClient.subscribeToWallet('0.0.123456');
```

### Token Operations Example

```typescript
// Associate a token with the multisig wallet
const associateToken = async (walletId: string, tokenId: string) => {
  // Step 1: Create association request
  const requestResponse = await axios.post(`${API_BASE}/multisig/wallet/associate/request`, {
    walletId,
    tokenId
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  // Step 2: Get required signatures (repeat for each required signer)
  const signatures = [];
  for (const signer of requiredSigners) {
    const signature = await signTransaction(
      requestResponse.data.jobId,
      walletId,
      signer.accountId
    );
    signatures.push(signature);
  }

  // Step 3: Execute when threshold is met
  const executeResponse = await axios.post(`${API_BASE}/multisig/wallet/associate/execute`, {
    bytes: requestResponse.data.bytes,
    jobId: requestResponse.data.jobId
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  return executeResponse.data;
};

// Transfer tokens from multisig wallet
const transferTokens = async (walletId: string, tokenId: string, amount: number, recipient: string) => {
  const response = await axios.post(`${API_BASE}/multisig/wallet/withdraw/request`, {
    walletId,
    receiverId: recipient,
    tokenId,
    type: 'FUNGIBLE_COMMON',
    amountOrSerial: amount
  }, {
    headers: { Authorization: `Bearer ${authToken}` }
  });

  return response.data;
};
```

## 🗃️ Database Schema

### Collections Structure

#### multisig\_wallets

```javascript
{
  _id: ObjectId,
  wallet: String,                    // Hedera Account ID
  smartApp: String,                  // Smart application identifier  
  name: String,                      // Wallet display name
  description: String,               // Wallet description
  settings: {
    owners: [{
      wallet: String,                // Owner Hedera Account ID
      name: String                   // Owner display name
    }],
    threshold: Number                // Required signature count
  },
  history: [ObjectId],               // refs to multisig_histories
  createdAt: Date,
  updatedAt: Date
}
```

#### multisig\_histories

```javascript
{
  _id: ObjectId,
  type: String,                      // 'create'|'update'|'withdraw'|'associate'|'dissociate'
  payload: Object,                   // Transaction-specific data
  timestamp: String,                 // Transaction timestamp
  threshold: Number,                 // Required threshold
  events: [ObjectId],                // refs to multisig_events
  createdAt: Date,
  updatedAt: Date
}
```

#### multisig\_events

```javascript
{
  _id: ObjectId,
  status: String,                    // 'pending'|'success'|'error'
  action: String,                    // 'signature'|'execute'|'request'
  payload: Object,                   // Event-specific data
  timestamp: String,                 // Event timestamp
  transaction: Buffer,               // Serialized transaction (optional)
  signature: Buffer,                 // Signature data (optional)
  createdAt: Date,
  updatedAt: Date
}
```

## 🔒 Security Features

### Transaction Security

* **Time-limited requests**: Transactions expire after 2 minutes to prevent replay attacks
* **Signature validation**: All signatures verified against Hedera public keys
* **Threshold enforcement**: Transactions only execute when signature threshold is met
* **Owner validation**: Only wallet owners can sign transactions

### Access Control

* **JWT Authentication**: All API endpoints require valid authentication tokens
* **Wallet ownership**: Users can only access wallets they own or are members of
* **Role-based permissions**: Different access levels for wallet operations

### Data Protection

* **Encrypted storage**: Sensitive data encrypted at rest
* **Audit logging**: Complete audit trail for all operations
* **Input validation**: Comprehensive validation of all inputs
* **SQL injection prevention**: MongoDB queries properly parameterized

## ⚙️ Queue System

The application uses Bull Queue for reliable background processing:

### Queue Types

* **create.request**: Wallet creation requests with 2-minute delay
* **create.execute**: Wallet creation execution
* **withdraw\.request**: Withdrawal requests
* **withdraw\.execute**: Withdrawal execution
* **update.request**: Wallet update requests
* **update.execute**: Wallet update execution
* **stake.request**: Staking requests
* **stake.execute**: Staking execution
* **transaction.sign**: Transaction signature processing

### Queue Configuration

* **Retry Policy**: 3 attempts with exponential backoff
* **Timeout**: 2-minute timeout for transaction execution
* **Concurrency**: Configurable concurrent job processing
* **Error Handling**: Comprehensive error logging and recovery

### Monitoring Queues

```typescript
// Get queue statistics
const getQueueStats = async () => {
  const stats = await multisigQueue.getJobCounts();
  console.log('Queue Statistics:', {
    active: stats.active,
    waiting: stats.waiting,
    completed: stats.completed,
    failed: stats.failed,
    delayed: stats.delayed
  });
};

// Monitor failed jobs
const getFailedJobs = async () => {
  const failedJobs = await multisigQueue.getFailed();
  return failedJobs.map(job => ({
    id: job.id,
    name: job.name,
    data: job.data,
    error: job.failedReason,
    timestamp: job.timestamp
  }));
};
```

## 🔧 Development

### Project Structure

```
apps/multisig/
├── src/
│   ├── main.ts                      # Application entry point
│   ├── multisig.module.ts           # Root module configuration
│   ├── multisig.service.ts          # Core multisig business logic
│   ├── multisig.controller.ts       # REST API endpoints
│   ├── multisig.consumer.ts         # Bull Queue job processing
│   ├── multisig.gateway.ts          # WebSocket gateway
│   ├── multisig.events.ts           # Event definitions
│   ├── entities/                    # Database entity definitions
│   │   ├── wallets/                 # Wallet entities
│   │   ├── histories/               # History entities
│   │   └── events/                  # Event entities
│   ├── models/                      # Database model services
│   │   ├── wallets/                 # Wallet model operations
│   │   ├── histories/               # History model operations
│   │   └── events/                  # Event model operations
│   └── interfaces/                  # TypeScript interface definitions
│       └── namespaces/              # Organized interface namespaces
├── test/                            # Test files
├── config/                          # Configuration files
├── tsconfig.app.json               # TypeScript configuration
└── README.md                       # This file
```

### Running Tests

```bash
# Unit tests
npm run test multisig

# E2E tests
npm run test:e2e multisig

# Test coverage
npm run test:cov multisig

# Watch mode for TDD
npm run test:watch multisig

# Debug tests
npm run test:debug multisig
```

### Development Commands

```bash
# Start in development mode with hot reload
npm run start:dev multisig

# Start in debug mode
npm run start:debug multisig

# Build for production
npm run build multisig

# Start production build
npm run start:prod multisig

# Lint code
npm run lint

# Format code
npm run format
```

### Adding New Features

1. **Define interfaces** in `src/interfaces/`
2. **Create/update entities** in `src/entities/`
3. **Implement business logic** in `src/multisig.service.ts`
4. **Add API endpoints** in `src/multisig.controller.ts`
5. **Add queue processing** in `src/multisig.consumer.ts`
6. **Update WebSocket events** in `src/multisig.gateway.ts`
7. **Write tests** for all new functionality

## 🧪 Testing

### Test Categories

#### Unit Tests

* Service method testing
* Controller endpoint testing
* Model operation testing
* Utility function testing

#### Integration Tests

* Database integration
* Queue system integration
* WebSocket communication
* Hedera SDK integration

#### E2E Tests

* Complete wallet creation workflow
* Multi-signature transaction flow
* Error handling scenarios
* Performance testing

### Running Specific Tests

```bash
# Test specific file
npm test -- multisig.service.spec.ts

# Test specific pattern
npm test -- --testNamePattern="wallet creation"

# Test with coverage
npm run test:cov -- --testPathPattern=multisig
```

## 🤝 Contributing

We welcome contributions to improve the multisig platform! Please read our [Contributing Guide](https://github.com/HSuiteNetwork/smart-engines/blob/develop/docs/developers/CONTRIBUTING.md) for details on:

* **Code Style**: Follow ESLint and Prettier configurations
* **Testing Requirements**: Maintain >90% test coverage
* **Documentation**: Update documentation for new features
* **PR Process**: Use conventional commits and proper PR templates

### Development Workflow

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Make changes and add tests
4. Run the test suite: `npm run test multisig`
5. Commit changes: `git commit -m 'feat: add amazing feature'`
6. Push to branch: `git push origin feature/amazing-feature`
7. Open a Pull Request

## 📄 License

This package is part of the HSuite ecosystem and is covered by its license terms.

***

## 🆘 Support & Documentation

* **GitHub Issues**: Report bugs and request features
* **API Documentation**: Swagger UI at `/api/docs` when running
* **Community**: Join our Discord for real-time support
* **Enterprise Support**: Contact us for enterprise deployment assistance

***

<p align="center">Built with ❤️ by the HSuite Team<br>Securing digital assets on Hedera with enterprise-grade multi-signature solutions<br>Copyright © 2025 HSuite. All rights reserved.</p>
