diff --git a/client/README.md b/client/README.md index 47ad72e2..a5fa85f8 100644 --- a/client/README.md +++ b/client/README.md @@ -9,7 +9,7 @@ A JS Client for the Stacks Blockchain API This package provides the ability to: - Execute REST API requests against the Stacks Blockchain API -- Subscribe to WebSockets for real-time Stacks updates (for addresses or transactions) +- Subscribe to WebSockets or Socket.io for real-time Stacks updates (see [Available Updates](#Available-Updates)) - Full type safety for WebSocket and API requests and responses ## Installation @@ -17,37 +17,336 @@ This package provides the ability to: You can install this package using NPM: ```shell -npm install --save-dev @stacks/blockchain-api-client +npm install --save @stacks/blockchain-api-client ``` ## Usage -Here is an example code that connects with the WebSocket server and subscribes to updates for a specific Stacks address: +Here is example code that subscribes to updates for a specific Stacks address: + +### Websockets ```js import { connectWebSocketClient } from '@stacks/blockchain-api-client'; -// for mainnet, replace with ws://stacks-node-api.testnet.stacks.co/ +// for testnet, replace with wss://stacks-node-api.testnet.stacks.co/ const client = await connectWebSocketClient('wss://stacks-node-api.mainnet.stacks.co/'); const sub = await client.subscribeAddressTransactions('ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA', event => console.log(event); - /* - { - address: 'ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA', - tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', - tx_status: 'success', - tx_type: 'token_transfer', - } - */ ); await sub.unsubscribe(); ``` -## Documentation +### Socket.io -You can find full references [here](https://hirosystems.github.io/stacks-blockchain-api/client/index.html). +```js +import { io } from "socket.io-client"; +import * as stacks from '@stacks/blockchain-api-client'; + +// for testnet, replace with https://stacks-node-api.testnet.stacks.co/ +const socketUrl = "https://stacks-node-api.mainnet.stacks.co/"; + +const socket = io(socketUrl, { + transports: [ "websocket" ] +}); +const sc = new stacks.StacksApiSocketClient(socket); + +sc.subscribeAddressTransactions('ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA'); +``` + +## Available Updates + +### Block Updates + +Sent every time a new Stacks block is mined. + +Example message: +```json +{ + "canonical": true, + "height": 3275, + "hash": "0xe77ba8cf6bb7c0e4f64adc83356289ed467d31a22354907b4bb814590058430f", + "parent_block_hash": "0x75ab21ef25cbff2caa14c27d830ed7886a4d1522e1b6f9e5dc3b59ccf73ed49f", + "burn_block_time": 1594233639, + "burn_block_time_iso": "2020-08-27T16:41:26.000Z", + "burn_block_hash": "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2", + "burn_block_height": 654439, + "miner_txid": "0xd7d56070277ccd87b42acf0c91f915dd181f9db4cf878a4e95518bc397c240cc", + "parent_microblock_hash": "0x590a1bb1d7bcbeafce0a9fc8f8a69e369486192d14687fe95fbe4dc1c71d49df", + "parent_microblock_sequence": 2, + "txs": [ + "0x4262db117659d1ca9406970c8f44ffd3d8f11f8e18c591d2e3960f4070107754", + "0x383632cd3b5464dffb684082750fcfaddd1f52625bbb9f884ed8f45d2b1f0547", + "0xc99fe597e44b8bd15a50eec660c6e679a7144a5a8553d214b9d5f1406d278c22" + ], + "microblocks_accepted": [ + "0xce0b1a4099d3fc7d5885cc7a3baa952b6d999f9709d0683b98b843597208231c", + "0x4c0529b6448a5885991c5021bd869cc97f1692c128a98b382729dc962203c326", + "0x64968846291dfea1015228a9d4bbd60aac81378cd6774b810b08e59e6b0e7494" + ], + "microblocks_streamed": [ + "0xb5650ef855f7d90fc146942e85cf9fac3a8c47ec408aca02f3cf9ed7c82f6cc6", + "0xeeb9aa5741d84aa0bc5de4f2fbdeae57ae29694479475d45a67ae7bd7e2c98f3", + "0x4f4c368d5f06fdf6065c5bafd9cb37391fddc9c279cfc57be35e4bf8ee932cbd", + "0xde2fc8d99872c827f144c752c002d29f9315dfc09472a09572ac7447ae623dea" + ], + "execution_cost_read_count": 2477, + "execution_cost_read_length": 1659409, + "execution_cost_runtime": 2520952000, + "execution_cost_write_count": 608, + "execution_cost_write_length": 80170 +} +``` + +### Microblock Updates + +Sent every time a new Stacks microblock is streamed. + +Example message: +```json +{ + "canonical": true, + "microblock_canonical": true, + "microblock_hash": "0xa31ee2244ceee0d042c0b129a91df2433c4ffd3b94e7e4e5dfa3a15927684a6f", + "microblock_sequence": 0, + "microblock_parent_hash": "0x5d053c206a7bcc5dcfe8bb8a61d8699fc068179f388eb2aec62786b7318c36c4", + "block_height": 38224, + "parent_block_height": 38223, + "parent_block_hash": "0x5d053c206a7bcc5dcfe8bb8a61d8699fc068179f388eb2aec62786b7318c36c4", + "block_hash": "", + "txs": [ + "0xe4b46358b7864c9db31e15e7db4f74042a2e1748db920b93480ed56463ac1c48", + "0x1de11ca776fc4a713465bc5974790cd3cdab7d8ad89fa474c10a4160cf89efdc", + "0x16b3a99d6d100562964f6f0f0ae02d47121386495c4fd903e4e9f72548ae0b35", + "0xc99f802dfffee9190e4b8ee5c128295f4eec51974d7cabdec0ba49c35b17bca5", + "0xeffa0b1d1e5b96dc1de1ff49b390752f35cbe49eddf5a6c7ff1ee80ea2b73886", + "0x93f927bdf15056f65ff3b0c6041287c9cfd070e4bddadedeb1aa1627d837022a", + "0xdbd62060daf483a7fdac2d76c3a88091690ff1f26827e2627c0894e5f73dcf0a", + "0x0d89a6edb51f96eec1dfbbaf1abc66861c96c75a6962545c0783d78773563a4b" + ], + "parent_burn_block_height": 710158, + "parent_burn_block_hash": "0x00000000000000000007b6fa2dcd91e0c69d488f9742d7e5261286aefce29ee0", + "parent_burn_block_time": 1637167098, + "parent_burn_block_time_iso": "2021-11-17T16:38:18.000Z" +} +``` + +### Mempool Updates + +Sent every time a new transaction is submitted to the mempool. Transactions of different types and structures may be received. + +Example message: +```json +{ + "tx_id": "0x698096b646d17297836542beecfe8d6a30454b2ce5ce4e9b0e5d243b05dce998", + "nonce": 66, + "fee_rate": "554000", + "sender_address": "SPBDCE0KCWY56SX6XE7MB6DVVETABYM2WRDK6PCB", + "sponsored": false, + "post_condition_mode": "allow", + "post_conditions": [], + "anchor_mode": "any", + "tx_status": "pending", + "receipt_time": 1637172201, + "receipt_time_iso": "2021-11-17T18:03:21.000Z", + "tx_type": "contract_call", + "contract_call": { + "contract_id": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1", + "function_name": "swap-x-for-y", + "function_signature": "", + "function_args": [ + { + "hex": "0x0616982f3ec112a5f5928a5c96a914bd733793b896a50e61726b6164696b6f2d746f6b656e", + "repr": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-token", + "name": "token-x-trait", + "type": "trait_reference" + }, + { + "hex": "0x0616982f3ec112a5f5928a5c96a914bd733793b896a50a757364612d746f6b656e", + "repr": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.usda-token", + "name": "token-y-trait", + "type": "trait_reference" + }, + { + "hex": "0x010000000000000000000000003b023380", + "repr": "u990000000", + "name": "dx", + "type": "uint" + }, + { + "hex": "0x0100000000000000000000000062ea4a9f", + "repr": "u1659521695", + "name": "min-dy", + "type": "uint" + } + ] + } +} +``` + +### Transaction Updates + +Sent every time a single transaction (subscribed by transaction ID) is updated. Transactions of different types and structures may be received. + +Example message if subscribed to updates for a transaction with ID `0xd78988664aaa9a1b751cd58c55b253914f790e95ca6f3d402a866559e1cbe0b3` after it was submitted to the mempool: +```json +{ + "tx_id": "0xd78988664aaa9a1b751cd58c55b253914f790e95ca6f3d402a866559e1cbe0b3", + "nonce": 18, + "fee_rate": "74400", + "sender_address": "SP36ADRBVM8J00ZWR5QXC8V65WTJNCD1BF4EJ93ZZ", + "sponsored": false, + "post_condition_mode": "deny", + "post_conditions": [ + { + "type": "stx", + "condition_code": "sent_less_than_or_equal_to", + "amount": "50000000", + "principal": { + "type_id": "principal_standard", + "address": "SP36ADRBVM8J00ZWR5QXC8V65WTJNCD1BF4EJ93ZZ" + } + } + ], + "anchor_mode": "any", + "is_unanchored": false, + "block_hash": "0x4f957ac52af57196eea8ae6ca9e848fc7772da72365d9ed4d3452afddc7a3cf2", + "parent_block_hash": "0x4b7ea97418fd44fbc4af278424fbde67fbfb253398628f78319671d1eab48a47", + "block_height": 38231, + "burn_block_time": 1637173532, + "burn_block_time_iso": "2021-11-17T18:25:32.000Z", + "parent_burn_block_time": 1637173325, + "parent_burn_block_time_iso": "2021-11-17T18:22:05.000Z", + "canonical": true, + "tx_index": 27, + "tx_status": "success", + "tx_result": { + "hex": "0x070100000000000000000000000000000009", + "repr": "(ok u9)" + }, + "microblock_hash": "", + "microblock_sequence": 2147483647, + "microblock_canonical": true, + "event_count": 4, + "events": [], + "execution_cost_read_count": 13, + "execution_cost_read_length": 4320, + "execution_cost_runtime": 5609000, + "execution_cost_write_count": 5, + "execution_cost_write_length": 21, + "tx_type": "contract_call", + "contract_call": { + "contract_id": "SPZW30K9VG6YCPYV4BX4V1FT0VJ66R1Q01W9DQ1W.nebula", + "function_name": "claim", + "function_signature": "(define-public (claim ))" + } +}, +``` + +### Address Transaction Updates + +Sent every time a transaction is sent or received by a specific Stacks address. Transactions of different types and structures may be received. + +Example message if subscribed to updates for an address `SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q`: +```json +{ + "tx_id": "0x1f9e737dfbebcb57f0879a44518c1cc909be0ceb8ab0bc9b38ce63e3b6847917", + "nonce": 6, + "fee_rate": "277600", + "sender_address": "SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q", + "sponsored": false, + "post_condition_mode": "deny", + "post_conditions": [ + { + "type": "stx", + "condition_code": "sent_less_than_or_equal_to", + "amount": "25000000", + "principal": { + "type_id": "principal_standard", + "address": "SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q" + } + }, + { + "type": "non_fungible", + "condition_code": "not_sent", + "principal": { + "type_id": "principal_contract", + "contract_name": "stacks-skaters", + "address": "SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG" + }, + "asset": { + "contract_name": "stacks-skaters", + "asset_name": "stacks-skaters", + "contract_address": "SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG" + }, + "asset_value": { + "hex": "0x0100000000000000000000000000000000", + "repr": "u0" + } + }, + { + "type": "stx", + "condition_code": "sent_less_than_or_equal_to", + "amount": "20000000", + "principal": { + "type_id": "principal_contract", + "contract_name": "stacks-skaters", + "address": "SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG" + } + } + ], + "anchor_mode": "any", + "tx_status": "pending", + "receipt_time": 1637172946, + "receipt_time_iso": "2021-11-17T18:15:46.000Z", + "tx_type": "contract_call", + "contract_call": { + "contract_id": "SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG.stacks-skaters", + "function_name": "mint", + "function_signature": "" + } +} +``` + +### Address Balance Updates + +Sent every time a specific address sends or receives a transaction that changes its balance. + +Example message: +```json +{ + "balance": "53349741093", + "total_sent": "6432000000", + "total_received": "60358503333", + "total_fees_sent": "576762240", + "total_miner_rewards_received": "0", + "lock_tx_id": "", + "locked": "0", + "lock_height": 0, + "burnchain_lock_height": 0, + "burnchain_unlock_height": 0, + "token_offering_locked": { + "total_locked": "0", + "total_unlocked": "18286444440", + "unlock_schedule": [ + { + "amount": "2285805555", + "block_height": 24837 + }, + { + "amount": "2285805555", + "block_height": 29157 + }, + { + "amount": "2285805555", + "block_height": 33477 + } + ] + } +} +``` ## Known Issues diff --git a/docs/entities/blocks/block.example.json b/docs/entities/blocks/block.example.json index 2ee32ec3..bb7b073a 100644 --- a/docs/entities/blocks/block.example.json +++ b/docs/entities/blocks/block.example.json @@ -25,5 +25,10 @@ "0xeeb9aa5741d84aa0bc5de4f2fbdeae57ae29694479475d45a67ae7bd7e2c98f3", "0x4f4c368d5f06fdf6065c5bafd9cb37391fddc9c279cfc57be35e4bf8ee932cbd", "0xde2fc8d99872c827f144c752c002d29f9315dfc09472a09572ac7447ae623dea" - ] + ], + "execution_cost_read_count": 2477, + "execution_cost_read_length": 1659409, + "execution_cost_runtime": 2520952000, + "execution_cost_write_count": 608, + "execution_cost_write_length": 80170 } diff --git a/docs/entities/microblocks/microblock.example.json b/docs/entities/microblocks/microblock.example.json new file mode 100644 index 00000000..2d15fd52 --- /dev/null +++ b/docs/entities/microblocks/microblock.example.json @@ -0,0 +1,25 @@ +{ + "canonical": true, + "microblock_canonical": true, + "microblock_hash": "0xa31ee2244ceee0d042c0b129a91df2433c4ffd3b94e7e4e5dfa3a15927684a6f", + "microblock_sequence": 0, + "microblock_parent_hash": "0x5d053c206a7bcc5dcfe8bb8a61d8699fc068179f388eb2aec62786b7318c36c4", + "block_height": 38224, + "parent_block_height": 38223, + "parent_block_hash": "0x5d053c206a7bcc5dcfe8bb8a61d8699fc068179f388eb2aec62786b7318c36c4", + "block_hash": "", + "txs": [ + "0xe4b46358b7864c9db31e15e7db4f74042a2e1748db920b93480ed56463ac1c48", + "0x1de11ca776fc4a713465bc5974790cd3cdab7d8ad89fa474c10a4160cf89efdc", + "0x16b3a99d6d100562964f6f0f0ae02d47121386495c4fd903e4e9f72548ae0b35", + "0xc99f802dfffee9190e4b8ee5c128295f4eec51974d7cabdec0ba49c35b17bca5", + "0xeffa0b1d1e5b96dc1de1ff49b390752f35cbe49eddf5a6c7ff1ee80ea2b73886", + "0x93f927bdf15056f65ff3b0c6041287c9cfd070e4bddadedeb1aa1627d837022a", + "0xdbd62060daf483a7fdac2d76c3a88091690ff1f26827e2627c0894e5f73dcf0a", + "0x0d89a6edb51f96eec1dfbbaf1abc66861c96c75a6962545c0783d78773563a4b" + ], + "parent_burn_block_height": 710158, + "parent_burn_block_hash": "0x00000000000000000007b6fa2dcd91e0c69d488f9742d7e5261286aefce29ee0", + "parent_burn_block_time": 1637167098, + "parent_burn_block_time_iso": "2021-11-17T16:38:18.000Z" +}