Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/blockfrost/blockfrost-websocket-link

WebSocket link for Blockfrost.io API.
https://github.com/blockfrost/blockfrost-websocket-link

blockfrost cardano websockets

Last synced: 17 days ago
JSON representation

WebSocket link for Blockfrost.io API.

Awesome Lists containing this project

README

        

[![Made by Five Binaries](https://img.shields.io/badge/made%20by-Five%20Binaries-darkviolet.svg?style=flat-square)](https://fivebinaries.com/)



# blockfrost-websocket-link



WebSocket link for Blockfrost.io API.



About
Installation
Usage
UI Explorer
Documentation

## About

**WebSocket Link** is a _server-side application_ that serves as a WebSocket bridge to the Cardano blockchain using the
**Blockfrost REST API**.
`blockfrost-websocket-link` is designed to be run in your infrastructure. It can connect to the public **Blockfrost
REST API** (using your token) or to your own local `blockfrost-backend-ryo` instance.

## Installation

### Dev

`yarn dev`

### Production

`yarn start`

### Nix

The Nix files are automatically regenerated by `yarn` using the `yarn-plugin-nixify`. You can
build the server by running:

```console
$ nix-build
```

## Usage

In order to start the server, you need to configure some environment variables.

### Required

- `BLOCKFROST_NETWORK`: lets you choose which network it should connect to (_mainnet_ or _testnet_)
- `BLOCKFROST_PROJECT_ID`: **Blockfrost.io**'s project token

### Optional

- `BLOCKFROST_BACKEND_URL`: URL pointing to your own backend (`blockfrost-backend-ryo`) if you prefer not to use the
public **Blockfrost REST API**
- `BLOCKFROST_BLOCK_LISTEN_INTERVAL`: how often should be the server pulling the backend for new data (in milliseconds,
default `5000`)
- `BLOCKFROST_FIAT_RATES_PROXY`: the proxy used to fetch fiat rates
- `BLOCKFROST_REQUEST_CONCURRENCY`: the **Blockfrost.io** HTTP API requests limit (default `500`)
- `BLOCKFROST_SENTRY_DSN`: the **Sentry** data source name to optionally monitor the service
- `BLOCKFROST_WSLINK_DEBUG`: enables `debug` logging level
- `BUILD_COMMIT`: provided by `/status` endpoint
- `METRICS_COLLECTOR_INTERVAL_MS`: frequency for refreshing metrics and performing health check (default `10000`)
- `PORT`: which port the server should listen to (default `3005`)

Once your server has started, you can connect to it.

```
$ wscat -c ws://localhost:3005 -n
Connected (press CTRL+C to quit)
> {"id":0,"command":"GET_SERVER_INFO","params":{}}
< {"id":0,"type":"message","data":{"name":"Cardano","shortcut":"ada","testnet":false,"version":"0.14.0","decimals":6,"blockHeight":6576695,"blockHash":"2f82b09b22c54806cd61d83d814151bf11fdcd3fb46af231a5c3ec8c85bbb5e3"}}
> {"id":1,"command":"GET_BLOCK","params":{"hashOrNumber":"5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb"}}
< {"id":1,"type":"message","data":{"time":1506203091,"height":null,"hash":"5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb","slot":null,"epoch":null,"epoch_slot":null,"slot_leader":"Genesis slot leader","size":0,"tx_count":14505,"output":"31112484745000000","fees":"0","block_vrf":null,"previous_block":null,"next_block":"89d9b5a5b8ddc8d7e5a6795e9774d97faf1efea59b2caf7eaf9f8c5b32059df4","confirmations":6576696}}
> {"id":2,"command":"SUBSCRIBE_BLOCK","params":{}}
< {"id":2,"type":"message","data":{"subscribed":true}}
< {"id":2,"type":"message","data":{"time":1638458991,"height":6576700,"hash":"4f4ebd2246a7c9f61624c6eaf09038d36474ba9be788526637a0d68ccb50ad93","slot":46892700,"epoch":306,"epoch_slot":63900,"slot_leader":"pool12g6gfm5c4q7rzwwxdmh0xdxk07tyvujp6d9tke2m46k7q7cz7p0","size":71037,"tx_count":37,"output":"5608976268607","fees":"10040718","block_vrf":"vrf_vk1tpln5vj8nlgrlxac5t0umc546mqdusvq9y2ldr6k3fjrsjscqhaqtzvcth","previous_block":"469de7723eddc90504769cb9e1ef1252c7d84aa0dcdc728d4e3524db923db651","next_block":null,"confirmations":0}}
< {"id":2,"type":"message","data":{"time":1638459043,"height":6576701,"hash":"edd0d8eec73a043615fdd51b76c929f2231418bafc976ca0531d497ab5581ce4","slot":46892752,"epoch":306,"epoch_slot":63952,"slot_leader":"pool166vvvlk496szmtn4uz6wgcq6djryjk70grpap02yxyspjzkr490","size":68826,"tx_count":42,"output":"2196392602738","fees":"10265229","block_vrf":"vrf_vk1kmvctdxmaqz8tp04tsdgqrk7vfmdutmyq782rd6yvz3zlugqmezq2kf3yf","previous_block":"4f4ebd2246a7c9f61624c6eaf09038d36474ba9be788526637a0d68ccb50ad93","next_block":null,"confirmations":0}}
< {"id":2,"type":"message","data":{"time":1638459047,"height":6576702,"hash":"ad9ff078664cc6b56adac63cad3832d9383157d9eb39c742dc4016f54f39a93e","slot":46892756,"epoch":306,"epoch_slot":63956,"slot_leader":"pool1cc76kmtcpf6vht32ya5ke9er74dnpy4jh5qpy4klqwp87ygdsu6","size":58765,"tx_count":35,"output":"3219104538435","fees":"8369852","block_vrf":"vrf_vk182ttxy4dhxyvmkhxd3zac54f5zwqz7hhnvru8prax2udfcsve8dq8m6h68","previous_block":"edd0d8eec73a043615fdd51b76c929f2231418bafc976ca0531d497ab5581ce4","next_block":null,"confirmations":0}}
...
```

## UI explorer

There is an example UI for this project called [blockfrost-websocket-link-ui](https://github.com/blockfrost/blockfrost-websocket-link-ui)
and you can find its hosted version at [websocket-link.blockfrost.dev](https://websocket-link.blockfrost.dev/).

## API

As its name suggests, `blockfrost-websocket-link` provides a WebSocket-based API: the client needs to connect to it
through a WebSocket. Once the WebSocket connection is correctly established the server is immediately ready to accept
commands. The communication (both ways) is _JSON encoded_: the server expects JSON encoded messages and will respond
using the same encoding.

Each command message requires:

- `id`: an identifier which is mirrored by the server in the output message; This identifier, while unused by the server, is useful for the client to
reconcile output messages to relative input message.
- `command`: Command to execute (`ESTIMATE_FEE` | `GET_ACCOUNT_INFO` | `GET_ACCOUNT_UTXO` | `GET_BALANCE_HISTORY` | `GET_BLOCK` |
`GET_PROTOCOL_PARAMETERS` | `GET_SERVER_INFO` | `GET_TRANSACTION` | `PUSH_TRANSACTION` |
`SUBSCRIBE_ADDRESS` | `SUBSCRIBE_BLOCK` | `UNSUBSCRIBE_ADDRESS` | `UNSUBSCRIBE_BLOCK`).
- `params`: optionally a set of parameters, depending on the command.

**The structure of an input message is:**

```ts
{
id: number | string; // Unique identifier for tracking responses
"command": string; // Command
"params": { // Parameters object based on the command
...
}
}
```

**General structure of a success response:**

```ts
{
id: number | string; // Unique identifier for tracking responses
"type": "message"
data: { // payload
...
}
}
```

**Structure of an error response:**

```ts
{
id: number | string; // identifier
"type": "error"
data: {
"error": {
"message": string;
// These optional properties below are set in case of BlockfrostServerError or BlockfrostClientError
// thrown by blockfrost-js https://github.com/blockfrost/blockfrost-js?tab=readme-ov-file#error-handling
"error"?: string;
"status_code"?: number;
"name"?: number;
"url"?: number;
"body"?: unknown;
}
},
}
```

### Request / response commands

For each of these commands the client receives an immediate response

- [`ESTIMATE_FEE`](#estimate_fee) - estimate transaction submission fee
- [`GET_ACCOUNT_INFO`](#get_account_info) - get general information about an account
- [`GET_ACCOUNT_UTXO`](#get_account_utxo) - get unspent UTxOs of an account
- [`GET_ADA_HANDLE`](#get_ada_handle) - resolves an Ada Handle
- [`GET_BALANCE_HISTORY`](#get_balance_history) - get balance history of an account
- [`GET_BLOCK`](#get_block) - get details of a block
- [`GET_PROTOCOL_PARAMETERS`](#get_protocol_parameters) - get latest epoch protocol parameters
- [`GET_TRANSACTION`](#get_transaction) - get details of a transaction
- [`GET_SERVER_INFO`](#get_server_info) - get information about the server
- [`PUSH_TRANSACTION`](#push_transaction) - submits a transaction to the network

### Subscription commands

Each subscription command immediately responds with a confirmation of the subscription status. Upon successful subscription, the client will receive additional messages whenever the subscribed events occur.

When an unsubscribe command is sent, the client receives an immediate response confirming the unsubscribe status. Once successfully unsubscribed, the client will no longer receive messages for those events.

- [`SUBSCRIBE_ADDRESS`](#subscribe_addresses) - subscribe to new transactions for given addresses
- [`UNSUBSCRIBE_ADDRESS`](#unsubscribe_address) - cancel all new transactions subscriptions
- [`SUBSCRIBE_BLOCK`](#subscribe_block) - subscribe to new blocks
- [`UNSUBSCRIBE_BLOCK`](#unsubscribe_block) - cancel new blocks subscription

### ESTIMATE_FEE

**Note: DEPRECATED** - use `min_fee_a` from [`GET_PROTOCOL_PARAMETERS`](#get_protocol_parameters) instead.

Estimates the minimum fee required for transaction submission based on the linear fee parameters for the current epoch.

Input message:

```ts
{
id: number | string; // identifier
"command": "ESTIMATE_FEE"
}
```

Response:

```TypeScript
{
id: number | string;
type: "message";
data: {
//The linear factor for the minimum fee calculation for given epoch (min_fee_a)
// https://docs.cardano.org/about-cardano/explore-more/parameter-guide/#a-list-of-updatable-protocol-parameters
lovelacePerByte: number;
}
}
```

### GET_ACCOUNT_INFO

Retrieves the account details such as current balance, basic staking information, list of used addresses, paginated list of transactions associated with the account (optional) and more.

Input message:

```ts
{
"id": number | string;
"command": "GET_ACCOUNT_INFO";
"params": {
"descriptor": string; // account public key in hex (eg. 6d17587575a3b4f0f86ebad3977e8f7e4981faa863eccf5c1467065c74fe3435943769446dd290d103fb3d360128e86de4b47faea73ffb0900c94c6a61ef9ea2)
"details": 'basic' | 'tokens' | 'tokenBalances' |'txids' | 'txs';
"page"?: number; // optional, default 1
"pageSize"?: number; // optional, default 20
"cbor"?: boolean; // optional, get CBOR representation of transactions
}
}
```

Response:

```TypeScript
{
id: number | string;
type: "message";
data {
balance: string;
addresses?: {
change: {
address: string;
path: string;
transfers: number;
balance?: string;
sent?: string;
received?: string;
}[];
used: {
address: string;
path: string;
transfers: number;
balance?: string;
sent?: string;
received?: string;
}[];
unused: {
address: string;
path: string;
transfers: number;
balance?: string;
sent?: string;
received?: string;
}[];
};
empty: boolean;
availableBalance: string;
descriptor: string;
tokens?: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
history: {
total: number; // total transactions
unconfirmed: number; // unconfirmed transactions
transactions?: { // List of transactions data, available with details set to "txs"
txUtxos: { // https://docs.blockfrost.io/#tag/cardano--transactions/GET/txs/{hash}/utxos
hash: string;
inputs: {
address: string;
amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
tx_hash: string;
output_index: number;
data_hash: string | null;
collateral: boolean;
}[];
outputs: {
address: string;
amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
output_index: number;
data_hash: string | null;
}[];
};
txData: { // https://docs.blockfrost.io/#tag/cardano--transactions/GET/txs/{hash}
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
cbor?: string;
};
address: string;
txHash: string;
}[];
txids?: string[]; // List of transaction ids, available with details set to "txids"
};
page: {
size: number;
total: number;
index: number;
};
misc: {
staking: {
address: string;
isActive: boolean;
rewards: string;
poolId: string | null;
drep: {
drep_id: string;
hex: string;
amount: string;
active: boolean;
active_epoch: number | null;
has_script: boolean;
} | null;
};
};
}
}
```

### GET_ACCOUNT_UTXO

Fetches all unspent transaction outputs (UTXOs) for the specified account.

Input message:

```ts
{
"id": number | string;
"command": "GET_ACCOUNT_UTXO";
"params": {
"descriptor": string; // account public key
}
}
```

Response:

```TypeScript
{
id: number | string;
type: "message";
data: {
address: string;
utxoData: {
tx_hash: string;
tx_index: number;
output_index: number;
amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
block: string;
data_hash: string | null;
};
path: string;
blockInfo: { // https://docs.blockfrost.io/#tag/cardano--blocks/GET/blocks/{hash_or_number}
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
}[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
};
}[];
}
```

### GET_BALANCE_HISTORY

Calculates a history of balance changes for an account within a specified date range.

Input message:

```ts
{
"id": number | string;
"command": "GET_BALANCE_HISTORY";
"params": {
"descriptor": string; // account public key
"groupBy": number;
"from": number;
"to": number;
}
}
```

Response:

```TypeScript
{
id: number | string;
type: "message";
data: {
time: number;
txs: number;
received: string;
sent: string;
sentToSelf: string;
rates?: { [k: string]: number | undefined };
}[]
}
```

### GET_ADA_HANDLE

Resolves an Ada Handle providing the address holding it.

Input message:

```ts
{
"id": number | string;
"command": "GET_ADA_HANDLE";
"params": {
"name": string; // Ada Handle name
}
}
```

Response output message `data` type:

```ts
{
id: number | string;
type: 'message';
data: string | null;
}
```

### GET_BLOCK

Retrieves detailed information about a specific block using its hash or height.

Input message:

```ts
{
"id": number | string;
"command": "GET_BLOCK";
"params": {
"hashOrNumber": number | string; // Block hash or block height
}
}
```

Response:
Payload contains [block data](https://docs.blockfrost.io/#tag/cardano--blocks/GET/blocks/{hash_or_number}).

```ts
{
id: number | string;
type: 'message';
data: {
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
}
[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
}
}
```

### GET_PROTOCOL_PARAMETERS

Gets the protocol parameters relative to the latest epochs.

Input message:

```ts
{
id: number | string;
"command": "GET_PROTOCOL_PARAMETERS"
}
```

Response:
Payload contains [protocol parameters](https://docs.blockfrost.io/#tag/cardano--epochs/GET/epochs/latest/parameters).

```TypeScript
{
id: number | string;
type: "message";
data: { // https://docs.blockfrost.io/#tag/cardano--epochs/GET/epochs/latest/parameters
epoch: number;
min_fee_a: number;
min_fee_b: number;
max_block_size: number;
max_tx_size: number;
max_block_header_size: number;
key_deposit: string;
pool_deposit: string;
e_max: number;
n_opt: number;
a0: number;
rho: number;
tau: number;
decentralisation_param: number;
extra_entropy: string | null;
protocol_major_ver: number;
protocol_minor_ver: number;
min_utxo: string;
min_pool_cost: string;
nonce: string;
cost_models: { [key: string]: unknown } | null;
cost_models_raw?: { [key: string]: unknown } | null;
price_mem: number | null;
price_step: number | null;
max_tx_ex_mem: string | null;
max_tx_ex_steps: string | null;
max_block_ex_mem: string | null;
max_block_ex_steps: string | null;
max_val_size: string | null;
collateral_percent: number | null;
max_collateral_inputs: number | null;
coins_per_utxo_size: string | null;
coins_per_utxo_word: string | null;
pvt_motion_no_confidence: number | null;
pvt_committee_normal: number | null;
pvt_committee_no_confidence: number | null;
pvt_hard_fork_initiation: number | null;
dvt_motion_no_confidence: number | null;
dvt_committee_normal: number | null;
dvt_committee_no_confidence: number | null;
dvt_update_to_constitution: number | null;
dvt_hard_fork_initiation: number | null;
dvt_p_p_network_group: number | null;
dvt_p_p_economic_group: number | null;
dvt_p_p_technical_group: number | null;
dvt_p_p_gov_group: number | null;
dvt_treasury_withdrawal: number | null;
committee_min_size: string | null;
committee_max_term_length: string | null;
gov_action_lifetime: string | null;
gov_action_deposit: string | null;
drep_deposit: string | null;
drep_activity: string | null;
pvtpp_security_group: number | null;
pvt_p_p_security_group: number | null;
min_fee_ref_script_cost_per_byte: number | null;
}
}
```

### GET_TRANSACTION

Returns information about a specified transaction, optionally with CBOR representation.

Input message:

```ts
{
"id": number | string;
"command": "GET_TRANSACTION";
"params": {
"txId": string; // transaction id
"cbor":? boolean;
}
}
```

Response:
Payload contains [transaction data](https://docs.blockfrost.io/#tag/cardano--transactions/GET/txs/{hash}).

```TypeScript
{
id: number | string;
type: "message";
data: { // https://docs.blockfrost.io/#tag/cardano--transactions/GET/txs/{hash}
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
cbor?: string;
};
}
```

### GET_SERVER_INFO

Fetches general information about the server, such as version, network, and the current block height.

Input message:

```ts
{
"id": number | string;
"command": "GET_SERVER_INFO";
}
```

Response:

```TypeScript
{
hostname: string;
name: string;
shortcut: string;
testnet: boolean;
version: string;
decimals: number;
blockHeight: number;
blockHash: string;
}
```

Example:

```json
{
"id": 1,
"type": "message",
"data": {
"hostname": "wslink-backend1",
"name": "Cardano",
"shortcut": "ada",
"testnet": false,
"version": "2.1.1",
"decimals": 6,
"blockHeight": 11085275,
"blockHash": "e958bfd655844f763e7b6613ffbcf17bde09782bb66efaea67ed49e70261439c"
}
}
```

### PUSH_TRANSACTION

Submits a transaction to the network.

Input message:

```ts
{
"id": number | string;
"command": "PUSH_TRANSACTION";
"params": {
"txData": string; // CBOR representation of the transaction
}
}
```

Response output message:

```ts
{
"id": number | string;
"type": "message";
"data": string; // transaction id
}
```

### SUBSCRIBE_ADDRESS

Subscribes to transaction notifications for a specified list of addresses. The event consist of detailed information about a specified transaction, including inputs, outputs and transaction CBOR.

Input message:

```ts
{
"id": number | string;
"command": "SUBSCRIBE_ADDRESS",
"params": {
"addresses": string[], // list of bech32 addresses
"cbor": true // optional - whether to include transaction CBOR
}
}
```

Confirmation of a subscription status:

```ts
{
"id": number | string;
"type": "message";
data: {
"subscribed": true; // successful subscription confirmation
};
}
```

Event:

```ts
{
id: number | string;
type: "message";
data: {
address: string;
txHash: string;
txData: { // https://docs.blockfrost.io/#tag/cardano--transactions/GET/txs/{hash}
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
decimals: number;
name?: string | null;
ticker?: string | null;
fingerprint?: string;
}[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
cbor?: string;
};
txUtxos: {
hash: string;
inputs: {
address: string;
amount: {
unit: string;
quantity: string;
fingerprint?: string; // lovelace has no fingerprint
decimals: number;
ticker?: string | null;
name?: string | null;
}[];
tx_hash: string;
output_index: number;
data_hash: string | null;
collateral: boolean;
}[];
outputs: {
address: string;
amount: {
unit: string;
quantity: string;
fingerprint?: string; // lovelace has no fingerprint
decimals: number;
ticker?: string | null;
name?: string | null;
}[];
output_index: number;
data_hash: string | null;
}[];
};
}[];
}
```

### SUBSCRIBE_BLOCK

Subscribes to notifications for each new block added to the blockchain.

Input message:

```ts
{
"id": number | string;
"command": "SUBSCRIBE_BLOCK";
}
```

Confirmation of a subscription status:

```ts
{
id: number | string;
"type": "message";
data: {
"subscribed": true; // successful subscription confirmation
};
}
```

Event message:

```ts
{
id: number | string;
type: 'message';
data: {
// https://docs.blockfrost.io/#tag/cardano--blocks/GET/blocks/latest
hash: string;
block: string;
block_height: number;
block_time: number;
slot: number;
index: number;
output_amount: {
unit: string;
quantity: string;
}
[];
fees: string;
deposit: string;
size: number;
invalid_before: string | null;
invalid_hereafter: string | null;
utxo_count: number;
withdrawal_count: number;
mir_cert_count: number;
delegation_count: number;
stake_cert_count: number;
pool_update_count: number;
pool_retire_count: number;
asset_mint_or_burn_count: number;
redeemer_count: number;
valid_contract: boolean;
}
}
```

### UNSUBSCRIBE_ADDRESS

Unsubscribes from transaction notifications for addresses.

Input message:

```ts
{
"id": number | string;
"command": "UNSUBSCRIBE_ADDRESS"
}
```

Output message:

```ts
{
id: number | string;
data: {
"subscribed": false; // successful un-subscription confirmation
},
"type": "message"
}
```

### UNSUBSCRIBE_BLOCK

Unsubscribes from block event notifications.

Input message:

```ts
{
"id": number | string;
"command": "UNSUBSCRIBE_BLOCK"
}
```

Confirmation of a subscription status:

```ts
{
id: number | string;
type: "message";
data: {
"subscribed": false; // successful un-subscription confirmation
};
}
```