npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rewindbitcoin/watchtower

v1.3.6

Published

Monitoring service for RewindBitcoin Wallet that tracks Bitcoin transactions and sends push notifications

Readme

Watchtower API for RewindBitcoin Wallet

📌 Overview

The Watchtower API is a security monitoring service for the RewindBitcoin Wallet that protects users' Bitcoin vaults from unauthorized access. It continuously watches the blockchain for specific transactions that would indicate someone is attempting to unfreeze a vault. When such activity is detected, the service immediately sends system-level push notifications to the user's iOS and Android devices where the RewindBitcoin app is installed, allowing them to take action before funds can be moved.

In practical terms, this means:

  • If someone gains access to your wallet (through theft, etc.), the Watchtower notifies you immediately
  • When an attacker tries to unfreeze your vault, you receive alerts on all your registered devices as high-priority system notifications
  • The RewindBitcoin app immediately displays emergency action options when you tap on the notification
  • You then have time to execute a "panic transaction" to move funds to your emergency cold storage before the attacker can access them
  • The service works silently in the background, only alerting you when necessary

By default, the RewindBitcoin app uses our hosted Watchtower service, but for enhanced privacy, you can also run your own Watchtower instance and configure the app to use it instead.


⚙️ Usage

📱 For Users

If you prefer to run your own Watchtower for enhanced privacy and control over your vault monitoring data, you can easily set it up:

Running Your Own Watchtower

You can easily run the Watchtower API directly using npx without installing it:

npx @rewindbitcoin/watchtower

