WebSocket link for Blockfrost.io API.
About • Installation • Usage • UI Explorer • Documentation
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.
yarn dev
yarn start
The Nix files are automatically regenerated by yarn
using the yarn-plugin-nixify
. You can
build the server by running:
$ nix-build
In order to start the server, you need to configure some environment variables.
BLOCKFROST_NETWORK
: lets you choose which network it should connect to (mainnet or testnet)BLOCKFROST_PROJECT_ID
: Blockfrost.io's project token
BLOCKFROST_BACKEND_URL
: URL pointing to your own backend (blockfrost-backend-ryo
) if you prefer not to use the public Blockfrost REST APIBLOCKFROST_BLOCK_LISTEN_INTERVAL
: how often should be the server pulling the backend for new data (in milliseconds, default5000
)BLOCKFROST_FIAT_RATES_PROXY
: the proxy used to fetch fiat ratesBLOCKFROST_SENTRY_DSN
: the Sentry data source name to optionally monitor the serviceBLOCKFROST_WSLINK_DEBUG
: enablesdebug
logging levelBUILD_COMMIT
: provided by/status
endpointMETRICS_COLLECTOR_INTERVAL_MS
: frequency for refreshing metrics and performing health check (default10000
)PORT
: which port the server should listen to (default3005
)
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}}
...
There is an example UI for this project called blockfrost-websocket-link-ui and you can find its hosted version at websocket-link.blockfrost.dev.
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_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:
{
id: number | string; // Unique identifier for tracking responses
"command": string; // Command
"params": { // Parameters object based on the command
...
}
}
General structure of a success response:
{
id: number | string; // Unique identifier for tracking responses
"type": "message"
data: { // payload
...
}
}
Structure of an error response:
{
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;
}
},
}
For each of these commands the client receives an immediate response
ESTIMATE_FEE
- estimate transaction submission feeGET_ACCOUNT_INFO
- get general information about an accountGET_ACCOUNT_UTXO
- get unspent UTxOs of an accountGET_ADA_HANDLE
- resolves an Ada HandleGET_BALANCE_HISTORY
- get balance history of an accountGET_BLOCK
- get details of a blockGET_TRANSACTION
- get details of a transactionGET_SERVER_INFO
- get information about the serverPUSH_TRANSACTION
- submits a transaction to the network
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 to new transactions for given addressesUNSUBSCRIBE_ADDRESS
- cancel all new transactions subscriptionsSUBSCRIBE_BLOCK
- subscribe to new blocksUNSUBSCRIBE_BLOCK
- cancel new blocks subscription
Estimates the minimum fee required for transaction submission based on the linear fee parameters for the current epoch.
Input message:
{
id: number | string; // identifier
"command": "ESTIMATE_FEE"
}
Response:
{
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;
}
}
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:
{
"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
}
}
Response:
{
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;
};
address: string;
txHash: string;
txCbor?: 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;
};
};
}
}
Fetches all unspent transaction outputs (UTXOs) for the specified account.
Input message:
{
"id": number | string;
"command": "GET_ACCOUNT_UTXO";
"params": {
"descriptor": string; // account public key
}
}
Response:
{
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;
};
}[];
}
Calculates a history of balance changes for an account within a specified date range.
Input message:
{
"id": number | string;
"command": "GET_BALANCE_HISTORY";
"params": {
"descriptor": string; // account public key
"groupBy": number;
"from": number;
"to": number;
}
}
Response:
{
id: number | string;
type: "message";
data: {
time: number;
txs: number;
received: string;
sent: string;
sentToSelf: string;
rates?: { [k: string]: number | undefined };
}[]
}
Resolves an Ada Handle providing the address holding it.
Input message:
{
"id": number | string;
"command": "GET_ADA_HANDLE";
"params": {
"name": string; // Ada Handle name
}
}
Response output message data
type:
{
id: number | string;
type: 'message';
data: string | null;
}
Retrieves detailed information about a specific block using its hash or height.
Input message:
{
"id": number | string;
"command": "GET_BLOCK";
"params": {
"hashOrNumber": number | string; // Block hash or block height
}
}
Response: Payload contains block data.
{
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;
}
}
Returns information about a specified transaction.
Input message:
{
"id": number | string;
"command": "GET_TRANSACTION";
"params": {
"txId": string; // transaction id
}
}
Response: Payload contains transaction data.
{
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;
};
}
Fetches general information about the server, such as version, network, and the current block height.
Input message:
{
"id": number | string;
"command": "GET_SERVER_INFO";
}
Response:
{
hostname: string;
name: string;
shortcut: string;
testnet: boolean;
version: string;
decimals: number;
blockHeight: number;
blockHash: string;
}
Example:
{
"id": 1,
"type": "message",
"data": {
"hostname": "wslink-backend1",
"name": "Cardano",
"shortcut": "ada",
"testnet": false,
"version": "2.1.1",
"decimals": 6,
"blockHeight": 11085275,
"blockHash": "e958bfd655844f763e7b6613ffbcf17bde09782bb66efaea67ed49e70261439c"
}
}
Submits a transaction to the network.
Input message:
{
"id": number | string;
"command": "PUSH_TRANSACTION";
"params": {
"txData": string; // CBOR representation of the transaction
}
}
Response output message:
{
"id": number | string;
"type": "message";
"data": string; // transaction id
}
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:
{
"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:
{
"id": number | string;
"type": "message";
data: {
"subscribed": true; // successful subscription confirmation
};
}
Event:
{
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;
};
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;
}[];
};
txCbor?: string;
}[];
}
Subscribes to notifications for each new block added to the blockchain.
Input message:
{
"id": number | string;
"command": "SUBSCRIBE_BLOCK";
}
Confirmation of a subscription status:
{
id: number | string;
"type": "message";
data: {
"subscribed": true; // successful subscription confirmation
};
}
Event message:
{
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;
}
}
Unsubscribes from transaction notifications for addresses.
Input message:
{
"id": number | string;
"command": "UNSUBSCRIBE_ADDRESS"
}
Output message:
{
id: number | string;
data: {
"subscribed": false; // successful un-subscription confirmation
},
"type": "message"
}
Unsubscribes from block event notifications.
Input message:
{
"id": number | string;
"command": "UNSUBSCRIBE_BLOCK"
}
Confirmation of a subscription status:
{
id: number | string;
type: "message";
data: {
"subscribed": false; // successful un-subscription confirmation
};
}