@stacks/blockchain-api-client
Version:
Client for the Stacks Blockchain API
158 lines • 6.19 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.StacksApiSocketClient = void 0;
const socket_io_client_1 = require("socket.io-client");
const common_1 = require("../common");
function getWsUrl(url) {
let urlObj;
try {
urlObj = new URL(url);
if (!urlObj.protocol || !urlObj.host) {
throw new TypeError(`[ERR_INVALID_URL]: Invalid URL: ${url}`);
}
}
catch (error) {
console.error(`Pass an absolute URL with a protocol/schema, e.g. "wss://example.com"`);
throw error;
}
return urlObj;
}
function createStacksApiSocket(opts) {
const socketOpts = {
...opts?.socketOpts,
query: {
...opts?.socketOpts?.query,
// Subscriptions can be specified on init using this handshake query param.
subscriptions: Array.from(new Set(opts?.subscriptions)).join(','),
},
};
if (!socketOpts.transports) {
socketOpts.transports = ['websocket'];
}
const socket = (0, socket_io_client_1.io)(getWsUrl(opts?.url ?? common_1.BASE_PATH).href, socketOpts);
return socket;
}
class StacksApiSocketClient {
constructor(args) {
if (args instanceof socket_io_client_1.Socket) {
this.socket = args;
}
else {
this.socket = createStacksApiSocket(args);
}
}
static connect(opts) {
return new StacksApiSocketClient(opts);
}
handleSubscription(topic, subscribe = false, listener) {
const subsQuery = this.socket.io.opts.query?.subscriptions;
const subscriptions = new Set(subsQuery ? subsQuery.split(',') : []);
if (subscribe) {
this.socket.emit('subscribe', topic, error => {
if (error)
console.error(`Error subscribing: ${error}`);
});
subscriptions.add(topic);
}
else {
this.socket.emit('unsubscribe', topic);
subscriptions.delete(topic);
}
// Update the subscriptions in the socket handshake so topics are persisted on re-connect.
if (this.socket.io.opts.query === undefined) {
this.socket.io.opts.query = {};
}
this.socket.io.opts.query.subscriptions = Array.from(subscriptions).join(',');
return {
unsubscribe: () => {
if (listener) {
this.socket.off(topic, listener);
}
this.handleSubscription(topic, false);
},
};
}
subscribeBlocks(listener) {
if (listener)
this.socket.on('block', listener);
return this.handleSubscription('block', true, listener);
}
unsubscribeBlocks() {
this.handleSubscription('block', false);
}
subscribeMicroblocks(listener) {
if (listener)
this.socket.on('microblock', listener);
return this.handleSubscription('microblock', true, listener);
}
unsubscribeMicroblocks() {
this.handleSubscription('microblock', false);
}
subscribeMempool(listener) {
if (listener)
this.socket.on('mempool', listener);
return this.handleSubscription('mempool', true, listener);
}
unsubscribeMempool() {
this.handleSubscription('mempool', false);
}
subscribeAddressTransactions(address, listener) {
if (listener)
this.socket.on(`address-transaction:${address}`, listener);
return this.handleSubscription(`address-transaction:${address}`, true, listener);
}
unsubscribeAddressTransactions(address) {
this.handleSubscription(`address-transaction:${address}`, false);
}
subscribeAddressStxBalance(address, listener) {
if (listener)
this.socket.on(`address-stx-balance:${address}`, listener);
return this.handleSubscription(`address-stx-balance:${address}`, true, listener);
}
unsubscribeAddressStxBalance(address) {
this.handleSubscription(`address-stx-balance:${address}`, false);
}
subscribeTransaction(txId, listener) {
if (listener)
this.socket.on(`transaction:${txId}`, listener);
return this.handleSubscription(`transaction:${txId}`, true, listener);
}
unsubscribeTransaction(txId) {
this.handleSubscription(`transaction:${txId}`, false);
}
subscribeNftEvent(listener) {
if (listener)
this.socket.on('nft-event', listener);
return this.handleSubscription('nft-event', true, listener);
}
unsubscribeNftEvent() {
this.handleSubscription('nft-event', false);
}
subscribeNftAssetEvent(assetIdentifier, value, listener) {
if (listener)
this.socket.on(`nft-asset-event:${assetIdentifier}+${value}`, listener);
return this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}`, true, listener);
}
unsubscribeNftAssetEvent(assetIdentifier, value) {
this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}`, false);
}
subscribeNftCollectionEvent(assetIdentifier, listener) {
if (listener)
this.socket.on(`nft-collection-event:${assetIdentifier}`, listener);
return this.handleSubscription(`nft-collection-event:${assetIdentifier}`, true, listener);
}
unsubscribeNftCollectionEvent(assetIdentifier) {
this.handleSubscription(`nft-collection-event:${assetIdentifier}`, false);
}
logEvents() {
this.socket.on('connect', () => console.log('socket connected'));
this.socket.on('disconnect', reason => console.warn('disconnected', reason));
this.socket.on('connect_error', error => console.error('connect_error', error));
this.socket.on('block', block => console.log('block', block));
this.socket.on('microblock', microblock => console.log('microblock', microblock));
this.socket.on('mempool', tx => console.log('mempool', tx));
this.socket.on('nft-event', event => console.log('nft-event', event));
}
}
exports.StacksApiSocketClient = StacksApiSocketClient;
//# sourceMappingURL=index.js.map
;