After starting your own Watchtower, you'll need to configure the RewindBitcoin app to use it:

  1. Open the RewindBitcoin app
  2. Go to Settings → Watchtower
  3. Enter your custom Watchtower URL (e.g., http://192.168.1.10:3000 or http://your-domain.com)
  4. Save your settings

Your app will now use your personal Watchtower instance instead of the default service, giving you complete control over your vault monitoring.

Command Line Options

# Run with specific port
npx @rewindbitcoin/watchtower --port 3000

# Disable specific networks
npx @rewindbitcoin/watchtower --disable-testnet --disable-tape

# Enable regtest with custom Esplora API URL
npx @rewindbitcoin/watchtower --enable-regtest \
  http://localhost:3002

# Enable commitment verification
npx @rewindbitcoin/watchtower --with-commitments

# Specify custom database folder (default is ./db)
npx @rewindbitcoin/watchtower --db-folder /path/to/database

# Display help information
npx @rewindbitcoin/watchtower --help

Network Monitoring

If no port is specified, a random available port will be used and displayed in the console.

By default, the watchtower monitors these networks:

  • bitcoin
  • testnet
  • tape (Rewind Bitcoin's own test network)

The regtest network is disabled by default and must be explicitly enabled with a valid Esplora API URL.

💻 For Developers

If you want to modify or contribute to the Watchtower API:

Clone and Install Dependencies

git clone https://github.com/rewindbitcoin/watchtower.git
cd watchtower
npm install

Development Mode

# Run in development mode
npx ts-node src/index.ts

Build from Source

# Build the project
npm run build

# Run the built version
npm start

Publishing (for maintainers)

# Build and publish to npm
npm publish

🔍 Blockchain Monitoring Strategy

The Watchtower uses an efficient monitoring strategy to minimize API calls:

  1. On startup: Initialize with the last checked block height minus IRREVERSIBLE_THRESHOLD from the database or current height (minus IRREVERSIBLE_THRESHOLD) if starting fresh.

  2. For each monitoring cycle:

    • Get all new blocks since the last checked height
    • Check if any pending transactions appear in these blocks
    • Send notifications to all devices for found transactions
    • Mark notifications as 'sent' or 'pending'
    • Update the last checked height
  3. Reorg handling: Recheck the last 4 blocks (IRREVERSIBLE_THRESHOLD) on each cycle to handle potential blockchain reorganizations

  4. In-memory caching: Keep track of checked blocks in memory to avoid redundant processing within a session

  5. Commitment verification: An optional security feature that validates transactions against their original vault creation transaction (See the Commitment Verification section for complete details)

This approach efficiently monitors transactions while handling multiple devices per vault and maintaining proper notification state.


🔐 Commitment Verification

The Watchtower API uses a commitment verification system to prevent abuse:

  • When enabled with --with-commitments flag, each vault registration requires a valid commitment transaction
  • The commitment is the actual transaction that created the vault on the blockchain
  • This transaction should have paid a fee to an authorized service address
  • The transactions being monitored by the watchtower are those that spend from this commitment (i.e., transactions that initiate the unfreezing of a vault)
  • This commitment system serves several important purposes:
    • Prevents spam registrations by requiring a real on-chain payment
    • Ensures only legitimate vaults can be registered with the service
  • Each commitment can only be used for one vault ID
  • Note: If you're running your own private watchtower, you can disable this feature as long as you don't make your service publicly available

📩 Push Notifications

The service uses Expo Push Notifications to deliver critical security alerts directly to users' iOS and Android devices when a monitored vault is accessed. These notifications appear as system-level alert dialogs with warning messages, ensuring users are promptly informed of potential security events.

Critical Security Alerts

When a vault access attempt is detected, the Watchtower immediately sends a push notification to all registered devices associated with that vault. These notifications:

  • Appear as high-priority system dialogs on both iOS and Android devices
  • Display clear warning messages about the vault being accessed
  • Include essential information about which vault is affected
  • Provide context about the wallet and transaction

Example Payload:

{
  "to": "ExponentPushToken[xyz]",
  "title": "Vault Access Alert!",
  "body": "Your vault vault123 in wallet 'My Bitcoin Wallet' is being accessed!",
  "data": {
    "vaultId": "vault123",
    "walletUUID": "wallet_unique_identifier",
    "walletName": "My Bitcoin Wallet",
    "vaultNumber": 1,
    "watchtowerId": "client_provided_unique_id_for_watchtower",
    "txid": "abcdef1234567890abcdef1234567890",
    "attemptCount": 1,
    "firstDetectedAt": 1634567890
  }
}

Persistent Notification System

The Watchtower implements a robust retry mechanism to ensure critical security alerts are not missed:

  • Persistent Retries: The system periodically retries sending notifications until the user explicitly acknowledges receipt
  • Escalating Schedule:
    • First day: Retry every 6 hours
    • After first day: Retry once per day for up to a week
  • Enhanced Context: Retry notifications include additional information about when the issue was first detected

This persistent approach ensures that even if a user's device is temporarily offline or notifications are missed, they will still be alerted to potential security issues with their vaults.

Example Retry Payload:

{
  "to": "ExponentPushToken[xyz]",
  "title": "Vault Access Alert!",
  "body": "Your vault vault123 in wallet 'My Bitcoin Wallet' is being accessed! (Attempt 3, first detected 14 hours ago)",
  "data": {
    "vaultId": "vault123",
    "walletUUID": "wallet_unique_identifier",
    "walletName": "My Bitcoin Wallet",
    "vaultNumber": 1,
    "watchtowerId": "client_provided_unique_id_for_watchtower",
    "txid": "abcdef1234567890abcdef1234567890",
    "attemptCount": 3,
    "firstDetectedAt": 1634567890
  }
}

Acknowledging Notifications

To stop receiving retry notifications once the alert has been seen, the client app should acknowledge receipt using the Acknowledge Notification Receipt API endpoint:

POST /watchtower/ack
{
  "pushToken": "ExponentPushToken[xyz]",
  "vaultId": "vault123"
}

This acknowledgment system ensures that users are only notified until they've confirmed awareness of the security event.


📡 API Endpoints

The Watchtower provides a simple REST API for registering vaults and acknowledging notifications. Below are the available endpoints:

Health Check

GET /generate_204

  • Purpose: Checks if the service is running.
  • Response: 204 No Content

Register Vaults to Be Monitored

POST /watchtower/register or POST /:networkId/watchtower/register

  • Purpose: Registers vaults and associates them with a push notification token.

  • URL Parameters:

    • networkId: The Bitcoin network (bitcoin, testnet, tape, or regtest)
    • If using /watchtower/register without networkId, defaults to bitcoin mainnet
  • Request Body:

    {
      "pushToken": "ExponentPushToken[xyz]",
      "walletUUID": "wallet_unique_identifier", // Unique ID for the wallet
      "walletName": "My Bitcoin Wallet",
      "watchtowerId": "client_provided_unique_id_for_watchtower", // Client-provided unique ID for this watchtower instance
      "locale": "es", // Optional, defaults to "en"
      "vaults": [
        {
          "vaultId": "vault123",
          "vaultNumber": 1,
          "triggerTxIds": ["txid1", "txid2"],
          "commitment": "0200000001abcdef..." // Required when commitment verification is enabled
        },
        {
          "vaultId": "vault456",
          "vaultNumber": 2,
          "triggerTxIds": ["txid3", "txid4"],
          "commitment": "0200000001ghijkl..." // Required when commitment verification is enabled
        }
      ]
    }

Supported Languages

The Watchtower API currently supports the following languages for notifications:

  • English (en) - Default
  • Spanish (es)

The language is specified using the locale parameter during vault registration.

  • Responses:
    • 200 OK: Registration successful
    • 400 Bad Request: Invalid input data or commitment transaction
    • 403 Forbidden: Commitment transaction doesn't pay to an authorized address
    • 409 Conflict: Vault has already been accessed and cannot be registered again

Acknowledge Notification Receipt

POST /watchtower/ack or POST /:networkId/watchtower/ack

  • Purpose: Acknowledges receipt of a notification for a specific vault.

  • URL Parameters:

    • networkId: The Bitcoin network (bitcoin, testnet, tape, or regtest)
    • If using /watchtower/ack without networkId, defaults to bitcoin mainnet
  • Request Body:

    {
      "pushToken": "ExponentPushToken[xyz]",
      "vaultId": "vault123"
    }
  • Responses:

    • 200 OK: Acknowledgment successful
    • 400 Bad Request: Invalid input data
    • 404 Not Found: No matching notification found
    • 500 Internal Server Error: Server error

Retrieve Unacknowledged Notifications

POST /watchtower/notifications or POST /:networkId/watchtower/notifications

  • Purpose: Retrieves all unacknowledged notifications for a specific device from a specific network.

  • URL Parameters:

    • networkId: The Bitcoin network (bitcoin, testnet, tape, or regtest)
    • If using /watchtower/notifications without networkId, defaults to bitcoin mainnet
  • Request Body:

    {
      "pushToken": "ExponentPushToken[xyz]"
    }
  • Response:

    {
      "notifications": [
        {
          "vaultId": "vault123",
          "walletUUID": "wallet_unique_identifier",
          "walletName": "My Bitcoin Wallet",
          "vaultNumber": 1,
          "watchtowerId": "client_provided_unique_id_for_watchtower",
          "txid": "abcdef1234567890abcdef1234567890",
          "attemptCount": 3,
          "firstDetectedAt": 1634567890,
          "networkId": "bitcoin"
        },
        {
          "vaultId": "vault456",
          "walletUUID": "wallet_unique_identifier",
          "walletName": "My Bitcoin Wallet",
          "vaultNumber": 2,
          "watchtowerId": "client_provided_unique_id_for_watchtower",
          "txid": "fedcba0987654321fedcba0987654321",
          "attemptCount": 1,
          "firstDetectedAt": 1634567891,
          "networkId": "bitcoin"
        }
      ]
    }
  • Responses:

    • 200 OK: Request successful (even if no notifications are found)
    • 400 Bad Request: Invalid input data (missing pushToken)
    • 500 Internal Server Error: Server error

🗃 Database Schema

The Watchtower API uses SQLite with the following structure:

Notifications Table: | Column | Type | Description | |----------|------|-------------| | pushToken | TEXT | Device push notification token | | vaultId | TEXT | Associated vault ID | | walletUUID | TEXT | Unique ID for the wallet | | walletName | TEXT | Name of the wallet containing the vault | | vaultNumber | INTEGER | The nth vault created in the wallet | | watchtowerId | TEXT | Client-provided unique ID for the watchtower instance used for registration | | firstAttemptAt | INTEGER | Unix timestamp of first notification attempt | | acknowledged | INTEGER | Whether notification was acknowledged (0=no, 1=yes) | | lastAttemptAt | INTEGER | Unix timestamp of last notification attempt | | attemptCount | INTEGER | Number of notification attempts made | | locale | TEXT | User's preferred language (default: 'en') |

Vault Transactions Table: | Column | Type | Description | |--------|------|-------------| | txid | TEXT | Primary Key - Transaction ID to monitor | | vaultId | TEXT | Associated vault ID | | status | TEXT | Status: 'unchecked', 'unseen', 'reversible', 'irreversible' | | commitmentTxid | TEXT | The txid of the commitment transaction (when using commitments) |

Commitments Table: | Column | Type | Description | |--------|------|-------------| | txid | TEXT | Primary Key - Transaction ID of the commitment | | vaultId | TEXT | Associated vault ID | | created_at | INTEGER | Unix timestamp when the commitment was registered |

Network State Table: | Column | Type | Description | |--------|------|-------------| | id | INTEGER | Primary Key (always 1) | | last_checked_height | INTEGER | Last block height that was checked |

Authorized Addresses Table (in separate database): | Column | Type | Description | |--------|------|-------------| | address | TEXT | Primary Key - Btc address authorized to use the service | | created_at | TIMESTAMP | When the address was added to the database |

This table is stored in a separate database file ({networkId}.sqlite) and is managed by another process. The watchtower only reads from this database when commitment verification is enabled.

🎯 Summary

The Watchtower API efficiently tracks Bitcoin transactions related to vaults and notifies users when their funds are accessed. It is designed to minimize redundant API calls and maximize efficiency in blockchain polling.

By combining commitment verification, efficient blockchain monitoring, and persistent push notifications, the Watchtower provides a robust security layer for Bitcoin vault users.