diff --git a/packages/dapi/README.md b/packages/dapi/README.md index bc6afbaa742..550529c24d9 100644 --- a/packages/dapi/README.md +++ b/packages/dapi/README.md @@ -5,64 +5,15 @@ A decentralized API for the Dash network -## Table of Contents -- [Install](#install) - - [Dependencies](#dependencies) -- [Usage](#usage) -- [Configuration](#configuration) -- [Making requests](#making-basic-requests) -- [API Reference](#api-reference) -- [Contributing](#contributing) -- [License](#license) +## Overview -## Install +DAPI (Decentralized API) is the decentralized HTTP API layer for the Dash Evolution platform. It provides a simple interface for accessing the Dash network, both for traditional Dash functionality and for the Dash Platform features. -```sh -npm install -``` +DAPI is designed to be run on the Dash masternode network, providing a decentralized, high-availability API service with no single point of failure. -### Dependencies +## Documentation -DAPI targets the latest v20 release of Node.js. - -DAPI requires the latest version of [dashcore](https://github.com/dashevo/dash-evo-branches/tree/evo) with Evolution features (special branch repo). - -1. **Install core.** You can use the docker image (`dashcore:evo`) or clone code from [the repository](https://github.com/dashevo/dash-evo-branches/tree/evo), switch to the `evo` branch, and build it by yourself. Note: you need to build image with ZMQ and wallet support. You can follow the build instructions located [here](https://github.com/dashevo/dash-evo-branches/tree/evo/doc) -2. **Configure core.** DAPI needs dashcore's ZMQ interface to be exposed and all indexes enabled. You can find the example config for dashcore [here](doc/dependencies_configs/dash.conf). To start dashcore process with this config, copy it somewhere to your system, and then run `./src/dashd -conf=/path/to/your/config`. - -## Usage - -After you've installed all the dependencies, you can start DAPI by running the `npm start` command inside the DAPI repo directory. - -```sh -npm start -``` - -## Configuration - -DAPI is configured via environment variables either explicitly passed or present in the `.env` dotfile. For example, to change the DAPI port, execute DAPI with the following arguments: `RPC_SERVER_PORT=3010 npm start`. Consult the sample environment [file](.env.example). You can see the full list of available options [here](doc/CONFIGURATION.md). - -## Making basic requests - -DAPI uses [JSON-RPC 2.0](https://www.jsonrpc.org/specification) as the main interface. If you want to confirm that DAPI is functioning and synced, you can request the best block height. - -Send the following json to your DAPI instance: - -```json -{"jsonrpc": "2.0","method": "getBestBlockHeight", "id": 1} -``` - -Note that you always need to specify an id, otherwise the server will respond with an empty body, as mentioned in the [spec](https://www.jsonrpc.org/specification#notification). - -## API Reference - -A list of all available RPC commands, along with their various arguments and expected responses can be found [here](doc/REFERENCE.md) - -Implementation of these commands can be viewed [here](lib/rpcServer/commands). - -## Contributing - -Feel free to dive in! [Open an issue](https://github.com/dashpay/platform/issues/new/choose) or submit PRs. +DAPI documentaion is available in the [doc](./doc/index.md) directory and [website](https://docs.dash.org/projects/platform/en/stable/docs/explanations/dapi.html). ## License diff --git a/packages/dapi/doc/CONFIGURATION.md b/packages/dapi/doc/CONFIGURATION.md deleted file mode 100644 index 068e72f519b..00000000000 --- a/packages/dapi/doc/CONFIGURATION.md +++ /dev/null @@ -1,26 +0,0 @@ -[Back to the main page](/README.md) - -# DAPI configuration - -DAPI is configured via environment variables. So, for example, in order to change rpc server port, you need to run `RPC_SERVER_PORT=3010 npm start`. - -## Full list of available options - -* `LIVENET` - boolean. Set to true if you are going to run DAPI on the livenet. Defaults to `false`. -* `RPC_SERVER_PORT` - integer. Port on which DAPI server will listen. Defaults to `3000` -* `DASHCORE_RPC_PROTOCOL` string. Protocol for connecting to dashcore RPC. Defaults to `http` -* `DASHCORE_RPC_USER`. Defaults to `dashrpc` -* `DASHCORE_RPC_PASS`. Defaults to `password` -* `DASHCORE_RPC_HOST`. Defaults to `127.0.0.1` -* `DASHCORE_RPC_PORT`. Defaults to `30002` -* `DASHCORE_ZMQ_HOST`. Defaults to `127.0.0.1` -* `DASHCORE_ZMQ_PORT`. Defaults to `30003` -* `DASHCORE_P2P_HOST`. Defaults to `127.0.0.1` -* `DASHCORE_P2P_PORT`. Defaults to `30001` -* `DRIVE_RPC_HOST`. Defaults to `127.0.0.1` -* `DRIVE_RPC_PORT`. Defaults to `6000` -* `DASHCORE_P2P_NETWORK`. Can be `testnet`, `regtest` and `livenet`. Defaults to `testnet` -* `NETWORK` Can be `testnet`, `regtest` and `livenet` Defaults to `testnet` -* `BLOOM_FILTER_PERSISTENCE_TIMEOUT` - integer. Bloom filter persistence timeout in milliseconds. Defaults to 1 minute. - -[Back to the main page](/README.md) diff --git a/packages/dapi/doc/README.md b/packages/dapi/doc/README.md deleted file mode 100644 index ea87395ae1b..00000000000 --- a/packages/dapi/doc/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# DAPI documentation. - -This is the home for the DAPI documentation. - -### Contents - -* [Configuration](./CONFIGURATION.md) \ No newline at end of file diff --git a/packages/dapi/doc/REFERENCE.md b/packages/dapi/doc/REFERENCE.md deleted file mode 100644 index fb814322ffa..00000000000 --- a/packages/dapi/doc/REFERENCE.md +++ /dev/null @@ -1,57 +0,0 @@ -[Back to the main page](/README.md) - -## API Reference - -### Table of Contents - -- [Layer 1 endpoints](#layer-1-endpoints) - - - [generate](#generate) - - [getBestBlockHash](#getbestblockhash) - - [getBlockHash](#getblockhash) - -## Layer 1 endpoints - -### getBestBlockHash - -Returns best block hash (hash of the chaintip) - -*takes no arguments* - -##### Response - -| name | type | description | -|--------------|------------------|----------------------------------------| -| blockHash | promise (string) | hash of chaintip | - ---- - -### getBestBlockHeight - -Returns best block height (height of the chaintip) - -*takes no arguments* - -##### Response - -| name | type | description | -|--------|------------------|--------------------| -| height | promise (string) | height of chaintip | - ---- - -### getBlockHash - -Returns block hash for a given height. - -##### Params - -| name | type | description | -|--------------|--------|----------------------------------------| -| args.height | number | block height | - -##### Response - -| name | type | description | -|------------|------------------|---------------------------------------------| -| blockHash | promise (string) | promise containing a string of a block hash | diff --git a/packages/dapi/doc/architecture.md b/packages/dapi/doc/architecture.md new file mode 100644 index 00000000000..904dc5b4511 --- /dev/null +++ b/packages/dapi/doc/architecture.md @@ -0,0 +1,229 @@ +# DAPI Architecture + +This document explains the high-level architecture of DAPI, its components, and how they interact with the Dash ecosystem. + +## Overview + +DAPI (Decentralized API) serves as the gateway to the Dash network, providing access to both Dash Core blockchain functionality and Dash Platform (Evolution) features. +Unlike traditional centralized APIs, DAPI is designed to run on the Dash masternode network, ensuring high availability and censorship resistance. + +## Architecture Diagram + +``` +┌─────────────────────────────────────────────────────┐ +│ DAPI │ +│ │ +│ ┌───────────────────┐ ┌─────────────────────┐ │ +│ │ │ │ │ │ +│ │ API Process │ │ Core Streams │ │ +│ │ (api.js) │ │ Process │ │ +│ │ │ │ (core-streams.js) │ │ +│ │ - Core endpoints │ │ │ │ +│ │ - Platform │ │ - Block streaming │ │ +│ │ endpoints │ │ - TX streaming │ │ +│ │ - JSON-RPC │ │ - Masternode list │ │ +│ │ │ │ streaming │ │ +│ └───────┬───────────┘ └─────────┬───────────┘ │ +│ │ │ │ +└──────────┼──────────────────────────┼───────────────┘ + │ │ + ▼ ▼ +┌──────────────────────┐ ┌─────────────────────────┐ +│ │ │ │ +│ Dash Core │ │ Drive & Tenderdash │ +│ │ │ │ +│ - Blockchain │ │ - Platform State │ +│ - Mempool │ │ - Data Contracts │ +│ - Wallet │ │ - Identities │ +│ - P2P Network │ │ - Documents │ +│ │ │ │ +└──────────────────────┘ └─────────────────────────┘ +``` + +## Key Components + +### API Process + +The API process is the main entry point for DAPI. It handles the basic gRPC and JSON-RPC endpoints, including both Core and Platform functionality. + +#### Responsibilities: + +- **JSON-RPC Server**: Serves legacy JSON-RPC endpoints +- **Core gRPC Endpoints**: Serves Core blockchain endpoints +- **Platform gRPC Endpoints**: Serves Platform (Evolution) endpoints + +#### Connections: + +- **Dash Core**: Connects to Core via RPC and ZMQ +- **Drive**: Connects to Drive via gRPC +- **Tenderdash**: Connects to Tenderdash via RPC and WebSocket + +#### Startup Sequence: + +1. Load configuration +2. Connect to Dash Core's ZMQ interface +3. Initialize Platform and Drive clients +4. Connect to Tenderdash WebSocket +5. Start JSON-RPC server +6. Start gRPC server with Core and Platform handlers + +#### Endpoints Served: + +- **Core gRPC Endpoints**: + - `getBestBlockHeight` + - `getBlockchainStatus` + - `getTransaction` + - `broadcastTransaction` + +- **Platform gRPC Endpoints**: + - `broadcastStateTransition` + - `waitForStateTransitionResult` + - `getConsensusParams` + - `getStatus` + - And various unimplemented endpoints + +- **JSON-RPC Endpoints**: + - `getBestBlockHash` + - `getBlockHash` + +#### Dependencies: + +- Dash Core (via RPC and ZMQ) +- Drive (via gRPC) +- Tenderdash (via RPC and WebSocket) + +#### How to run + +```bash +node scripts/api.js +``` + +### Core Streams Process + +The Core Streams process handles streaming data from the Dash blockchain, including blocks, transactions, and masternode lists. + +#### Responsibilities: + +- **Transaction Streaming**: Stream transactions matching bloom filters +- **Block Header Streaming**: Stream block headers and chain locks +- **Masternode List Streaming**: Stream masternode list updates + +#### Connections: + +- **Dash Core**: Connects to Core via RPC and ZMQ +- **Chain Data Provider**: Maintains a cache of block headers + +#### Startup Sequence: + +1. Load configuration +2. Connect to Dash Core's ZMQ interface +3. Initialize bloom filter emitter collection +4. Set up event listeners for ZMQ events +5. Initialize chain data provider and block headers cache +6. Initialize masternode list sync +7. Start gRPC server with streaming handlers + +#### Endpoints Served: + +- **Stream gRPC Endpoints**: + - `subscribeToTransactionsWithProofs` + - `subscribeToBlockHeadersWithChainLocks` + - `subscribeToMasternodeList` + +#### Dependencies: +- Dash Core (via RPC and ZMQ) + +### Communication + +Both API and Core Streams components operate independently and do not directly communicate with each other. +Instead, they both connect to the same underlying services (Dash Core, Drive, Tenderdash) to provide their respective functionality. + +## Interfaces + +DAPI provides two main interfaces for client interaction: + +### gRPC Interface + +The primary and recommended interface, using Protocol Buffers for efficient, typed communication. Supports: +- Request/response endpoints +- Server-side streaming endpoints +- Strong typing and versioning + +### JSON-RPC Interface + +A legacy interface provided for compatibility with existing tools. Features: +- Compatible with the JSON-RPC 2.0 specification +- Limited subset of Dash Core's JSON-RPC functionality +- No streaming capabilities + +## Connection to the Dash Ecosystem + +DAPI connects to several underlying services: + +### Dash Core + +DAPI communicates with Dash Core in two ways: +- **RPC Interface**: For direct blockchain queries and commands +- **ZMQ Interface**: For real-time notifications of new blocks, transactions, and chainlocks + +### Drive + +For Platform functionality, DAPI connects to Drive via gRPC. Drive is responsible for: +- Processing and validating state transitions +- Maintaining Platform state (data contracts, documents, identities) +- Providing proofs for Platform operations + +### Tenderdash + +DAPI connects to Tenderdash (a modified version of Tendermint) which serves as the consensus engine for Dash Platform. Connections include: +- **RPC Interface**: For querying Platform chain state +- **WebSocket Interface**: For subscribing to real-time Platform events + +## Process Flow Examples + +### Example 1: Querying a transaction + +1. Client sends gRPC request to `getTransaction` endpoint +2. API process receives request +3. API process queries Dash Core via RPC +4. Dash Core returns transaction data +5. API process formats the response and returns it to the client + +### Example 2: Subscribing to transactions with a bloom filter + +1. Client creates a bloom filter and connects to `subscribeToTransactionsWithProofs` stream +2. Core Streams process receives the request and registers the bloom filter +3. When Dash Core emits a ZMQ notification for a new transaction: + - Core Streams process tests the transaction against the bloom filter + - If it matches, the transaction is sent to the client with merkle proofs +4. The stream continues until the client disconnects + +## Security + +DAPI protects connections by using TLS to encrypt communication between clients and the masternodes. +This encryption safeguards transmitted data from unauthorized access, interception, or tampering. +Platform gRPC endpoints provide an additional level of security by optionally returning cryptographic proofs. +Successful proof verification guarantees that the server responded without modifying the requested data. + +## Deployment Considerations + +DAPI is designed to be deployed on masternode. The prefered and officaially supported way is to use [dashmate](https://docs.dash.org/en/stable/docs/user/network/dashmate/index.html). + +## Monitoring + +Both components use the same logging infrastructure, allowing for consistent monitoring of the entire DAPI service. +Logs are output to the console by default and can be redirected to files or log management systems as needed. + +Key events that are logged include: +- Process startup and shutdown +- Connection to dependencies +- Server listening status +- Error conditions + +## Endpoints + +See the [endpoints](./endpoints/index.md) document for details on available endpoints. + +## Further Information + +- Consult the [Dash Platform Developer Documentation](https://docs.dash.org/projects/platform/en/stable/) for more information about the broader Dash Platform ecosystem diff --git a/packages/dapi/doc/dependencies_configs/dash.conf b/packages/dapi/doc/dependencies_configs/dash.conf deleted file mode 100755 index f81fa8ae390..00000000000 --- a/packages/dapi/doc/dependencies_configs/dash.conf +++ /dev/null @@ -1,33 +0,0 @@ -# general -daemon=0 # set it to 1 if you want to run dash as a daemon process -logtimestamps=1 -maxconnections=256 -debug=0 -printtoconsole=1 - -# Enabling indices -txindex=1 -addressindex=1 -timestampindex=1 -spentindex=1 - -# Enabling ZeroMQ notifications -zmqpubrawtx=tcp://0.0.0.0:30003 -zmqpubrawtxlock=tcp://0.0.0.0:30003 -zmqpubhashblock=tcp://0.0.0.0:30003 -#zmqpubhashtx=tcp://0.0.0.0:30003 -#zmqpubhashtxlock=tcp://0.0.0.0:30003 -#zmqpubrawblock=tcp://0.0.0.0:30003 - -# JSONRPC -server=1 -rpcuser=dashrpc -rpcpassword=password -rpcport=30002 -rpcbind=0.0.0.0 -rpcallowip=0.0.0.0/0 -rpcworkqueue=64 - -# external network -listen=1 -bind=0.0.0.0 diff --git a/packages/dapi/doc/endpoints/core/broadcastTransaction.md b/packages/dapi/doc/endpoints/core/broadcastTransaction.md new file mode 100644 index 00000000000..e8e779bf424 --- /dev/null +++ b/packages/dapi/doc/endpoints/core/broadcastTransaction.md @@ -0,0 +1,83 @@ +# broadcastTransaction + +## Client API + +Broadcasts a transaction to the Dash network. + +**Request Parameters**: +- `transaction`: Binary buffer containing serialized transaction (required) + +**Response Parameters**: +- `transactionId`: ID of the broadcast transaction (string) + +**Example Usage**: +```javascript +const txHex = '0200000001...'; // Raw transaction hex +const result = await dapiClient.core.broadcastTransaction(txHex); +console.log(`Transaction broadcast with ID: ${result.transactionId}`); +``` + +## Internal Implementation + +The `broadcastTransaction` endpoint is implemented in the `broadcastTransactionHandlerFactory.js` file. + +### Implementation Details + +1. **Transaction Validation** + - Validates that the transaction is properly formatted and serialized + - Performs basic structure checks before attempting to broadcast + +2. **Core RPC Interaction** + - Calls Core's `sendrawtransaction` RPC method + - Passes the raw transaction data to the Core node for propagation to the network + +3. **Error Handling** + - Maps Core RPC error codes to appropriate gRPC error codes + - Handles common error scenarios: + - Invalid transaction format (RPC error code -22) + - Transaction rejected (RPC error code -26) + - Transaction already in blockchain (RPC error code -27) + - Transaction validation failures (RPC error code -25) + - Provides descriptive error messages to help diagnose transaction issues + +4. **Dependencies** + - Dash Core RPC interface for transaction broadcasting + +### Code Flow + +``` +Client Request + → gRPC Server + → broadcastTransactionHandler + → Validate Transaction Format + → Convert Binary to Hex (if needed) + → Call sendrawtransaction RPC + → If Successful: + → Return Transaction ID + → If Error: + → Map RPC Error to gRPC Error + → Return Error Response +``` + +### Common Error Scenarios + +The handler maps Core RPC errors to meaningful client responses: + +1. **Invalid Transaction Format (-22)** + - Occurs when the transaction data is malformed + - Returns INVALID_ARGUMENT error with details + +2. **Transaction Rejected (-26)** + - Occurs when the transaction is valid but rejected by the network + - Common causes include double spends, insufficient fees, or script verification failures + - Returns FAILED_PRECONDITION error with specific rejection reason + +3. **Already in Blockchain (-27)** + - Occurs when attempting to broadcast a transaction that's already confirmed + - Returns ALREADY_EXISTS error + +4. **Transaction Validation Error (-25)** + - Occurs when the transaction fails internal validation checks + - Returns INVALID_ARGUMENT error with validation details + +This error mapping helps clients understand exactly why a transaction broadcast failed. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/core/getBestBlockHeight.md b/packages/dapi/doc/endpoints/core/getBestBlockHeight.md new file mode 100644 index 00000000000..16c1fa0e822 --- /dev/null +++ b/packages/dapi/doc/endpoints/core/getBestBlockHeight.md @@ -0,0 +1,54 @@ +# getBestBlockHeight + +## Client API + +Returns the height of the latest block in the chain. + +**Request Parameters**: None + +**Response Parameters**: +- `height`: Height of the best block (number) + +**Example Usage**: +```javascript +const height = await dapiClient.core.getBestBlockHeight(); +console.log(`Current block height: ${height}`); +``` + +## Internal Implementation + +The `getBestBlockHeight` endpoint is implemented in the `getBestBlockHeightHandlerFactory.js` file. + +### Implementation Details + +1. **Caching Mechanism** + - The implementation uses a caching strategy to avoid making frequent RPC calls to the Core node + - The cache is invalidated when a new block is detected via ZMQ notifications + - RPC calls to Core are only made when the cache is empty or invalid + +2. **Handler Flow** + - When a request is received, the handler first checks if a valid cached value exists + - If cache is valid, returns the cached value immediately + - If cache is invalid or empty, makes an RPC call to Core's `getBlockCount` method + - The returned value is cached before being sent back to the client + +3. **Dependencies** + - Dash Core RPC interface + - ZMQ for new block notifications (for cache invalidation) + +4. **Error Handling** + - Forwards any errors from the Core RPC call with appropriate gRPC error codes + - Handles network connectivity issues with the Core node + +### Code Flow + +``` +Client Request + → gRPC Server + → getBestBlockHeightHandler + → Check Cache + → If Valid: Return Cached Height + → If Invalid: Call Core RPC getBlockCount + → Cache Result + → Return Height +``` \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/core/getBlockchainStatus.md b/packages/dapi/doc/endpoints/core/getBlockchainStatus.md new file mode 100644 index 00000000000..5df6e869343 --- /dev/null +++ b/packages/dapi/doc/endpoints/core/getBlockchainStatus.md @@ -0,0 +1,82 @@ +# getBlockchainStatus + +## Client API + +Returns status information about the Dash blockchain. + +**Request Parameters**: None + +**Response Parameters**: +- `chain`: Chain name (e.g., "main", "test", "regtest") +- `blocks`: Current block count +- `headers`: Current header count +- `bestBlockHash`: Hash of the best block +- `difficulty`: Current network difficulty +- `verificationProgress`: Sync progress (0-1) +- `chainWork`: Total chain work in hex +- `softForks`: Information about active and pending soft forks +- `protocolVersion`: P2P protocol version +- `version`: Core software version + +**Example Usage**: +```javascript +const status = await dapiClient.core.getBlockchainStatus(); +console.log(`Network: ${status.chain}, Blocks: ${status.blocks}`); +``` + +## Internal Implementation + +The `getBlockchainStatus` endpoint is implemented in the `getBlockchainStatusHandlerFactory.js` file. + +### Implementation Details + +1. **Data Collection** + - The implementation fetches data from two Core RPC calls in parallel: + - `getBlockchainInfo`: For blockchain-specific information + - `getNetworkInfo`: For network-specific details + - Combines the results into a comprehensive response + +2. **Caching Strategy** + - Uses caching to reduce load on Core node + - Cache is invalidated when new blocks are detected via ZMQ notifications + +3. **Status Determination** + - Calculates sync status (SYNCING or READY) based on verification progress value + - Provides chain status details from Core's internal state + +4. **Dependencies** + - Dash Core RPC interface + - ZMQ for new block notifications (for cache invalidation) + +5. **Error Handling** + - Maps Core RPC errors to appropriate gRPC error codes + - Handles connection issues with informative error messages + +### Code Flow + +``` +Client Request + → gRPC Server + → getBlockchainStatusHandler + → Check Cache + → If Valid: Return Cached Status + → If Invalid: + → Parallel Requests: + → Call getBlockchainInfo RPC + → Call getNetworkInfo RPC + → Combine Results + → Determine Sync Status + → Cache Response + → Return Status +``` + +### Response Construction + +The handler combines information from multiple sources: +- Basic blockchain info: chain name, blocks, headers, best hash +- Network details: protocol version, services, connections +- Mining information: difficulty, chain work +- Software version information +- Soft fork activation statuses + +This provides clients with a complete overview of the current blockchain state in a single call. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/core/getTransaction.md b/packages/dapi/doc/endpoints/core/getTransaction.md new file mode 100644 index 00000000000..d29797dcffa --- /dev/null +++ b/packages/dapi/doc/endpoints/core/getTransaction.md @@ -0,0 +1,82 @@ +# getTransaction + +## Client API + +Retrieves a transaction by ID. + +**Request Parameters**: +- `id`: Transaction ID (string, required) + +**Response Parameters**: +- `transaction`: Binary buffer containing serialized transaction +- `blockHash`: Hash of the block containing the transaction +- `height`: Height of the block containing the transaction +- `confirmations`: Number of confirmations +- `isInstantLocked`: Whether transaction is instant locked +- `isChainLocked`: Whether transaction is chain locked + +**Example Usage**: +```javascript +const txId = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; +const tx = await dapiClient.core.getTransaction(txId); +console.log(`Transaction is in block: ${tx.height}`); +``` + +## Internal Implementation + +The `getTransaction` endpoint is implemented in the `getTransactionHandlerFactory.js` file. + +### Implementation Details + +1. **Input Validation** + - Validates that the transaction ID is a valid 64-character hex string + - Returns appropriate error responses for invalid inputs + +2. **Core RPC Interaction** + - Calls Core's `getrawtransaction` RPC method with `verbose=1` flag + - This returns both the raw transaction data and metadata about its inclusion in the blockchain + +3. **Response Transformation** + - Converts the Core RPC response to the DAPI gRPC format + - Maps fields from Core's response to DAPI's response structure + - Adds additional fields like InstantLock and ChainLock status + +4. **Error Handling** + - Maps Core RPC error codes to appropriate gRPC error codes + - Handles "transaction not found" (-5) errors specifically + - Provides descriptive error messages for debugging + +5. **Dependencies** + - Dash Core RPC interface for transaction data + - InsightAPI (optional fallback) if transaction is not found in Core + +### Code Flow + +``` +Client Request + → gRPC Server + → getTransactionHandler + → Validate Transaction ID Format + → Call getrawtransaction RPC with verbose=1 + → If Found: Process Response + → Extract Transaction Data + → Extract Block Information + → Check Lock Statuses + → Build Response + → If Not Found: Return Not Found Error + → Return Transaction Response +``` + +### Transaction Lock Status + +The handler checks two important security features of Dash transactions: + +1. **InstantLock Status** + - Indicates if the transaction has been locked by InstantSend + - Provides immediate transaction security without waiting for confirmations + +2. **ChainLock Status** + - Indicates if the block containing the transaction is protected by ChainLocks + - Provides protection against 51% attacks and chain reorganizations + +These statuses help clients determine the security level of a transaction. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/core/subscribeToMasternodeList.md b/packages/dapi/doc/endpoints/core/subscribeToMasternodeList.md new file mode 100644 index 00000000000..905f8c761ea --- /dev/null +++ b/packages/dapi/doc/endpoints/core/subscribeToMasternodeList.md @@ -0,0 +1,87 @@ +# subscribeToMasternodeList + +## Client API + +Subscribes to masternode list updates. + +**Request Parameters**: None + +**Response Parameters**: +- Stream of `masternodeListDiff` messages with masternode list differences + +**Example Usage**: +```javascript +const stream = dapiClient.core.subscribeToMasternodeList(); + +stream.on('data', (masternodeListDiff) => { + console.log('Masternode list updated:', masternodeListDiff); +}); +``` + +## Internal Implementation + +The `subscribeToMasternodeList` endpoint is implemented in the `subscribeToMasternodeListHandlerFactory.js` file. + +### Implementation Details + +1. **Masternode List Sync** + - Uses the `MasternodeListSync` class to maintain a synchronized view of the masternode list + - Listens for updates from Core node via RPC and ZMQ + +2. **Streaming Mechanism** + - Establishes a gRPC server-side streaming connection + - Emits masternode list differences when changes are detected + - Client receives a stream of diff updates rather than full list snapshots + +3. **Diff Calculation** + - Calculates only the changes between previous and current masternode lists + - Includes added, removed, and modified masternodes + - Optimizes bandwidth by sending only what has changed + +4. **Dependencies** + - Dash Core RPC interface for initial list retrieval + - ZMQ for change notifications + - MasternodeListSync for maintaining state + +5. **Error Handling** + - Handles disconnections from Core + - Provides reconnection logic + - Propagates errors to the client through the stream + +### Code Flow + +``` +Client Request + → gRPC Server + → subscribeToMasternodeListHandler + → Initialize Stream Response + → Get Initial Masternode List + → Send Initial List to Client + → Subscribe to Masternode List Updates + → On Update: + → Calculate Diff from Previous List + → Send Diff to Client + → On Client Disconnect: + → Clean up Subscriptions +``` + +### Masternode List Diffs Structure + +The diff updates contain several key components: + +1. **Base Block Hash** + - The block hash where this diff starts + +2. **Block Hash** + - The block hash where this diff ends + +3. **Added Masternodes** + - List of newly activated masternodes + +4. **Modified Masternodes** + - List of existing masternodes with changed properties + +5. **Removed Masternodes** + - List of masternodes that are no longer active + +This structure allows clients to efficiently maintain their own copy of the masternode list by applying these diffs to their local state. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/index.md b/packages/dapi/doc/endpoints/index.md new file mode 100644 index 00000000000..4210c8c29f0 --- /dev/null +++ b/packages/dapi/doc/endpoints/index.md @@ -0,0 +1,109 @@ +# DAPI Endpoints Overview + +DAPI offers a variety of endpoints through two main interfaces: gRPC and JSON-RPC. This document provides an overview of all available endpoints and links to detailed documentation. + +## Interface Types + +### gRPC (Recommended) + +The gRPC interface is the recommended way to interact with DAPI. It offers: +- Better performance +- Strong typing +- Streaming capabilities +- Native support in many languages + +### JSON-RPC (Legacy) + +The JSON-RPC interface will eventually be deprecated. It offers: +- HTTP-based requests +- Compatibility with existing tools +- Simpler integration for basic use cases + +## Endpoint Categories + +DAPI endpoints are organized into three main categories: + +### 1. Core Endpoints + +These endpoints provide access to the underlying Dash blockchain (Core) functionality, such as blocks, transactions, and network status. + +**Main gRPC endpoints:** +- [`getBestBlockHeight`](./core/getBestBlockHeight.md) - Returns the current blockchain height +- [`getBlockchainStatus`](./core/getBlockchainStatus.md) - Returns blockchain status information +- [`getTransaction`](./core/getTransaction.md) - Retrieves transaction data by ID +- [`broadcastTransaction`](./core/broadcastTransaction.md) - Broadcasts a raw transaction to the network +- [`subscribeToMasternodeList`](./core/subscribeToMasternodeList.md) - Stream masternode list updates + +### 2. Platform Endpoints + +These endpoints provide access to Dash Platform (Evolution) features, enabling interaction with decentralized applications, identities, and data contracts. + +**Main gRPC endpoints:** +- [`broadcastStateTransition`](./platform/broadcastStateTransition.md) - Broadcasts a state transition to the platform +- [`waitForStateTransitionResult`](./platform/waitForStateTransitionResult.md) - Waits for a state transition to be processed +- [`getConsensusParams`](./platform/getConsensusParams.md) - Retrieves platform consensus parameters +- [`getStatus`](./platform/getStatus.md) - Gets platform status information + +The following endpoints are defined in the gRPC service but are served by Drive ABCI directly: + +- `getIdentity` +- `getIdentitiesContractKeys` +- `getIdentityBalance` +- `getIdentityBalanceAndRevision` +- `getIdentityKeys` +- `getDocuments` +- `getDataContract` +- `getDataContracts` +- `getDataContractHistory` +- `getIdentityByPublicKeyHash` +- `getIdentitiesByPublicKeyHashes` +- `getProofs` +- `getEpochsInfo` +- `getProtocolVersionUpgradeVoteStatus` +- `getProtocolVersionUpgradeState` +- `getIdentityContractNonce` +- `getIdentityNonce` + + +### 3. Stream Endpoints + +These endpoints provide real-time streaming data from the Dash network, including blocks, transactions, and masternode list updates. + +**Main streaming endpoints:** +- [`subscribeToBlockHeadersWithChainLocks`](./streams/subscribeToBlockHeadersWithChainLocks.md) - Stream block headers and chain locks +- [`subscribeToTransactionsWithProofs`](./streams/subscribeToTransactionsWithProofs.md) - Stream transactions matching a bloom filter + +### 4. JSON-RPC Endpoints + +These endpoints provide a subset of Dash Core functionality through the JSON-RPC interface for backward compatibility. + +**Available endpoints:** +- [`getBestBlockHash`](./json-rpc/getBestBlockHash.md) - Returns the hash of the best block +- [`getBlockHash`](./json-rpc/getBlockHash.md) - Returns the hash of a block at a specific height + +## Using the Endpoints + +### Direct Access + +You can access these endpoints directly using gRPC or JSON-RPC clients: + +**gRPC Example (using grpcurl):** +```bash +grpcurl -plaintext localhost:2500 org.dash.platform.dapi.v0.Core/getBestBlockHeight +``` + +**JSON-RPC Example (using curl):** +```bash +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"getBestBlockHash","params":[],"id":1}' http://localhost:2501 +``` + +### Client Libraries + +For most applications, it's recommended to use one of the DAPI client libraries: + +- [Dash SDK (JavaScript)](https://docs.dash.org/projects/platform/en/stable/docs/sdk-js/overview.html) +- [Dash SDK (Rust)](https://docs.dash.org/projects/platform/en/stable/docs/sdk-rs/overview.html) +- [DAPI Client (JavaScript)](https://docs.dash.org/projects/platform/en/stable/docs/dapi-client-js/overview.html) +- [gRPC Clients](https://github.com/dashpay/platform/tree/master/packages/dapi-grpc) (for other languages) + +These client libraries handle the complexity of interacting with DAPI and provide a more convenient interface for developers. diff --git a/packages/dapi/doc/endpoints/json-rpc/getBestBlockHash.md b/packages/dapi/doc/endpoints/json-rpc/getBestBlockHash.md new file mode 100644 index 00000000000..3476a3c88e9 --- /dev/null +++ b/packages/dapi/doc/endpoints/json-rpc/getBestBlockHash.md @@ -0,0 +1,87 @@ +# getBestBlockHash + +## Client API + +Returns the hash of the best (tip) block in the longest blockchain. + +**Request Format**: +```json +{ + "jsonrpc": "2.0", + "method": "getBestBlockHash", + "params": [], + "id": 1 +} +``` + +**Response Format**: +```json +{ + "jsonrpc": "2.0", + "result": "000000000000001bb82a7f5973618cfd3588ba1df2ee3004d4add6321678564b", + "id": 1 +} +``` + +**Example Usage**: +```javascript +// Using fetch API +const response = await fetch('http://localhost:2501', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'getBestBlockHash', + params: [], + id: 1 + }) +}); +const data = await response.json(); +console.log(`Best block hash: ${data.result}`); +``` + +## Internal Implementation + +The `getBestBlockHash` endpoint is implemented in the `getBestBlockHash.js` file. + +### Implementation Details + +1. **Caching Mechanism** + - Implements a caching strategy to avoid repeated calls to Core + - Cache is invalidated when new blocks are detected via ZMQ + - Only makes a Core RPC call when the cache is empty or invalid + +2. **Core Integration** + - Interfaces with Dash Core via RPC to get the latest block hash + - Uses the Core's `getBestBlockHash` method directly + +3. **Event Handling** + - Subscribes to ZMQ `hashblock` events from Core + - Uses these events to detect when new blocks are added to the chain + - Invalidates the cache when a new block is detected + +4. **Error Handling** + - Wraps Core RPC errors in JSON-RPC compatible error responses + - Maintains consistency with JSON-RPC 2.0 specification + +5. **Dependencies** + - Dash Core RPC interface + - ZMQ client for new block notifications + +### Code Flow + +``` +Client Request + → JSON-RPC Server + → getBestBlockHash Handler + → Check Cache + → If Valid: Return Cached Hash + → If Invalid: + → Call Core RPC getBestBlockHash + → Cache Result + → Return Hash +``` + +### Endpoint Categorization + +This endpoint is categorized as a Layer 1 (L1) endpoint in the API documentation, indicating that it interacts directly with the Dash Core blockchain functionality. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/json-rpc/getBlockHash.md b/packages/dapi/doc/endpoints/json-rpc/getBlockHash.md new file mode 100644 index 00000000000..161b2cf1f95 --- /dev/null +++ b/packages/dapi/doc/endpoints/json-rpc/getBlockHash.md @@ -0,0 +1,108 @@ +# getBlockHash + +## Client API + +Returns the hash of the block at the specified height in the local best blockchain. + +**Request Format**: +```json +{ + "jsonrpc": "2.0", + "method": "getBlockHash", + "params": [1000], + "id": 1 +} +``` + +**Response Format**: +```json +{ + "jsonrpc": "2.0", + "result": "00000000000000437b4c6fa42c9e5095844c1ed847417cead17612d7b153643e", + "id": 1 +} +``` + +**Example Usage**: +```javascript +// Using fetch API +const response = await fetch('http://localhost:2501', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'getBlockHash', + params: [1000], + id: 1 + }) +}); +const data = await response.json(); +console.log(`Block hash at height 1000: ${data.result}`); +``` + +## Internal Implementation + +The `getBlockHash` endpoint is implemented in the `getBlockHash.js` file. + +### Implementation Details + +1. **Input Validation** + - Validates the input parameters against a schema + - Requires a single height parameter that must be a non-negative integer + - Returns appropriate error responses for invalid inputs + +2. **Core Integration** + - Interfaces with Dash Core via RPC to get the block hash + - Calls Core's `getBlockHash` method with the provided height + +3. **Direct Delegation** + - This endpoint is a simple pass-through to the Core RPC + - After validation, it directly calls the corresponding Core method with the same parameters + +4. **Error Handling** + - Maps Core RPC errors to JSON-RPC compatible error responses + - Handles "block height out of range" errors specifically + - Provides descriptive error messages to help diagnose issues + +5. **Dependencies** + - Dash Core RPC interface + - JSON schema validator for parameter validation + +### Code Flow + +``` +Client Request + → JSON-RPC Server + → getBlockHash Handler + → Validate Height Parameter + → If Invalid: Return Error Response + → Call Core RPC getBlockHash with height + → If Successful: Return Block Hash + → If Error: Map to JSON-RPC Error Response +``` + +### Schema Validation + +The endpoint uses a JSON schema to validate the input: + +```json +{ + "type": "array", + "items": { + "type": "number", + "minimum": 0 + }, + "minItems": 1, + "maxItems": 1 +} +``` + +This ensures that: +- The params field is an array +- It contains exactly one item +- The item is a number (block height) +- The height is non-negative + +### Endpoint Categorization + +This endpoint is categorized as a Layer 1 (L1) endpoint in the API documentation, indicating that it interacts directly with the Dash Core blockchain functionality. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/platform/broadcastStateTransition.md b/packages/dapi/doc/endpoints/platform/broadcastStateTransition.md new file mode 100644 index 00000000000..b783d5e44bc --- /dev/null +++ b/packages/dapi/doc/endpoints/platform/broadcastStateTransition.md @@ -0,0 +1,90 @@ +# broadcastStateTransition + +## Client API + +Broadcasts a state transition to the Dash Platform. + +**Request Parameters**: +- `stateTransition`: Binary buffer containing serialized state transition (required) + +**Response Parameters**: +- Empty response on success + +**Example Usage**: +```javascript +const stateTransitionHex = '0300...'; // Raw state transition hex +const result = await dapiClient.platform.broadcastStateTransition(stateTransitionHex); +console.log('State transition broadcast successfully'); +``` + +## Internal Implementation + +The `broadcastStateTransition` endpoint is implemented in the `broadcastStateTransitionHandlerFactory.js` file. + +### Implementation Details + +1. **State Transition Processing** + - Takes a state transition (ST) byte array as input + - Converts the state transition to base64 format for Tenderdash compatibility + - Sends the encoded state transition to Tenderdash via the `broadcast_tx` RPC call + +2. **Validation Flow** + - Tenderdash performs initial validation during the `broadcast_tx` call + - If validation fails, DAPI may perform a `check_tx` call to get detailed error information + - This provides clients with specific validation error messages + +3. **Error Handling** + - Handles various error scenarios with specialized error responses: + - State transition already in mempool ("tx already exists in cache") + - State transition already in blockchain + - Transaction too large + - Mempool full + - Broadcast timeout + - Maps Tenderdash errors to appropriate gRPC error codes + - Returns detailed error information to help diagnose issues + +4. **Dependencies** + - Tenderdash RPC interface for transaction broadcasting + - Drive for state transition validation + +### Code Flow + +``` +Client Request + → gRPC Server + → broadcastStateTransitionHandler + → Validate State Transition Format + → Convert to Base64 Encoding + → Call Tenderdash broadcast_tx RPC + → If Successful: + → Return Empty Response + → If Error: + → Try check_tx for Detailed Error (optional) + → Map Tenderdash Error to gRPC Error + → Return Error Response +``` + +### Common Error Scenarios + +The handler processes several common error conditions: + +1. **Already in Mempool** + - Error message: "tx already exists in cache" + - Indicates the state transition is already being processed + - Returns ALREADY_EXISTS gRPC error + +2. **Validation Failures** + - Various error messages depending on the specific validation issue + - Usually relates to state transition structure or signature problems + - Returns INVALID_ARGUMENT or FAILED_PRECONDITION errors + +3. **System Capacity Issues** + - "mempool is full" or "tx too large" + - Indicates system resource constraints + - Returns RESOURCE_EXHAUSTED error + +4. **Timeout Errors** + - Occurs when the broadcast operation exceeds time limits + - Returns DEADLINE_EXCEEDED error + +These detailed error responses help clients understand exactly why a state transition broadcast failed and how to resolve the issue. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/platform/getConsensusParams.md b/packages/dapi/doc/endpoints/platform/getConsensusParams.md new file mode 100644 index 00000000000..f2c50d3117f --- /dev/null +++ b/packages/dapi/doc/endpoints/platform/getConsensusParams.md @@ -0,0 +1,92 @@ +# getConsensusParams + +## Client API + +Retrieves the platform consensus parameters. + +**Request Parameters**: +- `height`: Block height to retrieve parameters for (optional, defaults to latest) + +**Response Parameters**: +- `blockMaxBytes`: Maximum block size in bytes +- `blockMaxGas`: Maximum block gas limit +- `blockTimeIotaMs`: Block time parameter in milliseconds +- `evidenceMaxAgeDuration`: Maximum age of evidence in nanoseconds +- `evidenceMaxAgeNumBlocks`: Maximum age of evidence in blocks +- `evidenceMaxBytes`: Maximum evidence size in bytes +- `validatorSlashAmount`: Amount to slash validators by + +**Example Usage**: +```javascript +// Get latest consensus parameters +const latestParams = await dapiClient.platform.getConsensusParams(); +console.log(`Max block size: ${latestParams.blockMaxBytes} bytes`); + +// Get consensus parameters at a specific height +const heightParams = await dapiClient.platform.getConsensusParams(1000); +console.log(`Max block size at height 1000: ${heightParams.blockMaxBytes} bytes`); +``` + +## Internal Implementation + +The `getConsensusParams` endpoint is implemented in the `getConsensusParamsFactory.js` file. + +### Implementation Details + +1. **Parameter Retrieval** + - Calls the `getConsensusParams` function which interfaces with Tenderdash + - Can retrieve parameters at the latest height or at a specific historical height + - Makes a `consensus_params` RPC call to Tenderdash + +2. **Parameter Processing** + - Converts raw Tenderdash parameters to the DAPI gRPC format + - Handles duration formats and converts them to standard time units + - Organizes parameters into logical categories + +3. **Input Validation** + - Validates that the height parameter (if provided) is a positive integer + - Returns appropriate error responses for invalid inputs + +4. **Error Handling** + - Maps Tenderdash RPC errors to appropriate gRPC error codes + - Handles connection issues with detailed error messages + - Returns NOT_FOUND errors for requests for non-existent heights + +5. **Dependencies** + - Tenderdash RPC interface for consensus parameter data + +### Code Flow + +``` +Client Request + → gRPC Server + → getConsensusParamsHandler + → Validate Height Parameter (if provided) + → Call getConsensusParams Function + → Call Tenderdash consensus_params RPC + → With height if specified + → Without height for latest params + → Process Response + → Format Parameters + → Build Response Object + → Return Consensus Parameters +``` + +### Consensus Parameter Categories + +The parameters are organized into several categories: + +1. **Block Parameters** + - `blockMaxBytes`: Maximum allowed block size + - `blockMaxGas`: Maximum gas allowed per block + - `blockTimeIotaMs`: Minimum time increment between blocks + +2. **Evidence Parameters** + - `evidenceMaxAgeDuration`: Maximum age of evidence in time + - `evidenceMaxAgeNumBlocks`: Maximum age of evidence in blocks + - `evidenceMaxBytes`: Maximum size of evidence + +3. **Validator Parameters** + - `validatorSlashAmount`: Amount to slash validators for misbehavior + +These parameters govern the fundamental rules of the blockchain, controlling aspects like performance, security, and economic incentives. They can change over time through governance processes, which is why the API allows retrieving parameters at specific heights. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/platform/getStatus.md b/packages/dapi/doc/endpoints/platform/getStatus.md new file mode 100644 index 00000000000..2510a7bcf6d --- /dev/null +++ b/packages/dapi/doc/endpoints/platform/getStatus.md @@ -0,0 +1,118 @@ +# getStatus + +## Client API + +Retrieves the current status of the Dash Platform. + +**Request Parameters**: None + +**Response Parameters**: +- `version`: Version information + - `protocolVersion`: Protocol version number + - `software`: Software version string +- `time`: Time information + - `blockTime`: Last block time + - `genesisTime`: Blockchain genesis time + - `localTime`: Local node time +- `chain`: Chain information + - `blockHeight`: Current block height + - `blocksPerDay`: Average blocks per day + - `bestBlockHash`: Hash of the best block + - `syncStatus`: Sync status (SYNCING or READY) +- `sync`: Sync information + - `startingBlockHeight`: Height when sync started + - `currentBlockHeight`: Current sync height + - `latestHeight`: Latest known height in the network +- `network`: Network information + - `peerCount`: Number of connected peers + - `isListening`: Whether node is listening for connections + - `chainId`: Chain identifier string +- `nodeId`: Node identifier +- `proTxHash`: Protx hash (for masternodes) + +**Example Usage**: +```javascript +const status = await dapiClient.platform.getStatus(); +console.log(`Platform block height: ${status.chain.blockHeight}`); +console.log(`Platform version: ${status.version.software}`); +console.log(`Sync status: ${status.chain.syncStatus}`); +``` + +## Internal Implementation + +The `getStatus` endpoint is implemented in the `getStatusHandlerFactory.js` file. + +### Implementation Details + +1. **Caching Mechanism** + - Implements a caching strategy to reduce load on Platform subsystems + - Cache is valid for 3 minutes by default + - Cache is invalidated when new platform blocks are detected + +2. **Data Collection** + - Fetches status information from multiple sources in parallel: + - Drive client status + - Tenderdash status through RPC + - Tenderdash network information + - Uses `Promise.allSettled` to handle potential failures in any subsystem + - Constructs a comprehensive response from all available data + +3. **Status Determination** + - Calculates sync status based on current height vs. latest known height + - Provides sync progress information when syncing + - Includes chain, network, and time information + +4. **Partial Results** + - Handles scenarios where some components are unavailable + - Returns partial status information when possible + - Provides fallback values for non-critical fields + +5. **Dependencies** + - Drive client for Drive status + - Tenderdash RPC for blockchain status + - Tenderdash networking for peer information + +### Code Flow + +``` +Client Request + → gRPC Server + → getStatusHandler + → Check Cache + → If Valid: Return Cached Status + → If Invalid: + → Parallel Requests (Promise.allSettled): + → Drive Status + → Tenderdash Status + → Tenderdash Network Info + → Process All Results + → Handle Any Failed Requests + → Calculate Derived Fields + → Cache Response + → Return Complete Status +``` + +### Response Construction + +The handler carefully builds a comprehensive status response: + +1. **Version Information** + - Protocol version: Consensus protocol version number + - Software version: Implementation version string + +2. **Time Information** + - Block time: Timestamp of the most recent block + - Genesis time: When the blockchain started + - Local time: Current node's time (for comparison) + +3. **Chain Information** + - Current height and hash information + - Sync status determination (SYNCING or READY) + - Estimated blocks per day calculation + +4. **Network Status** + - Peer count and listening status + - Chain ID for network identification + - Node identifiers for the current node + +This comprehensive status provides clients with a complete picture of the platform's current state and health. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/platform/waitForStateTransitionResult.md b/packages/dapi/doc/endpoints/platform/waitForStateTransitionResult.md new file mode 100644 index 00000000000..2134ff31741 --- /dev/null +++ b/packages/dapi/doc/endpoints/platform/waitForStateTransitionResult.md @@ -0,0 +1,104 @@ +# waitForStateTransitionResult + +## Client API + +Waits for a state transition to be processed by the platform and returns the result. + +**Request Parameters**: +- `stateTransitionHash`: Hash of the state transition to wait for (string, required) +- `prove`: Boolean indicating whether to return a proof (optional, default: false) + +**Response Parameters**: +- If successful: + - `proof`: Merkle proof of the state transition (if requested) +- If error: + - `error`: Error details object + - `error.code`: Error code + - `error.message`: Error message + - `error.data`: Additional error data + +**Example Usage**: +```javascript +const stHash = '4bc5547b87323ef4efd9ef3ebfee4aec53a3e31877f6498126318839a01cd943'; +const result = await dapiClient.platform.waitForStateTransitionResult(stHash, true); +if (result.error) { + console.error(`Error processing state transition: ${result.error.message}`); +} else { + console.log('State transition processed successfully with proof:', result.proof); +} +``` + +## Internal Implementation + +The `waitForStateTransitionResult` endpoint is implemented in the `waitForStateTransitionResultHandlerFactory.js` file. + +### Implementation Details + +1. **Wait Mechanism** + - Uses the `waitForTransactionToBeProvable` function to monitor transaction state + - Polls Tenderdash until the transaction is either confirmed or rejected + - Has configurable timeout periods to prevent indefinite waiting + +2. **Proof Generation** + - If the `prove` parameter is true, fetches a cryptographic proof of inclusion + - Calls Drive to generate the state transition proof + - This proof can be used for verification without trusting DAPI + +3. **Result Processing** + - Processes both successful and unsuccessful state transitions + - For successful transactions, returns proof if requested + - For failed transactions, returns detailed error information + +4. **Error Handling** + - Handles timeout errors with `DeadlineExceededGrpcError` + - Captures and formats transaction execution errors from Tenderdash + - Handles Drive unavailability for proof generation + +5. **Dependencies** + - Tenderdash for transaction monitoring + - Drive for proof generation + - Internal waitForTransactionToBeProvable utility + +### Code Flow + +``` +Client Request + → gRPC Server + → waitForStateTransitionResultHandler + → Verify Tenderdash Availability + → Call waitForTransactionToBeProvable + → Poll Transaction Status + → If Timeout: Return DeadlineExceededError + → If Error: Process Transaction Error + → If Success: + → If Prove=true: + → Call Drive to Generate Proof + → Return Proof + → If Prove=false: + → Return Empty Success Response + → Return Response +``` + +### Transaction Status Monitoring + +The handler uses sophisticated techniques to monitor transaction status: + +1. **Initial Check** + - Checks if the transaction is already confirmed + - Avoids unnecessary waiting for already-processed transactions + +2. **Subscription** + - Subscribes to Tenderdash events to receive real-time updates + - More efficient than polling for transaction status + +3. **Timeout Management** + - Uses configurable timeouts based on network conditions + - Provides meaningful errors when timeouts occur + +4. **Error Classification** + - Classifies transaction errors into categories: + - Validation errors (transaction rejected) + - System errors (node unavailable) + - Timeout errors (transaction not confirmed in time) + +This comprehensive approach ensures reliable tracking of state transition processing and provides clients with clear information about the outcome. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/streams/subscribeToBlockHeadersWithChainLocks.md b/packages/dapi/doc/endpoints/streams/subscribeToBlockHeadersWithChainLocks.md new file mode 100644 index 00000000000..6985a6c678e --- /dev/null +++ b/packages/dapi/doc/endpoints/streams/subscribeToBlockHeadersWithChainLocks.md @@ -0,0 +1,104 @@ +# subscribeToBlockHeadersWithChainLocks + +## Client API + +Streams block headers and chain locks. + +**Request Parameters**: +- `fromBlockHash` or `fromBlockHeight`: Starting point (optional) +- `count`: Number of blocks to fetch (0 means subscribe to new blocks) + +**Response Parameters**: +- Stream of block headers and chain locks + - `rawBlockHeader`: Serialized block header + - `rawChainLock`: Serialized chain lock + +**Example Usage**: +```javascript +const stream = dapiClient.core.subscribeToBlockHeadersWithChainLocks({ fromBlockHeight: 1000, count: 10 }); + +stream.on('data', (response) => { + if (response.rawBlockHeader) { + console.log('Received block header'); + } else if (response.rawChainLock) { + console.log('Received chain lock'); + } +}); +``` + +## Internal Implementation + +The `subscribeToBlockHeadersWithChainLocks` endpoint is implemented in the `subscribeToBlockHeadersWithChainLocksHandlerFactory.js` file. + +### Implementation Details + +1. **Dual Operation Modes** + - **Historical Mode**: Retrieves a specific count of block headers from a starting point + - **Streaming Mode**: Provides real-time updates when new blocks are created + - **Combined Mode**: Historical headers followed by real-time streaming + +2. **Historical Data Retrieval** + - Uses an iterator pattern for efficient header retrieval + - Supports two ways to specify the starting point: + - `fromBlockHash`: Start from a specific block hash + - `fromBlockHeight`: Start from a specific block height + - Fetches headers in batches for better performance + - Includes associated chain locks when available + +3. **Real-time Streaming** + - Uses a `ProcessMediator` for event-based communication + - Subscribes to ZMQ events from Dash Core + - Emits block headers and chain locks as they are received + - Implements proper cleanup on client disconnection + +4. **Flow Control** + - Implements back-pressure handling + - Uses acknowledgment for stream responses + - Prevents overwhelming clients with data + +5. **Dependencies** + - BlockHeadersCache for efficient access to historical headers + - ZMQ client for real-time notifications + - ProcessMediator for event management + +### Code Flow + +``` +Client Request + → gRPC Server + → subscribeToBlockHeadersWithChainLocksHandler + → Validate Parameters + → If Historical Data Requested (count > 0): + → Create Historical Headers Iterator + → Stream Headers Until Count Reached + → If Streaming Requested (count = 0 or all historical sent): + → Subscribe to ZMQ Events + → On New Block: + → Format Block Header + → Send to Client + → On New ChainLock: + → Format ChainLock + → Send to Client + → On Client Disconnect: + → Clean Up Subscriptions +``` + +### Stream Lifecycle Management + +The handler implements careful resource management: + +1. **Initialization** + - Sets up event listeners and iterators + - Prepares caches for efficient data retrieval + +2. **Active Streaming** + - Monitors Core node for new blocks and chain locks + - Transforms raw data to client-friendly format + - Sends data through the gRPC stream + +3. **Cleanup** + - Detects client disconnection (explicit or timeout) + - Removes event listeners and subscriptions + - Releases resources to prevent memory leaks + +This lifecycle management ensures efficient operation even with long-lived streaming connections. \ No newline at end of file diff --git a/packages/dapi/doc/endpoints/streams/subscribeToTransactionsWithProofs.md b/packages/dapi/doc/endpoints/streams/subscribeToTransactionsWithProofs.md new file mode 100644 index 00000000000..77ec249b740 --- /dev/null +++ b/packages/dapi/doc/endpoints/streams/subscribeToTransactionsWithProofs.md @@ -0,0 +1,127 @@ +# subscribeToTransactionsWithProofs + +## Client API + +Streams transactions matching a bloom filter with merkle proofs. + +**Request Parameters**: +- `bloomFilter`: Parameters for bloom filter (object, required) + - `vData`: Filter data + - `nHashFuncs`: Number of hash functions + - `nTweak`: Random value + - `nFlags`: Bloom filter update flags +- `fromBlockHash` or `fromBlockHeight`: Starting point (optional) +- `count`: Number of blocks to fetch (0 means subscribe to new transactions) + +**Response Parameters**: +- Stream of: + - `rawTransaction`: Serialized transaction + - `rawMerkleBlock`: Serialized merkle block (proof) + - `instantSendLockMessages`: Instant send lock data + +**Example Usage**: +```javascript +const bloomFilter = { + vData: '...', + nHashFuncs: 11, + nTweak: 0, + nFlags: 0 +}; + +const stream = dapiClient.core.subscribeToTransactionsWithProofs(bloomFilter); + +stream.on('data', (response) => { + if (response.rawMerkleBlock) { + console.log('Received merkle block'); + } else if (response.rawTransaction) { + console.log('Received transaction'); + } else if (response.instantSendLockMessages) { + console.log('Received instant send lock'); + } +}); +``` + +## Internal Implementation + +The `subscribeToTransactionsWithProofs` endpoint is implemented in the `subscribeToTransactionsWithProofsHandlerFactory.js` file. + +### Implementation Details + +1. **Bloom Filtering** + - Uses Bloom filters to efficiently match transactions of interest + - Applies filter to both historical and new transactions + - Supports standard Bloom filter flags for filter updates + +2. **Operation Modes** + - **Historical Mode**: Retrieves transactions from past blocks + - **Streaming Mode**: Provides real-time transaction updates + - **Combined Mode**: Historical data followed by real-time streaming + +3. **Historical Data Processing** + - Creates an iterator to efficiently process historical blocks + - For each block, filters transactions using the provided Bloom filter + - Sends matching transactions along with Merkle proofs + - Sends associated InstantLock messages when available + +4. **Real-time Streaming** + - Uses a `ProcessMediator` for event-driven architecture + - Subscribes to Core ZMQ events for new transactions and blocks + - Tests each transaction against the filter before sending + - Includes Merkle proofs for transaction inclusion verification + +5. **Mempool Handling** + - Processes mempool transactions to catch recent unconfirmed transactions + - Applies rate limiting to reduce load on Core + - Sends mempool transactions that match the filter + +6. **Dependencies** + - ZMQ client for real-time notifications + - Bloom filter implementation for transaction filtering + - ProcessMediator for event management + - Block cache for efficient block retrieval + +### Code Flow + +``` +Client Request + → gRPC Server + → subscribeToTransactionsWithProofsHandler + → Validate Bloom Filter Parameters + → Create BloomFilter Instance + → If Historical Data Requested (count > 0): + → Process Mempool Transactions + → Create Historical Transactions Iterator + → For Each Block: + → Filter Transactions Using Bloom Filter + → Send Matching Transactions + → Send Merkle Block (Proof) + → Send Associated InstantLocks + → If Streaming Requested (count = 0 or all historical sent): + → Subscribe to ZMQ Events + → On New Block: + → Filter Transactions + → Send Matching Transactions with Proofs + → On New Transaction: + → Test Against Filter + → If Match: Send Transaction + → On Client Disconnect: + → Clean Up Resources +``` + +### Response Types + +The endpoint emits three types of responses: + +1. **Raw Transactions** + - Serialized transaction data for transactions matching the filter + - Includes transaction metadata + +2. **Merkle Blocks** + - Partial block data that proves transaction inclusion + - Contains Merkle path to verify transactions without downloading the entire block + +3. **InstantSend Locks** + - Provides instant transaction finality information + - Allows clients to know when a transaction is secured by InstantSend + +These responses collectively enable lightweight clients to validate transactions without downloading the full blockchain. \ No newline at end of file diff --git a/packages/dapi/doc/index.md b/packages/dapi/doc/index.md new file mode 100644 index 00000000000..7f299ea38b5 --- /dev/null +++ b/packages/dapi/doc/index.md @@ -0,0 +1,73 @@ +# DAPI Documentation + +This guide provides comprehensive information about DAPI, its architecture, configuration, and available endpoints. + +## What is DAPI? + +Historically, nodes in most cryptocurrency networks communicated with each other, and the outside world, according to a peer-to-peer (P2P) protocol. +The use of P2P protocols presented some downsides for developers, namely, network resources were difficult to access without specialized knowledge or trusted third-party services. + +To overcome these obstacles, the Dash decentralized API (DAPI) uses Dash's robust masternode infrastructure to provide an API for accessing the network. +DAPI supports both layer 1 (Core blockchain) and layer 2 (Dash Platform) functionality so all developers can interact with Dash via a single interface. + +DAPI offers several advantages over traditional centralized APIs: + +- **No single point of failure** - Running on the masternode network ensures high availability +- **Censorship resistance** - No central authority can block access +- **Built-in scalability** - As the masternode network grows, API capacity grows +- **Multiple interfaces** - Supports both modern gRPC and legacy JSON-RPC + +## DAPI Architecture + +DAPI consists of two main processes: + +1. **API Process** - Handles standard gRPC and JSON-RPC endpoints: + - Core blockchain endpoints + - Platform (Evolution) endpoints + - Legacy JSON-RPC endpoints + +2. **Core Streams Process** - Handles streaming data endpoints: + - Block headers streaming + - Transaction filtering and streaming + - Masternode list updates + +Each process connects independently to the underlying Dash infrastructure (Core, Drive, and Tenderdash) to provide its functionality. + +Learn more about DAPI's architecture in the [Architecture](./architecture.md) section. + +## Endpoints + +### Overview +- [Endpoints Overview](./endpoints/index.md) - Index of all available API endpoints + +### Core Endpoints +- [getBestBlockHeight](./endpoints/core/getBestBlockHeight.md) +- [getBlockchainStatus](./endpoints/core/getBlockchainStatus.md) +- [getTransaction](./endpoints/core/getTransaction.md) +- [broadcastTransaction](./endpoints/core/broadcastTransaction.md) +- [subscribeToMasternodeList](./endpoints/core/subscribeToMasternodeList.md) + +### Platform Endpoints +- [broadcastStateTransition](./endpoints/platform/broadcastStateTransition.md) +- [waitForStateTransitionResult](./endpoints/platform/waitForStateTransitionResult.md) +- [getConsensusParams](./endpoints/platform/getConsensusParams.md) +- [getStatus](./endpoints/platform/getStatus.md) + +### Stream Endpoints +- [subscribeToBlockHeadersWithChainLocks](./endpoints/streams/subscribeToBlockHeadersWithChainLocks.md) +- [subscribeToTransactionsWithProofs](./endpoints/streams/subscribeToTransactionsWithProofs.md) + +### JSON-RPC Endpoints +- [getBestBlockHash](./endpoints/json-rpc/getBestBlockHash.md) +- [getBlockHash](./endpoints/json-rpc/getBlockHash.md) + +## Client Libraries + +Rather than directly interacting with DAPI's gRPC or JSON-RPC interfaces, most developers should use one of the official client libraries: + +- [Dash SDK (JavaScript)](https://docs.dash.org/projects/platform/en/stable/docs/sdk-js/overview.html) +- [Dash SDK (Rust)](https://docs.dash.org/projects/platform/en/stable/docs/sdk-rs/overview.html) +- [DAPI Client (JavaScript)](https://docs.dash.org/projects/platform/en/stable/docs/dapi-client-js/overview.html) +- [gRPC Clients](https://github.com/dashpay/platform/tree/master/packages/dapi-grpc) (for other languages) + +These libraries handle the complexity of interacting with DAPI and provide idiomatic interfaces in their respective languages. diff --git a/packages/dapi/doc/swaggerDef.js b/packages/dapi/doc/swaggerDef.js deleted file mode 100644 index 7f1bee9b3f1..00000000000 --- a/packages/dapi/doc/swaggerDef.js +++ /dev/null @@ -1,75 +0,0 @@ -/** -* This file is used by swagger-jsdoc as the root document object of the -* OpenAPI document (https://swagger.io/specification/#oasObject). -* -* The file is only used as input to the swagger-jsdoc CLI application when -* generating the OAS API documentation (`swagger-jdsoc -d ...`). -*/ - -module.exports = { - openapi: '3.0.0', - 'x-api-id': 'dapi', - info: { - title: 'DAPI', - version: '0.2.2', - description: 'Dash Decentralized API (DAPI)', - }, - servers: [ - { - url: '{url}:{port}', - description: 'User-defined network', - variables: { - url: { - default: 'http://dapi.dash.org', - }, - port: { - default: '3000', - }, - }, - }, - ], - paths: {}, - /** Readme.io swagger extensions - * ------------------------------ - * - * x-send-defaults (default: false) - * - Whether to send the defaults specified in your swagger file, or render - * them as placeholders - */ - 'x-send-defaults': true, - /** - * x-headers (default: undefined) - * - Array of static headers to add to each request. Must be provided as an - * array of JSON objects with `key` and `value` properties. - */ - 'x-headers': [], - /** - * x-explorer-enabled (default: true) - * - Enable the API explorer - */ - 'x-explorer-enabled': true, - /** - * x-proxy-enabled (default: true) - * - Whether the Readme CORs proxy is enabled or not. If your API correctly - * returns CORs headers, you can safely turn this off. - */ - 'x-proxy-enabled': true, - /** - * x-samples-enabled (default: true) - * - Enable code examples - */ - 'x-samples-enabled': true, - /** - * x-samples-language - * - Languages to generate code samples for - * Default: ['curl', 'node', 'ruby', 'javascript', 'python'] - * Supported: node, curl, ruby, javascript, objectivec, python, java, php, csharp, swift, go - */ - 'x-samples-languages': [ - 'curl', - 'node', - 'ruby', - 'javascript', - 'python', - ], -};